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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d1a93009a55673a4827d9f8d85c19b5c08f4b19c
4
- data.tar.gz: a7f4a3bb7a58ded55e6edac658cb20e0ad5d0821
2
+ SHA256:
3
+ metadata.gz: 72ef3493437238f93258320d1e8bdfea5d155e731ed6e88d55b284bff3c7a3a0
4
+ data.tar.gz: ecf432149b7b13a7437ad6c8a8433b85fbe4cf223ba07016831c2da3a8598de2
5
5
  SHA512:
6
- metadata.gz: d46e2e2d42e8a5e7947ccb2b0eb187b930e1e1dcb5912b75ffd78aca7532af0b9144d0210b7ca46ec3c4d591cfd8c742b64e393c60fda814d7ce75ae2aaada26
7
- data.tar.gz: 5debdf55ddc8886db1e4e117e13829f6f93e2f08364126c0c693ed4dfde469374c49a35bef3f5b18455ab5379bf1289b386f30ebbae25603b4c5725beb2c231e
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Akinori MUSHA
1
+ Copyright (c) 2013-2026 Akinori MUSHA
2
2
  Copyright (c) 2011-2012 Akinori MUSHA, Eric Hodel
3
3
  Copyright (c) 2006-2011 Aaron Patterson, Mike Dalessio
4
4
 
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/http-cookie.svg)](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 domain_name gem.
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 raise runtime errors to help migration, so
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
 
@@ -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
@@ -1,5 +1,5 @@
1
1
  module HTTP
2
2
  class Cookie
3
- VERSION = "1.0.3"
3
+ VERSION = "1.1.6"
4
4
  end
5
5
  end
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 = URI(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 = URI(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 = URI(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 = URI(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
- # Gets an implementation class by the name, optionally trying to
9
- # load "http/cookie_jar/*_saver" if not found. If loading fails,
10
- # IndexError is raised.
11
- def implementation(symbol)
12
- @@class_map.fetch(symbol)
13
- rescue IndexError
14
- begin
15
- require 'http/cookie_jar/%s_saver' % symbol
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, optionally trying to
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
- @@class_map.fetch(symbol)
16
- rescue IndexError
17
- begin
18
- require 'http/cookie_jar/%s_store' % symbol
19
- @@class_map.fetch(symbol)
20
- rescue LoadError, IndexError
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
  # CookiestxtSaver saves and loads cookies in the cookies.txt format.
5
4
  class HTTP::CookieJar::CookiestxtSaver < HTTP::CookieJar::AbstractSaver
@@ -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|