Class: Hanami::Action::Response Private
- Inherits:
-
Rack::Response
- Object
- Rack::Response
- Hanami::Action::Response
- Defined in:
- lib/hanami/action/response.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
The HTTP response for an action, given to #handle.
Inherits from ‘Rack::Response`, providing compatibility with Rack functionality.
Constant Summary collapse
- DEFAULT_VIEW_OPTIONS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
-> (*) { {} }.freeze
- EMPTY_BODY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
[].freeze
- FILE_SYSTEM_ROOT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Pathname.new("/").freeze
Instance Attribute Summary collapse
- #charset ⇒ Object private
- #env ⇒ Object readonly private
- #exposures ⇒ Object readonly private
- #request ⇒ Object readonly private
- #view_options ⇒ Object readonly private
Class Method Summary collapse
- .build(status, env) ⇒ Object private
Instance Method Summary collapse
-
#[](key) ⇒ Object
Returns the exposure value for the given key.
-
#[]=(key, value) ⇒ Object
Sets an exposure value for the given key.
- #_send_file(send_file_response) ⇒ Object private
- #allow_redirect? ⇒ Boolean private
-
#body=(str) ⇒ Object
Sets the response body.
-
#cache_control(*values) ⇒ Object
Specifies the response freshness policy for HTTP caches using the ‘Cache-Control` header.
-
#cookies ⇒ CookieJar
Returns the set of cookies to be included in the response.
-
#expires(amount, *values) ⇒ Object
Sets the ‘Expires` header and `Cache-Control`/`max-age` directive for the response.
-
#flash ⇒ Flash
Returns the flash for the request.
-
#format ⇒ Symbol?
Returns the format for the response.
-
#format=(value) ⇒ Object
Sets the format and associated content type for the response.
-
#fresh(options) ⇒ Object
Sets the ‘etag` and/or `last_modified` headers on the response and halts with a `304 Not Modified` response if the request is still fresh according to the `IfNoneMatch` and `IfModifiedSince` request headers.
- #head? ⇒ Boolean private
-
#initialize(request:, config:, content_type: nil, charset: nil, env: {}, headers: {}, view_options: nil, session_enabled: false) ⇒ Response
constructor
private
A new instance of Response.
-
#redirect_to(url, status: 302) ⇒ Object
Sets the response to redirect to the given URL and halts further handling.
-
#render(view, **input) ⇒ Object
Sets the response body from the rendered view.
- #renderable? ⇒ Boolean private
-
#send_file(path) ⇒ void
Sends the file at the given path as the response, for any file within the configured ‘public_directory`.
-
#session ⇒ Hash
Returns the session for the response.
-
#session_enabled? ⇒ Boolean
Returns true if the session is enabled for the request.
- #set_format(value) ⇒ Object private
-
#status=(code) ⇒ Object
Sets the response status.
-
#unsafe_send_file(path) ⇒ void
Send the file at the given path as the response, for a file anywhere in the file system.
Constructor Details
#initialize(request:, config:, content_type: nil, charset: nil, env: {}, headers: {}, view_options: nil, session_enabled: false) ⇒ Response
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Response.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/hanami/action/response.rb', line 51 def initialize(request:, config:, content_type: nil, charset: nil, env: {}, headers: {}, view_options: nil, session_enabled: false) # rubocop:disable Layout/LineLength # `Rack::Response#initialize` copies the headers into its own internal store on both Rack # 2.2+ (`Utils::HeaderHash[headers]`) and Rack 3.x (`Headers.new` + per-entry copy), so it # never aliases the hash passed in. That means we can skip a defensive `headers.dup` here # and avoid an allocation per request without risk of pollution. See the regression spec # in `spec/unit/hanami/action/response_spec.rb` if you're tempted to add one back. super([], 200, headers) self.content_type = content_type if content_type @request = request @config = config @charset = charset @exposures = {} @env = env @view_options = || DEFAULT_VIEW_OPTIONS @session_enabled = session_enabled @sending_file = false end |
Instance Attribute Details
#charset ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
37 38 39 |
# File 'lib/hanami/action/response.rb', line 37 def charset @charset end |
#env ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 |
# File 'lib/hanami/action/response.rb', line 33 def env @env end |
#exposures ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 |
# File 'lib/hanami/action/response.rb', line 33 def exposures @exposures end |
#request ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 |
# File 'lib/hanami/action/response.rb', line 33 def request @request end |
#view_options ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 |
# File 'lib/hanami/action/response.rb', line 33 def @view_options end |
Class Method Details
.build(status, env) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
41 42 43 44 45 46 47 |
# File 'lib/hanami/action/response.rb', line 41 def self.build(status, env) new(config: Action.config.dup, content_type: Mime.best_q_match(env[Action::HTTP_ACCEPT]), env: env).tap do |r| r.status = status r.body = Http::Status.(status) r.set_format(Mime.format_from_media_type(r.content_type), config) end end |
Instance Method Details
#[](key) ⇒ Object
Returns the exposure value for the given key.
194 195 196 |
# File 'lib/hanami/action/response.rb', line 194 def [](key) @exposures.fetch(key) end |
#[]=(key, value) ⇒ Object
Sets an exposure value for the given key.
207 208 209 |
# File 'lib/hanami/action/response.rb', line 207 def []=(key, value) @exposures[key] = value end |
#_send_file(send_file_response) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
466 467 468 469 470 471 472 473 474 475 476 477 478 |
# File 'lib/hanami/action/response.rb', line 466 def _send_file(send_file_response) headers.merge!(send_file_response[Action::RESPONSE_HEADERS]) if send_file_response[Action::RESPONSE_CODE] == Action::NOT_FOUND headers.delete(Action::X_CASCADE) headers.delete(Action::CONTENT_LENGTH) Halt.call(Action::NOT_FOUND) else self.status = send_file_response[Action::RESPONSE_CODE] self.body = send_file_response[Action::RESPONSE_BODY] @sending_file = true end end |
#allow_redirect? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
448 449 450 451 452 |
# File 'lib/hanami/action/response.rb', line 448 def allow_redirect? return body.empty? if body.respond_to?(:empty?) !@sending_file end |
#body=(str) ⇒ Object
Sets the response body.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/hanami/action/response.rb', line 77 def body=(str) @length = 0 if str.nil? || str == EMPTY_BODY @body = EMPTY_BODY return end @body = [] if str.is_a?(::Rack::Files::BaseIterator) @body = str buffered_body! # Ensure appropriate content-length is set else write(str) end end |
#cache_control(*values) ⇒ Object
Specifies the response freshness policy for HTTP caches using the ‘Cache-Control` header.
Any number of non-value directives (‘:public`, `:private`, `:no_cache`, `:no_store`, `:must_revalidate`, `:proxy_revalidate`) may be passed along with a Hash of value directives (`:max_age`, `:min_stale`, `:s_max_age`).
See [RFC 2616 / 14.9](tools.ietf.org/html/rfc2616#section-14.9.1) for more on standard cache control directives.
366 367 368 369 |
# File 'lib/hanami/action/response.rb', line 366 def cache_control(*values) directives = Cache::CacheControl::Directives.new(*values) headers.merge!(directives.headers) end |
#cookies ⇒ CookieJar
Returns the set of cookies to be included in the response.
267 268 269 |
# File 'lib/hanami/action/response.rb', line 267 def @cookies ||= CookieJar.new(env.dup, headers, @config.) end |
#expires(amount, *values) ⇒ Object
Sets the ‘Expires` header and `Cache-Control`/`max-age` directive for the response.
You can provide an integer number of seconds in the future, or a Time object indicating when the response should be considered “stale”. The remaining arguments are passed to #cache_control.
395 396 397 398 |
# File 'lib/hanami/action/response.rb', line 395 def expires(amount, *values) directives = Cache::Expires::Directives.new(amount, *values) headers.merge!(directives.headers) end |
#flash ⇒ Flash
Returns the flash for the request.
This is the same flash object as the Hanami::Action::Request.
253 254 255 256 257 258 259 |
# File 'lib/hanami/action/response.rb', line 253 def flash unless session_enabled? raise Hanami::Action::MissingSessionError.new("Hanami::Action::Response#flash") end request.flash end |
#format ⇒ Symbol?
Returns the format for the response.
Returns nil if a format has not been assigned and also cannot be determined from the response’s ‘#content_type`.
145 146 147 |
# File 'lib/hanami/action/response.rb', line 145 def format @format ||= Mime.format_from_media_type(content_type, @config) end |
#format=(value) ⇒ Object
Sets the format and associated content type for the response.
Either a format name (‘:json`) or a MIME type (`“application/json”`) may be given. In either case, the format or content type will be derived from the given value, and both will be set.
Providing an unknown format name will raise an UnknownFormatError.
Providing an unknown MIME type will set the content type and set the format as nil.
176 177 178 179 180 181 182 |
# File 'lib/hanami/action/response.rb', line 176 def format=(value) format, content_type = Mime.format_and_media_type(value, @config) self.content_type = Mime.content_type_with_charset(content_type, charset) @format = format end |
#fresh(options) ⇒ Object
Sets the ‘etag` and/or `last_modified` headers on the response and halts with a `304 Not Modified` response if the request is still fresh according to the `IfNoneMatch` and `IfModifiedSince` request headers.
422 423 424 425 426 427 428 429 430 |
# File 'lib/hanami/action/response.rb', line 422 def fresh() conditional_get = Cache::ConditionalGet.new(env, ) headers.merge!(conditional_get.headers) conditional_get.fresh? do Halt.call(304) end end |
#head? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
460 461 462 |
# File 'lib/hanami/action/response.rb', line 460 def head? env[Action::REQUEST_METHOD] == Action::HEAD end |
#redirect_to(url, status: 302) ⇒ Object
Sets the response to redirect to the given URL and halts further handling.
278 279 280 281 282 283 |
# File 'lib/hanami/action/response.rb', line 278 def redirect_to(url, status: 302) return unless allow_redirect? redirect(::String.new(url), status) Halt.call(status) end |
#render(view, **input) ⇒ Object
Sets the response body from the rendered view.
123 124 125 126 127 128 129 130 131 |
# File 'lib/hanami/action/response.rb', line 123 def render(view, **input) view_input = { **.call(request, self), **exposures, **input } self.body = view.call(**view_input).to_str end |
#renderable? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
440 441 442 443 444 |
# File 'lib/hanami/action/response.rb', line 440 def renderable? return !head? && body.empty? if body.respond_to?(:empty?) !@sending_file && !head? end |
#send_file(path) ⇒ void
This method returns an undefined value.
Sends the file at the given path as the response, for any file within the configured ‘public_directory`.
Handles the following aspects for file responses:
-
Setting ‘Content-Type` and `Content-Length` headers
-
File Not Found responses (returns a 404)
-
Conditional GET (via ‘If-Modified-Since` header)
-
Range requests (via ‘Range` header)
304 305 306 307 308 |
# File 'lib/hanami/action/response.rb', line 304 def send_file(path) _send_file( Action::Rack::File.new(path, @config.public_directory).call(env) ) end |
#session ⇒ Hash
Returns the session for the response.
This is the same session object as the Hanami::Action::Request.
233 234 235 236 237 238 239 |
# File 'lib/hanami/action/response.rb', line 233 def session unless session_enabled? raise Hanami::Action::MissingSessionError.new("Hanami::Action::Response#session") end request.session end |
#session_enabled? ⇒ Boolean
Returns true if the session is enabled for the request.
217 218 219 |
# File 'lib/hanami/action/response.rb', line 217 def session_enabled? @session_enabled end |
#set_format(value) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
434 435 436 |
# File 'lib/hanami/action/response.rb', line 434 def set_format(value) # rubocop:disable Naming/AccessorMethodName @format = value end |
#status=(code) ⇒ Object
Sets the response status.
112 113 114 |
# File 'lib/hanami/action/response.rb', line 112 def status=(code) super(Http::Status.lookup(code)) end |
#unsafe_send_file(path) ⇒ void
This method returns an undefined value.
Send the file at the given path as the response, for a file anywhere in the file system.
321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/hanami/action/response.rb', line 321 def unsafe_send_file(path) directory = if Pathname.new(path).relative? @config.root_directory else FILE_SYSTEM_ROOT end _send_file( Action::Rack::File.new(path, directory).call(env) ) end |