Class: Rack::Response

Inherits:
Object show all
Includes:
Helpers
Defined in:
vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb

Overview

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 Response#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 Response#finish.

Direct Known Subclasses

MockResponse

Defined Under Namespace

Modules: Helpers Classes: Raw

Constant Summary collapse

CHUNKED =
'chunked'
STATUS_WITH_NO_ENTITY_BODY =
Utils::STATUS_WITH_NO_ENTITY_BODY

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#accepted?, #add_header, #append, #bad_request?, #buffered_body!, #cache!, #cache_control, #cache_control=, #client_error?, #content_length, #content_type, #content_type=, #created?, #delete_cookie, #do_not_cache!, #etag, #etag=, #forbidden?, #include?, #informational?, #invalid?, #location, #location=, #media_type, #media_type_params, #method_not_allowed?, #moved_permanently?, #no_content?, #not_acceptable?, #not_found?, #ok?, #precondition_failed?, #redirect?, #redirection?, #request_timeout?, #server_error?, #set_cookie, #set_cookie_header, #set_cookie_header=, #successful?, #unauthorized?, #unprocessable?

Constructor Details

#initialize(body = nil, status = 200, headers = {}) {|_self| ... } ⇒ Response

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:



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/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

Instance Attribute Details

#bodyObject

Returns the value of attribute body.



31
32
33
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 31

def body
  @body
end

#headersObject (readonly)

Returns the value of attribute headers.



32
33
34
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 32

def headers
  @headers
end

#lengthObject

Returns the value of attribute length.



31
32
33
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 31

def length
  @length
end

#statusObject

Returns the value of attribute status.



31
32
33
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 31

def status
  @status
end

Class Method Details

.[](status, headers, body) ⇒ Object



24
25
26
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 24

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

Instance Method Details

#chunked?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 95

def chunked?
  CHUNKED == get_header(TRANSFER_ENCODING)
end

#closeObject



152
153
154
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 152

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

#delete_header(key) ⇒ Object

Raises:

  • (ArgumentError)


172
173
174
175
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 172

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

#each(&callback) ⇒ Object



130
131
132
133
134
135
136
137
138
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 130

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

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

#empty?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 156

def empty?
  @block == nil && @body.empty?
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]



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/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) ⇒ Object Also known as: []

Raises:

  • (ArgumentError)


164
165
166
167
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 164

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

#has_header?(key) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


160
161
162
163
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 160

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

#no_entity_body?Boolean

Returns:

  • (Boolean)


99
100
101
102
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/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

#redirect(target, status = 302) ⇒ Object



90
91
92
93
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 90

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

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

Raises:

  • (ArgumentError)


168
169
170
171
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 168

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

#write(chunk) ⇒ Object

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!



146
147
148
149
150
# File 'vendor/bundler/ruby/3.4.0/bundler/gems/rack-40d68f842b5f/lib/rack/response.rb', line 146

def write(chunk)
  buffered_body!

  @writer.call(chunk.to_s)
end