class HTTP::CookieJar::HashStore
to be expired individually.
they differ in the ‘for_domain` flag value, which means they need
two cookies with the same name, domain and path coexist as long as
affects in storing cookies. On the other hand, in MozillaStore
RFC 6265 5.3 where there is no mention of how the host-only-flag
value. This store is built after the storage model described in
will overwrite each other regardless of the `for_domain` flag
In this store, cookies that share the same name, domain and path
A store class that uses a hash-based cookie store.
def add(cookie)
def add(cookie) path_cookies = ((@jar[cookie.domain] ||= {})[cookie.path] ||= {}) path_cookies[cookie.name] = cookie cleanup if (@gc_index += 1) >= @gc_threshold self end
def cleanup(session = false)
def cleanup(session = false) now = Time.now all_cookies = [] synchronize { break if @gc_index == 0 @jar.each { |domain, paths| domain_cookies = [] paths.each { |path, hash| hash.delete_if { |name, cookie| if cookie.expired?(now) || (session && cookie.session?) true else domain_cookies << cookie false end } } if (debt = domain_cookies.size - HTTP::Cookie::MAX_COOKIES_PER_DOMAIN) > 0 domain_cookies.sort_by!(&:created_at) domain_cookies.slice!(0, debt).each { |cookie| delete(cookie) } end all_cookies.concat(domain_cookies) } if (debt = all_cookies.size - HTTP::Cookie::MAX_COOKIES_TOTAL) > 0 all_cookies.sort_by!(&:created_at) all_cookies.slice!(0, debt).each { |cookie| delete(cookie) } end @jar.delete_if { |domain, paths| paths.delete_if { |path, hash| hash.empty? } paths.empty? } @gc_index = 0 } self end
def clear
def clear @jar.clear self end
def default_options
def default_options { :gc_threshold => HTTP::Cookie::MAX_COOKIES_TOTAL / 20 } end
def delete(cookie)
def delete(cookie) path_cookies = ((@jar[cookie.domain] ||= {})[cookie.path] ||= {}) path_cookies.delete(cookie.name) self end
def each(uri = nil) # :yield: cookie
def each(uri = nil) # :yield: cookie now = Time.now if uri tpath = uri.path @jar.each { |domain, paths| paths.each { |path, hash| next unless HTTP::Cookie.path_match?(path, tpath) hash.delete_if { |name, cookie| if cookie.expired?(now) true else if cookie.valid_for_uri?(uri) cookie.accessed_at = now yield cookie end false end } } } else synchronize { @jar.each { |domain, paths| paths.each { |path, hash| hash.delete_if { |name, cookie| if cookie.expired?(now) true else yield cookie false end } } } } end self end
def initialize(options = nil)
: GC threshold; A GC happens when this many times cookies have
:gc_threshold
Available option keywords are as below:
Generates a hash based cookie store.
new(**options)
:call-seq:
def initialize(options = nil) super @jar = { # hostname => { # path => { # name => cookie, # ... # }, # ... # }, # ... } @gc_index = 0 end
def initialize_copy(other)
def initialize_copy(other) @jar = Marshal.load(Marshal.dump(other.instance_variable_get(:@jar))) end