123456789_123456789_123456789_123456789_123456789_

Class: Rack::Response

Relationships & Source Files
Namespace Children
Modules:
Classes:
Raw
Extension / Inclusion / Inheritance Descendants
Subclasses:
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, Helpers
Inherits: Object
Defined in: lib/rack/response.rb

Overview

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 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.

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Helpers - Included

#add_header

Add a header that may have multiple values.

#cache!

Specify that the content should be cached.

#content_length, #delete_cookie,
#do_not_cache!

Specifies that the content shouldn’t be cached.

#include?, #media_type, #media_type_params, #set_cookie

Constructor Details

.new(body = nil, status = 200, headers = {}) {|_self| ... } ⇒ Response Also known as: .[]

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.

Yields:

  • (_self)

Yield Parameters:

  • _self (Response)

    the object that the method was called on

[ GitHub ]

  
# File 'lib/rack/response.rb', line 54

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

Class Method Details

.[](status, headers, body)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 24

def self.[](status, headers, body)
  self.new(body, status, headers)
end

Instance Attribute Details

#body (rw)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 31

attr_accessor :length, :status, :body

#chunked?Boolean (readonly)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 95

def chunked?
  CHUNKED == get_header(TRANSFER_ENCODING)
end

#empty?Boolean (readonly)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 156

def empty?
  @block == nil && @body.empty?
end

#headers (readonly)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 32

attr_reader :headers

#length (rw)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 31

attr_accessor :length, :status, :body

#no_entity_body?Boolean (readonly)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 99

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

#status (rw)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 31

attr_accessor :length, :status, :body

Instance Method Details

#[](key)

Alias for #get_header.

[ GitHub ]

  
# File 'lib/rack/response.rb', line 177

alias :[] :get_header

#[]=(key, value)

Alias for #set_header.

[ GitHub ]

  
# File 'lib/rack/response.rb', line 178

alias :[]= :set_header

#close

[ GitHub ]

  
# File 'lib/rack/response.rb', line 152

def close
  @body.close if @body.respond_to?(:close)
end

#delete_header(key)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/rack/response.rb', line 172

def delete_header(key)
  raise ArgumentError unless key.is_a?(String)
  @headers.delete key
end

#each(&callback)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 130

def each(&callback)
  @body.each(&callback)
  @buffered = true

  if @block
    @writer = callback
    @block.call(self)
  end
end

#finish(&block) ⇒ Array Also known as: #to_a

Generate a response array consistent with the requirements of the SPEC. which is suitable to be returned from the middleware #call(env) method.

Returns:

  • (Array)

    a 3-tuple suitable of [status, headers, body]

[ GitHub ]

  
# File 'lib/rack/response.rb', line 107

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

#get_header(key) Also known as: #[]

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/rack/response.rb', line 164

def get_header(key)
  raise ArgumentError unless key.is_a?(String)
  @headers[key]
end

#has_header?(key) ⇒ Boolean

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/rack/response.rb', line 160

def has_header?(key)
  raise ArgumentError unless key.is_a?(String)
  @headers.key?(key)
end

#redirect(target, status = 302)

[ GitHub ]

  
# File 'lib/rack/response.rb', line 90

def redirect(target, status = 302)
  self.status = status
  self.location = target
end

#set_header(key, value) Also known as: #[]=

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/rack/response.rb', line 168

def set_header(key, value)
  raise ArgumentError unless key.is_a?(String)
  @headers[key] = value
end

#to_a(&block)

Alias for #finish.

[ GitHub ]

  
# File 'lib/rack/response.rb', line 128

alias to_a finish           # For *response

#write(chunk)

Append a chunk to the response body.

Converts the response into a buffered response if it wasn’t already.

NOTE: Do not mix #write and direct #body access!

[ GitHub ]

  
# File 'lib/rack/response.rb', line 146

def write(chunk)
  buffered_body!

  @writer.call(chunk.to_s)
end