From 33e53751e6fedf7106dfefe074101657ad9645da Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 29 Oct 2024 10:23:36 +1300 Subject: [PATCH] Add support for Rack 3.1 optional input. --- .github/workflows/test.yaml | 3 +- gems/{rack-v3.rb => rack-v30.rb} | 2 +- gems/rack-v31.rb | 8 ++++ lib/protocol/rack/adapter.rb | 10 +++-- lib/protocol/rack/adapter/rack31.rb | 70 +++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 6 deletions(-) rename gems/{rack-v3.rb => rack-v30.rb} (85%) create mode 100644 gems/rack-v31.rb create mode 100644 lib/protocol/rack/adapter/rack31.rb diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 46062e0..15b699a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -30,7 +30,8 @@ jobs: gemfile: - gems/rack-v1.rb - gems/rack-v2.rb - - gems/rack-v3.rb + - gems/rack-v30.rb + - gems/rack-v31.rb experimental: [false] diff --git a/gems/rack-v3.rb b/gems/rack-v30.rb similarity index 85% rename from gems/rack-v3.rb rename to gems/rack-v30.rb index 5c7d5cc..05fcd9d 100644 --- a/gems/rack-v3.rb +++ b/gems/rack-v30.rb @@ -5,4 +5,4 @@ eval_gemfile("gems.rb") -gem "rack", "~> 3.0" +gem "rack", "~> 3.0.0" diff --git a/gems/rack-v31.rb b/gems/rack-v31.rb new file mode 100644 index 0000000..528a797 --- /dev/null +++ b/gems/rack-v31.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Released under the MIT License. +# Copyright, 2022-2023, by Samuel Williams. + +eval_gemfile("gems.rb") + +gem "rack", "~> 3.1.0" diff --git a/lib/protocol/rack/adapter.rb b/lib/protocol/rack/adapter.rb index 59ff856..944bc2c 100644 --- a/lib/protocol/rack/adapter.rb +++ b/lib/protocol/rack/adapter.rb @@ -5,15 +5,17 @@ require "rack" -require_relative "adapter/rack2" -require_relative "adapter/rack3" - module Protocol module Rack module Adapter - if ::Rack.release >= "3" + if ::Rack.release >= "3.1" + require_relative "adapter/rack31" + IMPLEMENTATION = Rack31 + elsif ::Rack.release >= "3" + require_relative "adapter/rack3" IMPLEMENTATION = Rack3 else + require_relative "adapter/rack2" IMPLEMENTATION = Rack2 end diff --git a/lib/protocol/rack/adapter/rack31.rb b/lib/protocol/rack/adapter/rack31.rb new file mode 100644 index 0000000..108fe41 --- /dev/null +++ b/lib/protocol/rack/adapter/rack31.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +# Released under the MIT License. +# Copyright, 2022-2024, by Samuel Williams. + +require "console" + +require_relative "rack3" + +module Protocol + module Rack + module Adapter + class Rack31 < Rack3 + def make_environment(request) + request_path, query_string = request.path.split("?", 2) + server_name, server_port = (request.authority || "").split(":", 2) + + env = { + PROTOCOL_HTTP_REQUEST => request, + + RACK_ERRORS => $stderr, + RACK_LOGGER => self.logger, + + # The request protocol, either from the upgrade header or the HTTP/2 pseudo header of the same name. + RACK_PROTOCOL => request.protocol, + + # The response finished callbacks: + RACK_RESPONSE_FINISHED => [], + + # The HTTP request method, such as “GET” or “POST”. This cannot ever be an empty string, and so is always required. + CGI::REQUEST_METHOD => request.method, + + # The initial portion of the request URL's “path” that corresponds to the application object, so that the application knows its virtual “location”. This may be an empty string, if the application corresponds to the “root” of the server. + CGI::SCRIPT_NAME => "", + + # The remainder of the request URL's “path”, designating the virtual “location” of the request's target within the application. This may be an empty string, if the request URL targets the application root and does not have a trailing slash. This value may be percent-encoded when originating from a URL. + CGI::PATH_INFO => request_path, + CGI::REQUEST_PATH => request_path, + CGI::REQUEST_URI => request.path, + + # The portion of the request URL that follows the ?, if any. May be empty, but is always required! + CGI::QUERY_STRING => query_string || "", + + # The server protocol (e.g. HTTP/1.1): + CGI::SERVER_PROTOCOL => request.version, + + # The request scheme: + RACK_URL_SCHEME => request.scheme, + + # I'm not sure what sane defaults should be here: + CGI::SERVER_NAME => server_name, + CGI::SERVER_PORT => server_port, + } + + if body = request.body + if body.empty? + body.close + else + env[RACK_INPUT] = Input.new(body) + end + end + + self.unwrap_request(request, env) + + return env + end + end + end + end +end