Class: ActionDispatch::Response

Inherits:
Object
  • Object
show all
Includes:
Http::Cache::Response, Http::FilterRedirect, MonitorMixin, Rack::Response::Helpers
Defined in:
lib/action_dispatch/http/response.rb

Overview

Action Dispatch Response

Represents an HTTP response generated by a controller action. Use it to retrieve the current state of the response, or customize the response. It can either represent a real HTTP response (i.e. one that is meant to be sent back to the web browser) or a TestResponse (i.e. one that is generated from integration tests).

The Response object for the current request is exposed on controllers as ActionController::Metal#response. ActionController::Metal also provides a few additional methods that delegate to attributes of the Response such as ActionController::Metal#headers.

Integration tests will likely also want to inspect responses in more detail. Methods such as Integration::RequestHelpers#get and Integration::RequestHelpers#post return instances of TestResponse (which inherits from Response) for this purpose.

For example, the following demo integration test prints the body of the controller response to the console:

class DemoControllerTest < ActionDispatch::IntegrationTest
  def test_print_root_path_to_console
    get('/')
    puts response.body
  end
end

Defined Under Namespace

Classes: Buffer, ContentTypeHeader, FileBody, RackBody

Constant Summary collapse

Header =

To be deprecated:

Headers
CONTENT_TYPE =
"Content-Type"
"Set-Cookie"
NO_CONTENT_CODES =
[100, 101, 102, 103, 204, 205, 304]

Constants included from Http::FilterRedirect

Http::FilterRedirect::FILTERED

Instance Attribute Summary collapse

Attributes included from Http::Cache::Response

#cache_control

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Http::Cache::Response

#date, #date=, #date?, #etag=, #etag?, #last_modified, #last_modified=, #last_modified?, #strong_etag=, #strong_etag?, #weak_etag=, #weak_etag?

Methods included from Http::FilterRedirect

#filtered_location

Constructor Details

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

Returns a new instance of Response.

Yields:

  • (_self)

Yield Parameters:



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/action_dispatch/http/response.rb', line 198

def initialize(status = 200, headers = nil, body = [])
  super()

  @headers = Headers.new

  headers&.each do |key, value|
    @headers[key] = value
  end

  self.body, self.status = body, status

  @cv           = new_cond
  @committed    = false
  @sending      = false
  @sent         = false

  prepare_cache_control!

  yield self if block_given?
end

Instance Attribute Details

#headers ⇒ Object (readonly) Also known as: header

The headers for the response.

header["Content-Type"] # => "text/plain"
header["Content-Type"] = "application/json"
header["Content-Type"] # => "application/json"

Also aliased as headers.

headers["Content-Type"] # => "text/plain"
headers["Content-Type"] = "application/json"
headers["Content-Type"] # => "application/json"

Also aliased as header for compatibility.



85
86
87
# File 'lib/action_dispatch/http/response.rb', line 85

def headers
  @headers
end

#request ⇒ Object

The request that the response is responding to.



67
68
69
# File 'lib/action_dispatch/http/response.rb', line 67

def request
  @request
end

#status ⇒ Object

The HTTP status code.



70
71
72
# File 'lib/action_dispatch/http/response.rb', line 70

def status
  @status
end

#stream ⇒ Object (readonly)

The underlying body, as a streamable object.



196
197
198
# File 'lib/action_dispatch/http/response.rb', line 196

def stream
  @stream
end

Class Method Details

.create(status = 200, headers = {}, body = [], default_headers: self.default_headers) ⇒ Object



186
187
188
189
# File 'lib/action_dispatch/http/response.rb', line 186

def self.create(status = 200, headers = {}, body = [], default_headers: self.default_headers)
  headers = merge_default_headers(headers, default_headers)
  new status, headers, body
end

.merge_default_headers(original, default) ⇒ Object



191
192
193
# File 'lib/action_dispatch/http/response.rb', line 191

def self.merge_default_headers(original, default)
  default.respond_to?(:merge) ? default.merge(original) : original
end

Instance Method Details

#abort ⇒ Object



447
448
449
450
451
452
453
454
455
# File 'lib/action_dispatch/http/response.rb', line 447

def abort
  if stream.respond_to?(:abort)
    stream.abort
  elsif stream.respond_to?(:close)
    # `stream.close` should really be reserved for a close from the other direction,
    # but we must fall back to it for compatibility.
    stream.close
  end
end

#await_commit ⇒ Object



224
225
226
227
228
# File 'lib/action_dispatch/http/response.rb', line 224

def await_commit
  synchronize do
    @cv.wait_until { @committed }
  end
end

#await_sent ⇒ Object



230
231
232
# File 'lib/action_dispatch/http/response.rb', line 230

def await_sent
  synchronize { @cv.wait_until { @sent } }
end

#body ⇒ Object

Returns the content of the response as a string. This contains the contents of any calls to render.



370
371
372
373
374
375
376
377
378
# File 'lib/action_dispatch/http/response.rb', line 370

def body
  if @stream.respond_to?(:to_ary)
    @stream.to_ary.join
  elsif @stream.respond_to?(:body)
    @stream.body
  else
    @stream
  end
end

#body=(body) ⇒ Object

Allows you to manually set or override the response body.



385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/action_dispatch/http/response.rb', line 385

def body=(body)
  # Prevent ActionController::Metal::Live::Response from committing the response prematurely.
  synchronize do
    if body.respond_to?(:to_str)
      @stream = build_buffer(self, [body])
    elsif body.respond_to?(:to_path)
      @stream = body
    elsif body.respond_to?(:to_ary)
      @stream = build_buffer(self, body)
    else
      @stream = body
    end
  end
end

#body_parts ⇒ Object



434
435
436
437
438
# File 'lib/action_dispatch/http/response.rb', line 434

def body_parts
  parts = []
  @stream.each { |x| parts << x }
  parts
end

#charset ⇒ Object

The charset of the response. HTML wants to know the encoding of the content you're giving them, so we need to send that along.



340
341
342
343
# File 'lib/action_dispatch/http/response.rb', line 340

def charset
  header_info = parsed_content_type_header
  header_info.charset || self.class.default_charset
end

#charset=(charset) ⇒ Object

Sets the HTTP character set. In case of nil parameter it sets the charset to default_charset.

response.charset = 'utf-16' # => 'utf-16'
response.charset = nil      # => 'utf-8'


329
330
331
332
333
334
335
336
# File 'lib/action_dispatch/http/response.rb', line 329

def charset=(charset)
  content_type = parsed_content_type_header.mime_type
  if false == charset
    set_content_type content_type, nil
  else
    set_content_type content_type, charset || self.class.default_charset
  end
end

#close ⇒ Object



443
444
445
# File 'lib/action_dispatch/http/response.rb', line 443

def close
  stream.close if stream.respond_to?(:close)
end

#code ⇒ Object

Returns a string to ensure compatibility with Net::HTTPResponse.



351
352
353
# File 'lib/action_dispatch/http/response.rb', line 351

def code
  @status.to_s
end

#commit! ⇒ Object



234
235
236
237
238
239
240
# File 'lib/action_dispatch/http/response.rb', line 234

def commit!
  synchronize do
    before_committed
    @committed = true
    @cv.broadcast
  end
end

#committed? ⇒ Boolean

Returns:

  • (Boolean)


258
# File 'lib/action_dispatch/http/response.rb', line 258

def committed?; synchronize { @committed }; end

#content_type ⇒ Object

Content type of response.



309
310
311
# File 'lib/action_dispatch/http/response.rb', line 309

def content_type
  super.presence
end

#content_type=(content_type) ⇒ Object

Sets the HTTP response's content MIME type. For example, in the controller you could write this:

response.content_type = "text/html"

This method also accepts a symbol with the extension of the MIME type:

response.content_type = :html

If a character set has been defined for this response (see #charset=) then the character set information will also be included in the content type information.



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/action_dispatch/http/response.rb', line 290

def content_type=(content_type)
  case content_type
  when NilClass
    return
  when Symbol
    mime_type = Mime[content_type]
    raise ArgumentError, "Unknown MIME type #{content_type}" unless mime_type
    new_header_info = ContentTypeHeader.new(mime_type.to_s)
  else
    new_header_info = parse_content_type(content_type.to_s)
  end

  prev_header_info = parsed_content_type_header
  charset = new_header_info.charset || prev_header_info.charset
  charset ||= self.class.default_charset unless prev_header_info.mime_type
  set_content_type new_header_info.mime_type, charset
end

#cookies ⇒ Object

Returns the response cookies, converted to a Hash of (name => value) pairs

assert_equal 'AuthorOfNewPage', r.cookies['author']


470
471
472
473
474
475
476
477
478
479
480
481
482
# File 'lib/action_dispatch/http/response.rb', line 470

def cookies
  cookies = {}
  if header = get_header(SET_COOKIE)
    header = header.split("\n") if header.respond_to?(:to_str)
    header.each do |cookie|
      if pair = cookie.split(";").first
        key, value = pair.split("=").map { |v| Rack::Utils.unescape(v) }
        cookies[key] = value
      end
    end
  end
  cookies
end

#delete_header(key) ⇒ Object



222
# File 'lib/action_dispatch/http/response.rb', line 222

def delete_header(key); @headers.delete key; end

#each(&block) ⇒ Object



91
92
93
94
95
96
# File 'lib/action_dispatch/http/response.rb', line 91

def each(&block)
  sending!
  x = @stream.each(&block)
  sent!
  x
end

#get_header(key) ⇒ Object



220
# File 'lib/action_dispatch/http/response.rb', line 220

def get_header(key);    @headers[key];       end

#has_header?(key) ⇒ Boolean

Returns:

  • (Boolean)


219
# File 'lib/action_dispatch/http/response.rb', line 219

def has_header?(key);   @headers.key? key;   end

#media_type ⇒ Object

Media type of response.



314
315
316
# File 'lib/action_dispatch/http/response.rb', line 314

def media_type
  parsed_content_type_header.mime_type
end

#message ⇒ Object Also known as: status_message

Returns the corresponding message for the current HTTP status code:

response.status = 200
response.message # => "OK"

response.status = 404
response.message # => "Not Found"


363
364
365
# File 'lib/action_dispatch/http/response.rb', line 363

def message
  Rack::Utils::HTTP_STATUS_CODES[@status]
end

#rack_status_code(status) ⇒ Object

:nodoc:



51
52
53
54
# File 'lib/action_dispatch/http/response.rb', line 51

def rack_status_code(status) # :nodoc:
  status = :unprocessable_content if status == :unprocessable_entity
  Rack::Utils.status_code(status)
end

#reset_body! ⇒ Object



430
431
432
# File 'lib/action_dispatch/http/response.rb', line 430

def reset_body!
  @stream = build_buffer(self, [])
end

#response_code ⇒ Object

The response code of the request.



346
347
348
# File 'lib/action_dispatch/http/response.rb', line 346

def response_code
  @status
end

#send_file(path) ⇒ Object

Send the file stored at path as the response body.



425
426
427
428
# File 'lib/action_dispatch/http/response.rb', line 425

def send_file(path)
  commit!
  @stream = FileBody.new(path)
end

#sending! ⇒ Object



242
243
244
245
246
247
248
# File 'lib/action_dispatch/http/response.rb', line 242

def sending!
  synchronize do
    before_sending
    @sending = true
    @cv.broadcast
  end
end

#sending? ⇒ Boolean

Returns:

  • (Boolean)


257
# File 'lib/action_dispatch/http/response.rb', line 257

def sending?;   synchronize { @sending };   end

#sending_file=(v) ⇒ Object



318
319
320
321
322
# File 'lib/action_dispatch/http/response.rb', line 318

def sending_file=(v)
  if true == v
    self.charset = false
  end
end

#sent! ⇒ Object



250
251
252
253
254
255
# File 'lib/action_dispatch/http/response.rb', line 250

def sent!
  synchronize do
    @sent = true
    @cv.broadcast
  end
end

#sent? ⇒ Boolean

Returns:

  • (Boolean)


259
# File 'lib/action_dispatch/http/response.rb', line 259

def sent?;      synchronize { @sent };      end

#set_header(key, v) ⇒ Object



221
# File 'lib/action_dispatch/http/response.rb', line 221

def set_header(key, v); @headers[key] = v;   end

#to_a ⇒ Object Also known as: prepare!

Turns the Response into a Rack-compatible array of the status, headers, and body. Allows explicit splatting:

status, headers, body = *response


461
462
463
464
# File 'lib/action_dispatch/http/response.rb', line 461

def to_a
  commit!
  rack_response @status, @headers.to_hash
end

#write(string) ⇒ Object



380
381
382
# File 'lib/action_dispatch/http/response.rb', line 380

def write(string)
  @stream.write string
end