http-cookie 1.0.3 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +67 -0
- data/LICENSE.txt +1 -1
- data/README.md +5 -2
- data/lib/http/cookie/scanner.rb +4 -3
- data/lib/http/cookie/uri_parser.rb +36 -0
- data/lib/http/cookie/version.rb +1 -1
- data/lib/http/cookie.rb +18 -8
- data/lib/http/cookie_jar/abstract_saver.rb +11 -22
- data/lib/http/cookie_jar/abstract_store.rb +13 -18
- data/lib/http/cookie_jar/cookiestxt_saver.rb +0 -1
- data/lib/http/cookie_jar/hash_store.rb +0 -3
- data/lib/http/cookie_jar/mozilla_store.rb +159 -32
- data/lib/http/cookie_jar/yaml_saver.rb +9 -5
- data/lib/http/cookie_jar.rb +8 -22
- data/lib/http-cookie.rb +4 -1
- metadata +10 -28
- data/.gitignore +0 -17
- data/.travis.yml +0 -21
- data/Gemfile +0 -4
- data/Rakefile +0 -20
- data/http-cookie.gemspec +0 -34
- data/test/helper.rb +0 -55
- data/test/mechanize.yml +0 -101
- data/test/simplecov_start.rb +0 -2
- data/test/test_http_cookie.rb +0 -1122
- data/test/test_http_cookie_jar.rb +0 -985
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 72ef3493437238f93258320d1e8bdfea5d155e731ed6e88d55b284bff3c7a3a0
|
|
4
|
+
data.tar.gz: ecf432149b7b13a7437ad6c8a8433b85fbe4cf223ba07016831c2da3a8598de2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 110ace005f635800820a73c4c4955cdd0d80fdfddf781949957f2738e0bd7d78068c5d03537f9defa7eba25b7f8156e823897460cd3bf84db8fd7dff55550cd2
|
|
7
|
+
data.tar.gz: c20f7c2409b86773bcf93367d135058dea7bf52f7fe3ef240161be0b137d2dce9ced8fc4e8398353b876c469edaebcdecc2e7cba77f92795972e6472a8f13959
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,70 @@
|
|
|
1
|
+
## 1.1.6 (2026-04-20)
|
|
2
|
+
|
|
3
|
+
- Use `autoload` to avoid "circular require" warnings between `http/cookie` and `http/cookie_jar`. (#65)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## 1.1.5 (2026-04-19)
|
|
7
|
+
|
|
8
|
+
- Fix `NameError: uninitialized constant HTTP::Cookie::MAX_COOKIES_TOTAL` when `http/cookie_jar` is required without `http/cookie`, as done by the `http` gem. (#62)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## 1.1.4 (2026-04-07)
|
|
12
|
+
|
|
13
|
+
- Fix `require "http/cookie_jar"` raising `NameError: uninitialized constant HTTP`. (#61)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## 1.1.3 (2026-04-06)
|
|
17
|
+
|
|
18
|
+
- Restore compatibility with Ruby 2.6.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## 1.1.2 (2026-04-06)
|
|
22
|
+
|
|
23
|
+
- Stop requiring sqlite3 at load time by changing `MozillaStore::Database` from inheritance to composition.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## 1.1.1 (2026-04-06)
|
|
27
|
+
|
|
28
|
+
- Fix thread-unsafe runtime requires. (#43 by @brasic, #57)
|
|
29
|
+
- Replace `require 'cgi'` with `require 'cgi/escape'` to suppress Ruby 4.0 warning. (#56 by @dominion525)
|
|
30
|
+
- Do not define `MozillaStore` on JRuby; leave the constant undefined instead.
|
|
31
|
+
- Relax sqlite3 development dependency to `>= 1.3`.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## 1.1.0 (2025-09-26)
|
|
35
|
+
|
|
36
|
+
- Implement `Cookie#to_h`. (#55) @luke-hill @flavorjones
|
|
37
|
+
- Reduce gem size by excluding test files (#54) @yuri-zubov
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## 1.0.8 (2024-12-05)
|
|
41
|
+
|
|
42
|
+
- `Cookie#expires=` accepts `DateTime` objects. (#52) @luke-hill @flavorjones
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## 1.0.7 (2024-06-06)
|
|
46
|
+
|
|
47
|
+
- Explicitly require "cgi" to avoid `NameError` in some applications. (#50 by @flavorjones)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
## 1.0.6 (2024-06-01)
|
|
51
|
+
|
|
52
|
+
- Fix error formatting bug in HTTP::CookieJar::AbstractStore (#42 by @andrelaszlo)
|
|
53
|
+
- Allow non-RFC 3986-compliant URLs (#45 by @c960657)
|
|
54
|
+
- Add coverage for Ruby 3.2 and 3.3 (#46 by @flavorjones)
|
|
55
|
+
- Quash ruby 3.4 warnings (#47 by @flavorjones)
|
|
56
|
+
|
|
57
|
+
## 1.0.5 (2022-05-25)
|
|
58
|
+
|
|
59
|
+
- Silence SQLite3 warnings
|
|
60
|
+
|
|
61
|
+
## 1.0.4 (2021-06-07)
|
|
62
|
+
|
|
63
|
+
- Support Mozilla's cookie storage format up to version 7.
|
|
64
|
+
|
|
65
|
+
- Fix the time representation with creationTime and lastAccessed in
|
|
66
|
+
MozillaStore. (#8)
|
|
67
|
+
|
|
1
68
|
## 1.0.3 (2016-09-30)
|
|
2
69
|
|
|
3
70
|
- Treat comma as normal character in HTTP::Cookie.cookie_value_to_hash
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
[](https://badge.fury.io/rb/http-cookie)
|
|
2
|
+
|
|
1
3
|
# HTTP::Cookie
|
|
2
4
|
|
|
3
5
|
HTTP::Cookie is a ruby library to handle HTTP cookies in a way both
|
|
@@ -20,7 +22,8 @@ The following is an incomplete list of its features:
|
|
|
20
22
|
* It takes eTLD (effective TLD, also known as "Public Suffix") into
|
|
21
23
|
account just as major browsers do, to reject cookies with an eTLD
|
|
22
24
|
domain like "org", "co.jp", or "appspot.com". This feature is
|
|
23
|
-
brought to you by the
|
|
25
|
+
brought to you by the
|
|
26
|
+
[domain_name](https://github.com/knu/ruby-domain_name) gem.
|
|
24
27
|
|
|
25
28
|
* The number of cookies and the size are properly capped so that a
|
|
26
29
|
cookie store does not get flooded.
|
|
@@ -207,7 +210,7 @@ equivalent using HTTP::Cookie:
|
|
|
207
210
|
guarantee that it will remain available in the future.
|
|
208
211
|
|
|
209
212
|
|
|
210
|
-
HTTP::Cookie/CookieJar
|
|
213
|
+
HTTP::Cookie/CookieJar raises runtime errors to help migration, so
|
|
211
214
|
after replacing the class names, try running your test code once to
|
|
212
215
|
find out how to fix your code base.
|
|
213
216
|
|
data/lib/http/cookie/scanner.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'http/cookie'
|
|
2
3
|
require 'strscan'
|
|
3
4
|
require 'time'
|
|
@@ -23,7 +24,7 @@ class HTTP::Cookie::Scanner < StringScanner
|
|
|
23
24
|
class << self
|
|
24
25
|
def quote(s)
|
|
25
26
|
return s unless s.match(RE_BAD_CHAR)
|
|
26
|
-
'"' << s.gsub(/([\\"])/, "\\\\\\1") << '"'
|
|
27
|
+
(+'"') << s.gsub(/([\\"])/, "\\\\\\1") << '"'
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|
|
@@ -32,7 +33,7 @@ class HTTP::Cookie::Scanner < StringScanner
|
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def scan_dquoted
|
|
35
|
-
''.tap { |s|
|
|
36
|
+
(+'').tap { |s|
|
|
36
37
|
case
|
|
37
38
|
when skip(/"/)
|
|
38
39
|
break
|
|
@@ -51,7 +52,7 @@ class HTTP::Cookie::Scanner < StringScanner
|
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
def scan_value(comma_as_separator = false)
|
|
54
|
-
''.tap { |s|
|
|
55
|
+
(+'').tap { |s|
|
|
55
56
|
case
|
|
56
57
|
when scan(/[^,;"]+/)
|
|
57
58
|
s << matched
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module HTTP::Cookie::URIParser
|
|
2
|
+
module_function
|
|
3
|
+
|
|
4
|
+
# Regular Expression taken from RFC 3986 Appendix B
|
|
5
|
+
URIREGEX = %r{
|
|
6
|
+
\A
|
|
7
|
+
(?: (?<scheme> [^:/?\#]+ ) : )?
|
|
8
|
+
(?: // (?<authority> [^/?\#]* ) )?
|
|
9
|
+
(?<path> [^?\#]* )
|
|
10
|
+
(?: \? (?<query> [^\#]* ) )?
|
|
11
|
+
(?: \# (?<fragment> .* ) )?
|
|
12
|
+
\z
|
|
13
|
+
}x
|
|
14
|
+
|
|
15
|
+
# Escape RFC 3986 "reserved" characters minus valid characters for path
|
|
16
|
+
# More specifically, gen-delims minus "/" / "?" / "#"
|
|
17
|
+
def escape_path(path)
|
|
18
|
+
path.sub(/\A[^?#]+/) { |p| p.gsub(/[:\[\]@]+/) { |r| CGI.escape(r) } }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Parse a URI string or object, relaxing the constraints on the path component
|
|
22
|
+
def parse(uri)
|
|
23
|
+
URI(uri)
|
|
24
|
+
rescue URI::InvalidURIError
|
|
25
|
+
str = String.try_convert(uri) or
|
|
26
|
+
raise ArgumentError, "bad argument (expected URI object or URI string)"
|
|
27
|
+
|
|
28
|
+
m = URIREGEX.match(str) or raise
|
|
29
|
+
|
|
30
|
+
path = m[:path]
|
|
31
|
+
str[m.begin(:path)...m.end(:path)] = escape_path(path)
|
|
32
|
+
uri = URI.parse(str)
|
|
33
|
+
uri.__send__(:set_path, path)
|
|
34
|
+
uri
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/http/cookie/version.rb
CHANGED
data/lib/http/cookie.rb
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# :markup: markdown
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require 'http/cookie/version'
|
|
4
|
+
require 'http/cookie/uri_parser'
|
|
3
5
|
require 'time'
|
|
4
6
|
require 'uri'
|
|
5
7
|
require 'domain_name'
|
|
6
8
|
require 'http/cookie/ruby_compat'
|
|
9
|
+
require 'cgi/escape'
|
|
7
10
|
|
|
8
11
|
module HTTP
|
|
9
12
|
autoload :CookieJar, 'http/cookie_jar'
|
|
@@ -86,7 +89,7 @@ class HTTP::Cookie
|
|
|
86
89
|
|
|
87
90
|
# The Expires attribute value as a Time object.
|
|
88
91
|
#
|
|
89
|
-
# The setter method accepts a Time object, a string representation
|
|
92
|
+
# The setter method accepts a Time / DateTime object, a string representation
|
|
90
93
|
# of date/time that Time.parse can understand, or `nil`.
|
|
91
94
|
#
|
|
92
95
|
# Setting this value resets #max_age to nil. When #max_age is
|
|
@@ -128,7 +131,7 @@ class HTTP::Cookie
|
|
|
128
131
|
# new("name" => "uid", "value" => "a12345", "Domain" => 'www.example.org')
|
|
129
132
|
#
|
|
130
133
|
def initialize(*args)
|
|
131
|
-
@origin = @domain = @path =
|
|
134
|
+
@name = @origin = @domain = @path =
|
|
132
135
|
@expires = @max_age = nil
|
|
133
136
|
@for_domain = @secure = @httponly = false
|
|
134
137
|
@session = true
|
|
@@ -275,7 +278,7 @@ class HTTP::Cookie
|
|
|
275
278
|
logger = options[:logger]
|
|
276
279
|
created_at = options[:created_at]
|
|
277
280
|
end
|
|
278
|
-
origin =
|
|
281
|
+
origin = HTTP::Cookie::URIParser.parse(origin)
|
|
279
282
|
|
|
280
283
|
[].tap { |cookies|
|
|
281
284
|
Scanner.new(set_cookie, logger).scan_set_cookie { |name, value, attrs|
|
|
@@ -424,7 +427,7 @@ class HTTP::Cookie
|
|
|
424
427
|
# Returns the domain, with a dot prefixed only if the domain flag is
|
|
425
428
|
# on.
|
|
426
429
|
def dot_domain
|
|
427
|
-
@for_domain ? '.' << @domain : @domain
|
|
430
|
+
@for_domain ? (+'.') << @domain : @domain
|
|
428
431
|
end
|
|
429
432
|
|
|
430
433
|
# Returns the domain attribute value as a DomainName object.
|
|
@@ -455,7 +458,7 @@ class HTTP::Cookie
|
|
|
455
458
|
@origin.nil? or
|
|
456
459
|
raise ArgumentError, "origin cannot be changed once it is set"
|
|
457
460
|
# Delay setting @origin because #domain= or #path= may fail
|
|
458
|
-
origin =
|
|
461
|
+
origin = HTTP::Cookie::URIParser.parse(origin)
|
|
459
462
|
if URI::HTTP === origin
|
|
460
463
|
self.domain ||= origin.host
|
|
461
464
|
self.path ||= (origin + './').path
|
|
@@ -490,6 +493,8 @@ class HTTP::Cookie
|
|
|
490
493
|
def expires= t
|
|
491
494
|
case t
|
|
492
495
|
when nil, Time
|
|
496
|
+
when DateTime
|
|
497
|
+
t = t.to_time
|
|
493
498
|
else
|
|
494
499
|
t = Time.parse(t)
|
|
495
500
|
end
|
|
@@ -548,7 +553,7 @@ class HTTP::Cookie
|
|
|
548
553
|
# Tests if it is OK to accept this cookie if it is sent from a given
|
|
549
554
|
# URI/URL, `uri`.
|
|
550
555
|
def acceptable_from_uri?(uri)
|
|
551
|
-
uri =
|
|
556
|
+
uri = HTTP::Cookie::URIParser.parse(uri)
|
|
552
557
|
return false unless URI::HTTP === uri && uri.host
|
|
553
558
|
host = DomainName.new(uri.host)
|
|
554
559
|
|
|
@@ -585,7 +590,7 @@ class HTTP::Cookie
|
|
|
585
590
|
if @domain.nil?
|
|
586
591
|
raise "cannot tell if this cookie is valid because the domain is unknown"
|
|
587
592
|
end
|
|
588
|
-
uri =
|
|
593
|
+
uri = HTTP::Cookie::URIParser.parse(uri)
|
|
589
594
|
# RFC 6265 5.4
|
|
590
595
|
return false if secure? && !(URI::HTTPS === uri)
|
|
591
596
|
acceptable_from_uri?(uri) && HTTP::Cookie.path_match?(@path, uri.path)
|
|
@@ -594,7 +599,7 @@ class HTTP::Cookie
|
|
|
594
599
|
# Returns a string for use in the Cookie header, i.e. `name=value`
|
|
595
600
|
# or `name="value"`.
|
|
596
601
|
def cookie_value
|
|
597
|
-
"#{@name}=#{Scanner.quote(@value)}"
|
|
602
|
+
+"#{@name}=#{Scanner.quote(@value)}"
|
|
598
603
|
end
|
|
599
604
|
alias to_s cookie_value
|
|
600
605
|
|
|
@@ -650,6 +655,11 @@ class HTTP::Cookie
|
|
|
650
655
|
end
|
|
651
656
|
include Comparable
|
|
652
657
|
|
|
658
|
+
# Hash serialization helper for use back into other libraries (Like Selenium)
|
|
659
|
+
def to_h
|
|
660
|
+
PERSISTENT_PROPERTIES.each_with_object({}) { |property, hash| hash[property.to_sym] = instance_variable_get("@#{property}") }
|
|
661
|
+
end
|
|
662
|
+
|
|
653
663
|
# YAML serialization helper for Syck.
|
|
654
664
|
def to_yaml_properties
|
|
655
665
|
PERSISTENT_PROPERTIES.map { |name| "@#{name}" }
|
|
@@ -2,29 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
# An abstract superclass for all saver classes.
|
|
4
4
|
class HTTP::CookieJar::AbstractSaver
|
|
5
|
-
class << self
|
|
6
|
-
@@class_map = {}
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@@class_map.fetch(symbol)
|
|
17
|
-
rescue LoadError, IndexError
|
|
18
|
-
raise IndexError, 'cookie saver unavailable: %s' % symbol.inspect
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def inherited(subclass) # :nodoc:
|
|
23
|
-
@@class_map[class_to_symbol(subclass)] = subclass
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def class_to_symbol(klass) # :nodoc:
|
|
27
|
-
klass.name[/[^:]+?(?=Saver$|$)/].downcase.to_sym
|
|
6
|
+
def self.implementation(symbol)
|
|
7
|
+
case symbol
|
|
8
|
+
when :yaml
|
|
9
|
+
HTTP::CookieJar::YAMLSaver
|
|
10
|
+
when :cookiestxt
|
|
11
|
+
HTTP::CookieJar::CookiestxtSaver
|
|
12
|
+
else
|
|
13
|
+
raise IndexError, 'cookie saver unavailable: %s' % symbol.inspect
|
|
28
14
|
end
|
|
29
15
|
end
|
|
30
16
|
|
|
@@ -63,3 +49,6 @@ class HTTP::CookieJar::AbstractSaver
|
|
|
63
49
|
# self
|
|
64
50
|
end
|
|
65
51
|
end
|
|
52
|
+
|
|
53
|
+
require "http/cookie_jar/yaml_saver"
|
|
54
|
+
require "http/cookie_jar/cookiestxt_saver"
|
|
@@ -6,29 +6,18 @@ class HTTP::CookieJar::AbstractStore
|
|
|
6
6
|
include MonitorMixin
|
|
7
7
|
|
|
8
8
|
class << self
|
|
9
|
-
@@class_map = {}
|
|
10
9
|
|
|
11
|
-
# Gets an implementation class by the name
|
|
12
|
-
# load "http/cookie_jar/*_store" if not found. If loading fails,
|
|
13
|
-
# IndexError is raised.
|
|
10
|
+
# Gets an implementation class by the name.
|
|
14
11
|
def implementation(symbol)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
case symbol
|
|
13
|
+
when :hash
|
|
14
|
+
HTTP::CookieJar::HashStore
|
|
15
|
+
when :mozilla
|
|
16
|
+
HTTP::CookieJar::MozillaStore
|
|
17
|
+
else
|
|
21
18
|
raise IndexError, 'cookie store unavailable: %s' % symbol.inspect
|
|
22
19
|
end
|
|
23
20
|
end
|
|
24
|
-
|
|
25
|
-
def inherited(subclass) # :nodoc:
|
|
26
|
-
@@class_map[class_to_symbol(subclass)] = subclass
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def class_to_symbol(klass) # :nodoc:
|
|
30
|
-
klass.name[/[^:]+?(?=Store$|$)/].downcase.to_sym
|
|
31
|
-
end
|
|
32
21
|
end
|
|
33
22
|
|
|
34
23
|
# Defines options and their default values.
|
|
@@ -122,3 +111,9 @@ class HTTP::CookieJar::AbstractStore
|
|
|
122
111
|
# self
|
|
123
112
|
end
|
|
124
113
|
end
|
|
114
|
+
|
|
115
|
+
require 'http/cookie_jar/hash_store'
|
|
116
|
+
|
|
117
|
+
unless defined?(JRUBY_VERSION)
|
|
118
|
+
require 'http/cookie_jar/mozilla_store'
|
|
119
|
+
end
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# :markup: markdown
|
|
2
|
-
require 'http/cookie_jar'
|
|
3
2
|
|
|
4
3
|
class HTTP::CookieJar
|
|
5
4
|
# A store class that uses a hash-based cookie store.
|
|
@@ -67,10 +66,8 @@ class HTTP::CookieJar
|
|
|
67
66
|
def each(uri = nil) # :yield: cookie
|
|
68
67
|
now = Time.now
|
|
69
68
|
if uri
|
|
70
|
-
thost = DomainName.new(uri.host)
|
|
71
69
|
tpath = uri.path
|
|
72
70
|
@jar.each { |domain, paths|
|
|
73
|
-
next unless thost.cookie_domain?(domain)
|
|
74
71
|
paths.each { |path, hash|
|
|
75
72
|
next unless HTTP::Cookie.path_match?(path, tpath)
|
|
76
73
|
hash.delete_if { |name, cookie|
|