class Falcon::Adapters::Response

A wrapper for a `Rack` response.

A Rack response consisting of `[status, headers, body]` includes various rack-specific elements, including:

This wrapper takes those issues into account and adapts the rack response tuple into a {Protocol::HTTP::Response}.

Constants

IGNORE_HEADERS

Public Class Methods

new(status, headers, body, protocol = nil) click to toggle source

Initialize the response wrapper. @parameter status [Integer] The response status. @parameter headers [Protocol::HTTP::Headers] The response headers. @parameter body [Protocol::HTTP::Body] The response body. @parameter protocol [String] The response protocol for upgraded requests.

Calls superclass method
# File lib/falcon/adapters/response.rb, line 108
def initialize(status, headers, body, protocol = nil)
        super(nil, status, headers, body, protocol)
end
wrap(status, headers, body, request = nil) click to toggle source

Wrap a rack response. @parameter status [Integer] The rack response status. @parameter headers [Duck(:each)] The rack response headers. @parameter body [Duck(:each, :close) | Nil] The rack response body. @parameter request [Protocol::HTTP::Request] The original request.

# File lib/falcon/adapters/response.rb, line 72
def self.wrap(status, headers, body, request = nil)
        headers, meta = wrap_headers(headers)
        
        if block = meta['rack.hijack']
                body = Async::HTTP::Body::Hijack.wrap(request, &block)
        else
                ignored = headers.extract(IGNORE_HEADERS)
                
                unless ignored.empty?
                        Console.logger.warn("Ignoring protocol-level headers: #{ignored.inspect}")
                end
                
                body = Output.wrap(status, headers, body)
        end
        
        if request&.head?
                # I thought about doing this in Output.wrap, but decided the semantics are too tricky. Specifically, the various ways a rack response body can be wrapped, and the need to invoke #close at the right point.
                body = ::Protocol::HTTP::Body::Head.for(body)
        end
        
        protocol = meta['rack.protocol']
        
        # https://tools.ietf.org/html/rfc7231#section-7.4.2
        # headers.add('server', "falcon/#{Falcon::VERSION}")
        
        # https://tools.ietf.org/html/rfc7231#section-7.1.1.2
        # headers.add('date', Time.now.httpdate)
        
        return self.new(status, headers, body, protocol)
end
wrap_headers(fields) click to toggle source

Process the rack response headers into into a {Protocol::HTTP::Headers} instance, along with any extra `rack.` metadata. @returns [Tuple(Protocol::HTTP::Headers, Hash)]

# File lib/falcon/adapters/response.rb, line 48
def self.wrap_headers(fields)
        headers = ::Protocol::HTTP::Headers.new
        meta = {}
        
        fields.each do |key, value|
                key = key.downcase
                
                if key.start_with?('rack.')
                        meta[key] = value
                else
                        value.to_s.split("\n").each do |part|
                                headers.add(key, part)
                        end
                end
        end
        
        return headers, meta
end