lib/falcon/adapters/rack.rb in falcon-0.36.4 vs lib/falcon/adapters/rack.rb in falcon-0.36.5
- old
+ new
@@ -29,53 +29,66 @@
require 'async/logger'
module Falcon
module Adapters
class Rack
- # CGI keys (https://tools.ietf.org/html/rfc3875#section-4.1)
- HTTP_HOST = 'HTTP_HOST'.freeze
- PATH_INFO = 'PATH_INFO'.freeze
- REQUEST_METHOD = 'REQUEST_METHOD'.freeze
- REQUEST_PATH = 'REQUEST_PATH'.freeze
- REQUEST_URI = 'REQUEST_URI'.freeze
- SCRIPT_NAME = 'SCRIPT_NAME'.freeze
- QUERY_STRING = 'QUERY_STRING'.freeze
- SERVER_PROTOCOL = 'SERVER_PROTOCOL'.freeze
- SERVER_NAME = 'SERVER_NAME'.freeze
- SERVER_PORT = 'SERVER_PORT'.freeze
- REMOTE_ADDR = 'REMOTE_ADDR'.freeze
- CONTENT_TYPE = 'CONTENT_TYPE'.freeze
- CONTENT_LENGTH = 'CONTENT_LENGTH'.freeze
+ # CGI keys <https://tools.ietf.org/html/rfc3875#section-4.1>:
- # Rack environment variables
- RACK_VERSION = 'rack.version'.freeze
- RACK_ERRORS = 'rack.errors'.freeze
- RACK_LOGGER = 'rack.logger'.freeze
- RACK_INPUT = 'rack.input'.freeze
- RACK_MULTITHREAD = 'rack.multithread'.freeze
- RACK_MULTIPROCESS = 'rack.multiprocess'.freeze
- RACK_RUNONCE = 'rack.run_once'.freeze
- RACK_URL_SCHEME = 'rack.url_scheme'.freeze
- RACK_HIJACK = 'rack.hijack'.freeze
- RACK_IS_HIJACK = 'rack.hijack?'.freeze
- RACK_HIJACK_IO = 'rack.hijack_io'.freeze
- RACK_EARLY_HINTS = "rack.early_hints".freeze
+ HTTP_HOST = 'HTTP_HOST'
+ PATH_INFO = 'PATH_INFO'
+ REQUEST_METHOD = 'REQUEST_METHOD'
+ REQUEST_PATH = 'REQUEST_PATH'
+ REQUEST_URI = 'REQUEST_URI'
+ SCRIPT_NAME = 'SCRIPT_NAME'
+ QUERY_STRING = 'QUERY_STRING'
+ SERVER_PROTOCOL = 'SERVER_PROTOCOL'
+ SERVER_NAME = 'SERVER_NAME'
+ SERVER_PORT = 'SERVER_PORT'
+ REMOTE_ADDR = 'REMOTE_ADDR'
+ CONTENT_TYPE = 'CONTENT_TYPE'
+ CONTENT_LENGTH = 'CONTENT_LENGTH'
- ASYNC_HTTP_REQUEST = "async.http.request".freeze
+ # Rack environment variables:
- # Header constants
- HTTP_X_FORWARDED_PROTO = 'HTTP_X_FORWARDED_PROTO'.freeze
+ RACK_VERSION = 'rack.version'
+ RACK_ERRORS = 'rack.errors'
+ RACK_LOGGER = 'rack.logger'
+ RACK_INPUT = 'rack.input'
+ RACK_MULTITHREAD = 'rack.multithread'
+ RACK_MULTIPROCESS = 'rack.multiprocess'
+ RACK_RUNONCE = 'rack.run_once'
+ RACK_URL_SCHEME = 'rack.url_scheme'
+ RACK_HIJACK = 'rack.hijack'
+ RACK_IS_HIJACK = 'rack.hijack?'
+ RACK_HIJACK_IO = 'rack.hijack_io'
+ RACK_EARLY_HINTS = "rack.early_hints"
+ # Async::HTTP specific metadata:
+
+ ASYNC_HTTP_REQUEST = "async.http.request"
+
+ # Header constants:
+
+ HTTP_X_FORWARDED_PROTO = 'HTTP_X_FORWARDED_PROTO'
+
+ # Initialize the rack adaptor middleware.
+ # @parameter app [Object] The rack middleware.
+ # @parameter logger [Console::Logger] The logger to use.
def initialize(app, logger = Async.logger)
@app = app
raise ArgumentError, "App must be callable!" unless @app.respond_to?(:call)
@logger = logger
end
- # Rack separates multiple headers with the same key, into a single field with multiple "lines".
+ # Unwrap raw HTTP headers into the CGI-style expected by Rack middleware.
+ #
+ # Rack separates multiple headers with the same key, into a single field with multiple lines.
+ #
+ # @parameter headers [Protocol::HTTP::Headers] The raw HTTP request headers.
+ # @parameter env [Hash] The rack request `env`.
def unwrap_headers(headers, env)
headers.each do |key, value|
http_key = "HTTP_#{key.upcase.tr('-', '_')}"
if current_value = env[http_key]
@@ -84,11 +97,19 @@
env[http_key] = value
end
end
end
- # Process the incoming request into a valid rack env.
+ # Process the incoming request into a valid rack `env`.
+ #
+ # - Set the `env['CONTENT_TYPE']` and `env['CONTENT_LENGTH']` based on the incoming request body.
+ # - Set the `env['HTTP_HOST']` header to the request authority.
+ # - Set the `env['HTTP_X_FORWARDED_PROTO']` header to the request scheme.
+ # - Set `env['REMOTE_ADDR']` to the request remote adress.
+ #
+ # @parameter request [Protocol::HTTP::Request] The incoming request.
+ # @parameter env [Hash] The rack `env`.
def unwrap_request(request, env)
if content_type = request.headers.delete('content-type')
env[CONTENT_TYPE] = content_type
end
@@ -111,10 +132,13 @@
if remote_address = request.remote_address
env[REMOTE_ADDR] = remote_address.ip_address if remote_address.ip?
end
end
+ # Build a rack `env` from the incoming request and apply it to the rack middleware.
+ #
+ # @parameter request [Protocol::HTTP::Request] The incoming request.
def call(request)
request_path, query_string = request.path.split('?', 2)
server_name, server_port = (request.authority || '').split(':', 2)
env = {
@@ -192,9 +216,12 @@
@logger.error(self) {exception}
return failure_response(exception)
end
+ # Generate a suitable response for the given exception.
+ # @parameter exception [Exception]
+ # @returns [Protocol::HTTP::Response]
def failure_response(exception)
Protocol::HTTP::Response.for_exception(exception)
end
end
end