class Rack::Response
Rack::Response provides a convenient interface to create a Rack response.
It allows setting of headers and cookies, and provides useful defaults (an OK response with empty headers and body).
You can use #write to
iteratively generate your response, but note that this is buffered by Rack::Response until you call finish.
finish however can take a block inside which calls to
write are synchronous with the Rack
response.
Your application's call should end returning #finish.
Constants
- CHUNKED
- STATUS_WITH_NO_ENTITY_BODY
Attributes
Public Class Methods
# File lib/rack/response.rb, line 23 def self.[](status, headers, body) self.new(body, status, headers) end
Initialize the response object with the specified body,
status and headers.
If the body is nil, construct an empty response
object with internal buffering.
If the body responds to to_str, assume it's a
string-like object and construct a buffered response object containing
using that string as the initial contents of the buffer.
Otherwise it is expected body conforms to the normal
requirements of a Rack response body, typically
implementing one of each (enumerable body) or
call (streaming body).
The status defaults to 200 which is the “OK” HTTP
status code. You can provide any other valid status code.
The headers must be a Hash of key-value header
pairs which conform to the Rack specification
for response headers. The key must be a String instance and
the value can be either a String or Array
instance.
# File lib/rack/response.rb, line 53 def initialize(body = nil, status = 200, headers = {}) @status = status.to_i unless headers.is_a?(Hash) raise ArgumentError, "Headers must be a Hash!" end @headers = Headers.new # Convert headers input to a plain hash with lowercase keys. headers.each do |k, v| @headers[k] = v end @writer = self.method(:append) @block = nil # Keep track of whether we have expanded the user supplied body. if body.nil? @body = [] @buffered = true # Body is unspecified - it may be a buffered response, or it may be a HEAD response. @length = nil elsif body.respond_to?(:to_str) @body = [body] @buffered = true @length = body.to_str.bytesize else @body = body @buffered = nil # undetermined as of yet. @length = nil end yield self if block_given? end
Public Instance Methods
# File lib/rack/response.rb, line 94 def chunked? CHUNKED == get_header(TRANSFER_ENCODING) end
# File lib/rack/response.rb, line 151 def close @body.close if @body.respond_to?(:close) end
# File lib/rack/response.rb, line 171 def delete_header(key) raise ArgumentError unless key.is_a?(String) @headers.delete key end
# File lib/rack/response.rb, line 129 def each(&callback) @body.each(&callback) @buffered = true if @block @writer = callback @block.call(self) end end
# File lib/rack/response.rb, line 155 def empty? @block == nil && @body.empty? end
Generate a response array consistent with the requirements of the SPEC. @return [Array] a 3-tuple suitable of `[status, headers, body]` which is suitable to be returned from the middleware `#call(env)` method.
# File lib/rack/response.rb, line 106 def finish(&block) if no_entity_body? delete_header CONTENT_TYPE delete_header CONTENT_LENGTH close return [@status, @headers, []] else if block_given? # We don't add the content-length here as the user has provided a block that can #write additional chunks to the body. @block = block return [@status, @headers, self] else # If we know the length of the body, set the content-length header... except if we are chunked? which is a legacy special case where the body might already be encoded and thus the actual encoded body length and the content-length are likely to be different. if @length && !chunked? @headers[CONTENT_LENGTH] = @length.to_s end return [@status, @headers, @body] end end end
# File lib/rack/response.rb, line 163 def get_header(key) raise ArgumentError unless key.is_a?(String) @headers[key] end
# File lib/rack/response.rb, line 159 def has_header?(key) raise ArgumentError unless key.is_a?(String) @headers.key?(key) end
# File lib/rack/response.rb, line 98 def no_entity_body? # The response body is an enumerable body and it is not allowed to have an entity body. @body.respond_to?(:each) && STATUS_WITH_NO_ENTITY_BODY[@status] end
# File lib/rack/response.rb, line 89 def redirect(target, status = 302) self.status = status self.location = target end
# File lib/rack/response.rb, line 167 def set_header(key, value) raise ArgumentError unless key.is_a?(String) @headers[key] = value end