class Rack::Response
Your application’s call
should end returning Response#finish.write
are synchronous with the Rack response.finish
. finish
however can take a block inside which calls to
but note that this is buffered by Rack::Response until you call
You can use Response#write to iteratively generate your response,
defaults (an OK response with empty headers and body).
It allows setting of headers and cookies, and provides useful
response.
Rack::Response provides a convenient interface to create a Rack
def self.[](status, headers, body)
def self.[](status, headers, body) self.new(body, status, headers) end
def chunked?
def chunked? CHUNKED == get_header(TRANSFER_ENCODING) end
def close
def close @body.close if @body.respond_to?(:close) end
def delete_header(key)
def delete_header(key) raise ArgumentError unless key.is_a?(String) @headers.delete key end
def each(&callback)
def each(&callback) @body.each(&callback) @buffered = true if @block @writer = callback @block.call(self) end end
def empty?
def empty? @block == nil && @body.empty? end
def finish(&block)
-
(Array)
- a 3-tuple suitable of `[status, headers, body]`
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
def get_header(key)
def get_header(key) raise ArgumentError unless key.is_a?(String) @headers[key] end
def has_header?(key)
def has_header?(key) raise ArgumentError unless key.is_a?(String) @headers.key?(key) end
def initialize(body = nil, status = 200, headers = {})
the Rack specification for response headers. The key must be a +String+
The +headers+ must be a +Hash+ of key-value header pairs which conform to
can provide any other valid status code.
The +status+ defaults to +200+ which is the "OK" HTTP status code. You
body) or +call+ (streaming body).
Rack response body, typically implementing one of +each+ (enumerable
Otherwise it is expected +body+ conforms to the normal requirements of a
initial contents of the buffer.
construct a buffered response object containing using that string as the
If the +body+ responds to +to_str+, assume it's a string-like object and
buffering.
If the +body+ is +nil+, construct an empty response object with internal
and +headers+.
Initialize the response object with the specified +body+, +status+
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
def no_entity_body?
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
def redirect(target, status = 302)
def redirect(target, status = 302) self.status = status self.location = target end
def set_header(key, value)
def set_header(key, value) raise ArgumentError unless key.is_a?(String) @headers[key] = value end
def write(chunk)
NOTE: Do not mix #write and direct #body access!
Converts the response into a buffered response if it wasn't already.
Append a chunk to the response body.
def write(chunk) buffered_body! @writer.call(chunk.to_s) end