class Hanami::Action::CookieJar

A set of HTTP Cookies

It acts as an Hash

@since 0.1.0

@see Hanami::Action::Cookies#cookies

Constants

The key used by Rack to set the cookies as an Hash in the env

@since 0.1.0 @api private

@since 0.4.5 @api private

The key used by Rack to set the cookies as a String in the env

@since 0.1.0 @api private

HTTP_HEADER

The key that returns raw cookies from the Rack env

@since 0.1.0 @api private

RACK_SESSION_KEY

The key used by Rack to set the session cookie

We let CookieJar to NOT take care of this cookie, but it leaves the responsibility to the Rack middleware that handle sessions.

This prevents Set-Cookie to be sent twice.

@since 0.5.1 @api private

@see github.com/hanami/controller/issues/138

Public Class Methods

new(env, headers, default_options) click to toggle source

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 56
def initialize(env, headers, default_options)
  @_headers        = headers
  @cookies         = Utils::Hash.new(extract(env)).deep_symbolize!
  @default_options = default_options
end

Public Instance Methods

[](key) click to toggle source

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 85
def [](key)
  @cookies[key]
end
[]=(key, value) click to toggle source

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 109
def []=(key, value)
  changes << key
  @cookies[key] = value
end
each(&blk) click to toggle source

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
  include Hanami::Action
  include Hanami::Action::Cookies

  def call(params)
    cookies.each do |key, value|
      # ...
    end
  end
end
# File lib/hanami/action/cookie_jar.rb, line 135
def each(&blk)
  @cookies.each(&blk)
end
finish() click to toggle source

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 70
def finish
  @cookies.delete(RACK_SESSION_KEY)
  @cookies.each do |k,v|
    next unless changed?(k)
    v.nil? ? delete_cookie(k) : set_cookie(k, _merge_default_values(v))
  end if changed?
end

Private Instance Methods

_add_expires_option(value) click to toggle source

Add expires option to cookies if :max_age presents

@since 0.4.3 @api private

# File lib/hanami/action/cookie_jar.rb, line 181
def _add_expires_option(value)
  if value.has_key?(:max_age) && !value.has_key?(:expires)
    { expires: (Time.now + value[:max_age]) }
  else
    {}
  end
end
_merge_default_values(value) click to toggle source

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 168
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
changed?(key = nil) click to toggle source

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 154
def changed?(key = nil)
  if key.nil?
    changes.any?
  else
    changes.include?(key)
  end
end
changes() click to toggle source

Keep track of changed keys

@since 0.7.0 @api private

# File lib/hanami/action/cookie_jar.rb, line 145
def changes
  @changes ||= Set.new
end
extract(env) click to toggle source

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 195
def extract(env)
  hash   = env[COOKIE_HASH_KEY] ||= {}
  string = env[HTTP_HEADER]

  return hash if string == env[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| ::Rack::Utils.unescape(s) rescue s }
  cookies.each { |k,v| hash[k] = Array === v ? v.first : v }
  env[COOKIE_STRING_KEY] = string
  hash
end