class Hanami::Action::CookieJar
A set of HTTP Cookies
It acts as an Hash
@since 0.1.0
@see Hanami::Action::Cookies#cookies
Constants
- COOKIE_SEPARATOR
@since 0.4.5 @api private
Public Class Methods
Initialize the CookieJar
@param env [Hash] a raw Rack
env @param headers [Hash] the response headers
@return [CookieJar]
@since 0.1.0
# File lib/hanami/action/cookie_jar.rb, line 28 def initialize(env, headers, default_options) @_headers = headers @cookies = Utils::Hash.deep_symbolize(extract(env)) @default_options = default_options end
Public Instance Methods
Returns the object associated with the given key
@param key [Symbol] the key
@return [Object,nil] return the associated object, if found
@since 0.2.0
# File lib/hanami/action/cookie_jar.rb, line 60 def [](key) @cookies[key] end
Associate the given value with the given key and store them
@param key [Symbol] the key @param value [#to_s,Hash] value that can be serialized as a string or
expressed as a Hash
@option value [String] :value - Value of the cookie @option value [String] :domain - The domain @option value [String] :path - The path @option value [Integer] :max_age - Duration expressed in seconds @option value [Time] :expires - Expiration time @option value [TrueClass,FalseClass] :secure - Restrict cookie to secure
connections
@option value [TrueClass,FalseClass] :httponly - Restrict JavaScript
access
@return [void]
@since 0.2.0
@see en.wikipedia.org/wiki/HTTP_cookie
# File lib/hanami/action/cookie_jar.rb, line 84 def []=(key, value) changes << key @cookies[key] = value end
Iterates cookies
@param blk [Proc] the block to be yielded @yield [key, value] the key/value pair for each cookie
@return [void]
@since 1.1.0
@example
require "hanami/controller" class MyAction < Hanami::Action include Hanami::Action::Cookies def handle(req, res) # read cookies req.cookies.each do |key, value| # ... end end end
# File lib/hanami/action/cookie_jar.rb, line 110 def each(&blk) @cookies.each(&blk) end
Finalize itself, by setting the proper headers to add and remove cookies, before the response is returned to the webserver.
@return [void]
@since 0.1.0
@see Hanami::Action::Cookies#finish
# File lib/hanami/action/cookie_jar.rb, line 42 def finish @cookies.delete(Action::RACK_SESSION) if changed? @cookies.each do |k, v| next unless changed?(k) v.nil? ? delete_cookie(k) : set_cookie(k, _merge_default_values(v)) end end end
Private Instance Methods
Add expires option to cookies if :max_age presents
@since 0.4.3 @api private
# File lib/hanami/action/cookie_jar.rb, line 156 def _add_expires_option(value) if value.key?(:max_age) && !value.key?(:expires) {expires: (Time.now + value[:max_age])} else {} end end
Merge default cookies options with values provided by user
Cookies
values provided by user are respected
@since 0.4.0 @api private
# File lib/hanami/action/cookie_jar.rb, line 143 def _merge_default_values(value) cookies_options = if value.is_a?(::Hash) value.merge! _add_expires_option(value) else {value: value} end @default_options.merge cookies_options end
Check if the entire set of cookies has changed within the current request. If key
is given, it checks the associated cookie has changed.
@since 0.7.0 @api private
# File lib/hanami/action/cookie_jar.rb, line 129 def changed?(key = nil) if key.nil? changes.any? else changes.include?(key) end end
Keep track of changed keys
@since 0.7.0 @api private
# File lib/hanami/action/cookie_jar.rb, line 120 def changes @changes ||= Set.new end
Extract the cookies from the raw Rack
env.
This implementation is borrowed from Rack::Request#cookies.
@since 0.1.0 @api private
# File lib/hanami/action/cookie_jar.rb, line 170 def extract(env) hash = env[Action::COOKIE_HASH_KEY] ||= {} string = env[Action::HTTP_COOKIE] return hash if string == env[Action::COOKIE_STRING_KEY] # TODO: Next Rack 1.7.x ?? version will have ::Rack::Utils.parse_cookies # We can then replace the following lines. hash.clear # According to RFC 2109: # If multiple cookies satisfy the criteria above, they are ordered in # the Cookie header such that those with more specific Path attributes # precede those with less specific. Ordering with respect to other # attributes (e.g., Domain) is unspecified. cookies = ::Rack::Utils.parse_query(string, COOKIE_SEPARATOR) { |s| begin ::Rack::Utils.unescape(s) rescue StandardError s end } cookies.each { |k, v| hash[k] = v.is_a?(Array) ? v.first : v } env[Action::COOKIE_STRING_KEY] = string hash end