Class: Dommy::Rack::CookieJar
- Inherits:
-
Object
- Object
- Dommy::Rack::CookieJar
- Defined in:
- lib/dommy/rack/cookie_jar.rb,
sig/dommy/rack.rbs
Overview
A simplified, same-origin cookie store.
Defined Under Namespace
Classes: CookieEntry
Instance Method Summary collapse
- #all ⇒ Array[untyped]
- #clear ⇒ void
-
#cookies_for(request_url) ⇒ String
Build the Cookie request header value for the given URL, or "".
-
#export ⇒ Object
Every non-expired cookie as a plain Hash (name/value/domain/path/expires/ secure/http_only/host_only) — enough to round-trip the jar to disk and back via #import! without losing host-only scoping.
-
#get(name) ⇒ String?
First non-expired cookie value matching the name.
-
#import!(attrs) ⇒ Object
Restore a cookie from an #export Hash, preserving host_only exactly (unlike #set!, which infers it).
-
#initialize ⇒ CookieJar
constructor
A new instance of CookieJar.
-
#set!(name, value, domain: nil, path: "/", expires: nil, secure: false, http_only: false) ⇒ Object
Manually store a cookie.
-
#store_from_header(set_cookie_string, request_url) ⇒ void
Parse a single Set-Cookie header value and store the result.
Constructor Details
#initialize ⇒ CookieJar
Returns a new instance of CookieJar.
17 18 19 20 21 22 23 24 25 |
# File 'lib/dommy/rack/cookie_jar.rb', line 17 def initialize @entries = [] # The jar is shared between the page thread (document.cookie) and network # worker threads (request Cookie headers + Set-Cookie storage), so every # touch of @entries is guarded. The lock is held only around the array # access (no I/O, no reentrancy into the jar), so it never serializes the # blocking HTTP itself. @mutex = Mutex.new end |
Instance Method Details
#all ⇒ Array[untyped]
66 67 68 |
# File 'lib/dommy/rack/cookie_jar.rb', line 66 def all @mutex.synchronize { @entries.reject { |e| expired?(e) } } end |
#clear ⇒ void
This method returns an undefined value.
62 63 64 |
# File 'lib/dommy/rack/cookie_jar.rb', line 62 def clear @mutex.synchronize { @entries = [] } end |
#cookies_for(request_url) ⇒ String
Build the Cookie request header value for the given URL, or "".
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/dommy/rack/cookie_jar.rb', line 94 def (request_url) uri = URI.parse(request_url) secure_request = uri.scheme == "https" host = uri.host.to_s.downcase path = uri.path.to_s.empty? ? "/" : uri.path matches = @mutex.synchronize do @entries.reject { |e| expired?(e) }.select do |e| domain_match?(e, host) && path_match?(e.path, path) && (!e.secure || secure_request) end end # More specific (longer) paths first, per RFC 6265 (on the snapshot copy, # outside the lock). matches.sort_by! { |e| -e.path.length } matches.map { |e| "#{e.name}=#{e.value}" }.join("; ") end |
#export ⇒ Object
Every non-expired cookie as a plain Hash (name/value/domain/path/expires/
secure/http_only/host_only) — enough to round-trip the jar to disk and
back via #import! without losing host-only scoping. expires is a Time or
nil; the caller serializes it.
74 75 76 |
# File 'lib/dommy/rack/cookie_jar.rb', line 74 def export all.map(&:to_h) end |
#get(name) ⇒ String?
First non-expired cookie value matching the name.
58 59 60 |
# File 'lib/dommy/rack/cookie_jar.rb', line 58 def get(name) @mutex.synchronize { @entries.find { |e| e.name == name.to_s && !expired?(e) }&.value } end |
#import!(attrs) ⇒ Object
Restore a cookie from an #export Hash, preserving host_only exactly (unlike #set!, which infers it). Skips an already-expired entry. Symbol- or string-keyed Hashes both work, so a JSON round-trip is fine.
81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/dommy/rack/cookie_jar.rb', line 81 def import!(attrs) h = attrs.transform_keys(&:to_sym) entry = CookieEntry.new( name: h[:name].to_s, value: h[:value].to_s, domain: h[:domain].to_s, path: (h[:path] || "/"), expires: h[:expires], secure: !!h[:secure], http_only: !!h[:http_only], host_only: !!h[:host_only] ) @mutex.synchronize { store_entry(entry) unless expired?(entry) } nil end |
#set!(name, value, domain: nil, path: "/", expires: nil, secure: false, http_only: false) ⇒ Object
Manually store a cookie. domain defaults to host-only on request_host.
43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/dommy/rack/cookie_jar.rb', line 43 def set!(name, value, domain: nil, path: "/", expires: nil, secure: false, http_only: false) entry = CookieEntry.new( name: name.to_s, value: value.to_s, domain: (domain || "").sub(/\A\./, "").downcase, path: path || "/", expires: expires, secure: secure, http_only: http_only, host_only: domain.nil? ) @mutex.synchronize { store_entry(entry) } end |
#store_from_header(set_cookie_string, request_url) ⇒ void
This method returns an undefined value.
Parse a single Set-Cookie header value and store the result.
28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/dommy/rack/cookie_jar.rb', line 28 def store_from_header(, request_url) uri = URI.parse(request_url) entry = (, uri) return unless entry @mutex.synchronize do if expired?(entry) remove(entry.name, entry.domain, entry.path) else store_entry(entry) end end end |