Class: ActionDispatch::Response
| Relationships & Source Files | |
| Namespace Children | |
|
Classes:
| |
| Extension / Inclusion / Inheritance Descendants | |
|
Subclasses:
|
|
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
self,
MonitorMixin,
Http::Cache::Response,
Http::FilterRedirect,
Rack::Response::Helpers
|
|
| Inherits: | Object |
| Defined in: | actionpack/lib/action_dispatch/http/response.rb |
Overview
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
Constant Summary
-
AMBIGUOUS_CONTENT_TYPE_PART =
private
# File 'actionpack/lib/action_dispatch/http/response.rb', line 524
Parts of a Content-Type header that the parser could read differently than they were given: parameters, whitespace, quoting.
/[;\s"]/ -
CONTENT_TYPE =
# File 'actionpack/lib/action_dispatch/http/response.rb', line 98"Content-Type" -
CONTENT_TYPE_PARSER =
Internal use only
# File 'actionpack/lib/action_dispatch/http/response.rb', line 490/ \A (?<mime_type>[^;\s]\s*(?:;\s*(?:(?!charset)[^;\s]))*)? (?:;\s*charset=(?<quote>"?)(?<charset>[^;\s]+)\k<quote>)? /x -
Header =
# File 'actionpack/lib/action_dispatch/http/response.rb', line 64
To be deprecated:
Headers -
NO_CONTENT_CODES =
# File 'actionpack/lib/action_dispatch/http/response.rb', line 100[100, 101, 102, 103, 204, 205, 304].freeze
-
NullContentTypeHeader =
# File 'actionpack/lib/action_dispatch/http/response.rb', line 488ContentTypeHeader.new(nil, nil).freeze
-
SET_COOKIE =
# File 'actionpack/lib/action_dispatch/http/response.rb', line 99"Set-Cookie"
Http::FilterRedirect - Included
Http::Cache::Response - Included
DATE, DEFAULT_CACHE_CONTROL, IMMUTABLE, LAST_MODIFIED, MUST_REVALIDATE, MUST_UNDERSTAND, NO_CACHE, NO_STORE, PRIVATE, PUBLIC, SPECIAL_KEYS
Class Attribute Summary
Class Method Summary
- .create(status = 200, headers = {}, body = [], default_headers: self.default_headers)
- .merge_default_headers(original, default)
- .new(status = 200, headers = nil, body = []) {|_self| ... } ⇒ Response constructor
-
.rack_status_code(status)
Internal use only
See additional method definition at line 51.
Instance Attribute Summary
-
#body
rw
Returns the content of the response as a string.
-
#body=(body)
rw
Allows you to manually set or override the response body.
-
#charset
rw
The charset of the response.
-
#charset=(charset)
rw
Sets the HTTP character set.
- #committed? ⇒ Boolean readonly
-
#content_type
rw
Content type of response.
-
#content_type=(content_type)
rw
Sets the HTTP response's content MIME type.
-
#header
readonly
Alias for #headers.
-
#headers
(also: #header)
readonly
The headers for the response.
-
#request
rw
The request that the response is responding to.
- #sending? ⇒ Boolean readonly
- #sending_file=(v) writeonly
- #sent? ⇒ Boolean readonly
-
#status
rw
The HTTP status code.
-
#status=(status)
rw
Sets the HTTP status code.
-
#stream
readonly
The underlying body, as a streamable object.
Http::Cache::Response - Included
| #cache_control, #date, #date=, #date?, | |
| #etag= | This method sets a weak ETag validator on the response so browsers and proxies may cache the response, keyed on the ETag. |
| #etag?, #last_modified, #last_modified=, #last_modified?, #strong_etag=, | |
| #strong_etag? | True if an ETag is set, and it isn't a weak validator (not preceded with |
| #weak_etag=, | |
| #weak_etag? | True if an ETag is set, and it's a weak validator (preceded with |
Http::FilterRedirect - Included
Instance Method Summary
- #[]
- #[]=
-
#_cache_control
Aliasing these off because
AD::Http::Cache::Responsedefines them. - #_cache_control=
- #abort
- #await_commit
- #await_sent
- #body_parts
- #close
-
#code
Returns a string to ensure compatibility with
Net::HTTPResponse. - #commit!
-
#cookies
Returns the response cookies, converted to a
::Hashof (name => value) pairs. - #delete_header(key)
- #each(&block)
- #get_header(key)
- #handle_no_content!
- #has_header?(key) ⇒ Boolean
-
#location
(also: #redirect_url)
Location of the response.
-
#location=(location)
Sets the location of the response.
-
#media_type
Media type of response.
-
#message
(also: #status_message)
Returns the corresponding message for the current HTTP status code:
-
#prepare!
Alias for #to_a.
- #rack_response(status, headers)
-
#redirect_url
Alias for #location.
- #reset_body!
-
#response_code
The response code of the request.
-
#send_file(path)
Send the file stored at
pathas the response body. - #sending!
- #sent!
- #set_header(key, v)
-
#status_message
Alias for #message.
-
#to_a
(also: #prepare!)
Turns the
Responseinto a Rack-compatible array of the status, headers, and body. - #write(string)
- #assign_default_content_type_and_charset! private
- #before_committed private
- #before_sending private
- #build_buffer(response, body) private
-
#parsed_content_type_header
private
Small internal convenience method to get the parsed version of the current content type header.
- #set_content_type(content_type, charset) private
- #parse_content_type(content_type) private Internal use only
Http::Cache::Response - Included
| #cache_control_headers, #cache_control_segments, #generate_strong_etag, #generate_weak_etag, #handle_conditional_get!, #merge_and_normalize_cache_control!, #prepare_cache_control! |
Http::FilterRedirect - Included
Constructor Details
.new(status = 200, headers = nil, body = []) {|_self| ... } ⇒ Response
# File 'actionpack/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 @parsed_content_type = nil @parsed_content_type_raw = nil prepare_cache_control! yield self if block_given? end
Class Attribute Details
.default_charset (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 102
class_attribute :default_charset, default: "utf-8", instance_accessor: false
.default_charset? ⇒ Boolean (rw)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/http/response.rb', line 102
class_attribute :default_charset, default: "utf-8", instance_accessor: false
.default_headers (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 103
class_attribute :default_headers, instance_accessor: false
.default_headers? ⇒ Boolean (rw)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/http/response.rb', line 103
class_attribute :default_headers, instance_accessor: false
Class Method Details
.create(status = 200, headers = {}, body = [], default_headers: self.default_headers)
[ GitHub ]# File 'actionpack/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)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 191
def self.merge_default_headers(original, default) default.respond_to?(:merge) ? default.merge(original) : original end
.rack_status_code(status)
See additional method definition at line 51.
Instance Attribute Details
#body (rw)
Returns the content of the response as a string. This contains the contents of
any calls to render.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 372
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) (rw)
Allows you to manually set or override the response body.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 387
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
#charset (rw)
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.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 342
def charset header_info = parsed_content_type_header header_info.charset || self.class.default_charset end
#charset=(charset) (rw)
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'
# File 'actionpack/lib/action_dispatch/http/response.rb', line 331
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
#committed? ⇒ Boolean (readonly)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/http/response.rb', line 260
def committed?; synchronize { @committed }; end
#content_type (rw)
Content type of response.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 311
def content_type super.presence end
#content_type=(content_type) (rw)
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.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 292
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
#header (readonly)
Alias for #headers.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 87
alias_method :header, :headers
#headers (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.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 85
attr_reader :headers
#request (rw)
The request that the response is responding to.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 67
attr_accessor :request
#sending? ⇒ Boolean (readonly)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/http/response.rb', line 259
def sending?; synchronize { @sending }; end
#sending_file=(v) (writeonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 320
def sending_file=(v) if true == v self.charset = false end end
#sent? ⇒ Boolean (readonly)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/http/response.rb', line 261
def sent?; synchronize { @sent }; end
#status (rw)
The HTTP status code.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 70
attr_reader :status
#status=(status) (rw)
Sets the HTTP status code.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 276
def status=(status) @status = Response.rack_status_code(status) end
#stream (readonly)
The underlying body, as a streamable object.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 196
attr_reader :stream
Instance Method Details
#[]
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 89
delegate :[], :[]=, to: :@headers
#[]=
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 89
delegate :[], :[]=, to: :@headers
#_cache_control
Aliasing these off because AD::Http::Cache::Response defines them.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 107
alias :_cache_control :cache_control
#_cache_control=
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 108
alias :_cache_control= :cache_control=
#abort
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 449
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
#assign_default_content_type_and_charset! (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 569
def assign_default_content_type_and_charset! return if media_type ct = parsed_content_type_header set_content_type(ct.mime_type || Mime[:html].to_s, ct.charset || self.class.default_charset) end
#await_commit
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 226
def await_commit synchronize do @cv.wait_until { @committed } end end
#await_sent
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 232
def await_sent synchronize { @cv.wait_until { @sent } } end
#before_committed (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 547
def before_committed return if committed? assign_default_content_type_and_charset! merge_and_normalize_cache_control!(@cache_control) handle_conditional_get! handle_no_content! end
#before_sending (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 555
def before_sending # Normally we've already committed by now, but it's possible (e.g., if the # controller action tries to read back its own response) to get here before # that. In that case, we must force an "early" commit: we're about to freeze the # headers, so this is our last chance. commit! unless committed? @request. unless committed? end
#body_parts
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 436
def body_parts parts = [] @stream.each { |x| parts << x } parts end
#build_buffer(response, body) (private)
[ GitHub ]#close
[ GitHub ]#code
Returns a string to ensure compatibility with Net::HTTPResponse.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 353
def code @status.to_s end
#commit!
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 236
def commit! synchronize do before_committed @committed = true @cv.broadcast end end
#cookies
Returns the response cookies, converted to a ::Hash of (name => value) pairs
assert_equal 'AuthorOfNewPage', r.['author']
# File 'actionpack/lib/action_dispatch/http/response.rb', line 472
def = {} if header = get_header(SET_COOKIE) header = header.split("\n") if header.respond_to?(:to_str) header.each do || if pair = .split(";").first key, value = pair.split("=").map { |v| Rack::Utils.unescape(v) } [key] = value end end end end
#delete_header(key)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 224
def delete_header(key); @headers.delete key; end
#each(&block)
[ GitHub ]#get_header(key)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 222
def get_header(key); @headers[key]; end
#handle_no_content!
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 621
def handle_no_content! if NO_CONTENT_CODES.include?(@status) @headers.delete CONTENT_TYPE @headers.delete "Content-Length" end end
#has_header?(key) ⇒ Boolean
# File 'actionpack/lib/action_dispatch/http/response.rb', line 221
def has_header?(key); @headers.key? key; end
#location Also known as: #redirect_url
Location of the response.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 264
rdoc_method :method: location
#location=(location)
Sets the location of the response
# File 'actionpack/lib/action_dispatch/http/response.rb', line 269
rdoc_method :method: location=
#media_type
Media type of response.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 316
def media_type parsed_content_type_header.mime_type end
#message Also known as: #status_message
# File 'actionpack/lib/action_dispatch/http/response.rb', line 365
def Rack::Utils::HTTP_STATUS_CODES[@status] end
#parse_content_type(content_type) (private)
# File 'actionpack/lib/action_dispatch/http/response.rb', line 496
def parse_content_type(content_type) if content_type && match = CONTENT_TYPE_PARSER.match(content_type) ContentTypeHeader.new(match[:mime_type], match[:charset]) else NullContentTypeHeader end end
#parsed_content_type_header (private)
Small internal convenience method to get the parsed version of the current content type header. The result is memoized per raw header value, since the header is read several times per request (content negotiation, charset, committing the response) and parsing allocates a MatchData and its captures each time. A missing header is not memoized: it parses to a shared null object without allocating.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 510
def parsed_content_type_header raw = get_header(CONTENT_TYPE) return NullContentTypeHeader unless raw if raw == @parsed_content_type_raw @parsed_content_type else @parsed_content_type_raw = raw @parsed_content_type = parse_content_type(raw) end end
#prepare!
Alias for #to_a.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 467
alias prepare! to_a
#rack_response(status, headers)
[ GitHub ]#redirect_url
Alias for #location.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 443
alias_method :redirect_url, :location
#reset_body!
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 432
def reset_body! @stream = build_buffer(self, []) end
#response_code
The response code of the request.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 348
def response_code @status end
#send_file(path)
Send the file stored at path as the response body.
#sending!
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 244
def sending! synchronize do before_sending @sending = true @cv.broadcast end end
#sent!
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 252
def sent! synchronize do @sent = true @cv.broadcast end end
#set_content_type(content_type, charset) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 527
def set_content_type(content_type, charset) type = content_type || "" if charset charset = charset.to_s.downcase type = "#{type}; charset=#{charset}" else charset = nil end set_header CONTENT_TYPE, type # We serialized the parts ourselves, so prime the parsed-header memo # instead of letting the reader regexp-parse our own output back apart. # Parts the parser could read differently go through the parser. mime_type = content_type.presence unless mime_type&.match?(AMBIGUOUS_CONTENT_TYPE_PART) || charset&.match?(AMBIGUOUS_CONTENT_TYPE_PART) || charset == "" @parsed_content_type_raw = type @parsed_content_type = ContentTypeHeader.new(mime_type, charset) end end
#set_header(key, v)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 223
def set_header(key, v); @headers[key] = v; end
#status_message
Alias for #message.
# File 'actionpack/lib/action_dispatch/http/response.rb', line 368
alias_method :, :
#to_a Also known as: #prepare!
# File 'actionpack/lib/action_dispatch/http/response.rb', line 463
def to_a commit! rack_response @status, @headers.to_hash end
#write(string)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/response.rb', line 382
def write(string) @stream.write string end