cookie_store 0.1.4 → 0.2
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/.github/workflows/ci.yml +23 -0
- data/.gitignore +5 -0
- data/.tm_properties +1 -0
- data/cookie_store.gemspec +6 -3
- data/lib/cookie_store.rb +4 -2
- data/lib/cookie_store/cookie.rb +23 -91
- data/lib/cookie_store/cookie_parser.rb +110 -0
- data/lib/cookie_store/version.rb +3 -0
- data/test/cookie_store/cookie_test.rb +75 -23
- data/test/test_helper.rb +18 -1
- metadata +53 -8
- data/Gemfile.lock +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ed1b21def909112649960bb17b6e9f15291b27a45e1121111ba7fac8bc6944ca
|
4
|
+
data.tar.gz: 2c8066581ac182115e759ddf0421ce9e2a3ecc8c3bc6feab292efa9a2c9a3c16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8db6b08273b5324d8866709e52af11eefe89538c891cf5d551160a51df4386a612defb0e8f560e55d406fcbbf15add61b415b56ffb2c933877d66e7ee557589d
|
7
|
+
data.tar.gz: 1049c26606be9fe1585377c983357958416bd842a4e36c41cac7107f8f58841fadd003e29cf2e98cef5ff6f1d67078f0af9461b58783a7f0f0e15632b4d6c63e
|
@@ -0,0 +1,23 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
stream_parser:
|
11
|
+
name: CookieStore Test
|
12
|
+
runs-on: ubuntu-20.04
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- uses: ruby/setup-ruby@v1
|
16
|
+
with:
|
17
|
+
ruby-version: 3.0
|
18
|
+
|
19
|
+
- uses: actions/checkout@v2
|
20
|
+
|
21
|
+
- run: bundle
|
22
|
+
|
23
|
+
- run: bundle exec rake test
|
data/.gitignore
ADDED
data/.tm_properties
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
exclude = '{$exclude,log,tmp,.tm_properties,coverage}'
|
data/cookie_store.gemspec
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
1
|
+
require_relative 'lib/cookie_store/version'
|
3
2
|
|
4
3
|
Gem::Specification.new do |s|
|
5
4
|
s.name = "cookie_store"
|
6
|
-
s.version =
|
5
|
+
s.version = CookieStore::VERSION
|
7
6
|
s.authors = ["Jon Bracy"]
|
8
7
|
s.email = ["jonbracy@gmail.com"]
|
9
8
|
s.homepage = "https://github.com/malomalo/cookie_store"
|
@@ -14,8 +13,11 @@ Gem::Specification.new do |s|
|
|
14
13
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
14
|
s.require_paths = ["lib"]
|
16
15
|
|
16
|
+
s.add_runtime_dependency 'stream_parser', '>= 0.2'
|
17
|
+
|
17
18
|
# Developoment
|
18
19
|
s.add_development_dependency 'rake'
|
20
|
+
s.add_development_dependency 'byebug'
|
19
21
|
# s.add_development_dependency 'rdoc'
|
20
22
|
# s.add_development_dependency 'sdoc'
|
21
23
|
s.add_development_dependency 'minitest'
|
@@ -24,4 +26,5 @@ Gem::Specification.new do |s|
|
|
24
26
|
s.add_development_dependency 'faker'
|
25
27
|
s.add_development_dependency 'webmock'
|
26
28
|
s.add_development_dependency 'activesupport'
|
29
|
+
s.add_development_dependency 'simplecov'
|
27
30
|
end
|
data/lib/cookie_store.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'uri'
|
2
2
|
|
3
3
|
class CookieStore
|
4
|
+
|
5
|
+
autoload :CookieParser, 'cookie_store/cookie_parser'
|
4
6
|
|
5
7
|
# Maximum number of bytes per cookie (RFC 6265 6.1 requires at least 4096)
|
6
8
|
MAX_COOKIE_LENGTH = 4096
|
@@ -15,14 +17,14 @@ class CookieStore
|
|
15
17
|
def set_cookie(request_uri, set_cookie_value)
|
16
18
|
request_uri = URI.parse(request_uri)
|
17
19
|
|
18
|
-
CookieStore::Cookie.parse_cookies(request_uri, set_cookie_value)
|
20
|
+
CookieStore::Cookie.parse_cookies(request_uri, set_cookie_value) do |cookie|
|
19
21
|
# reject as per RFC2965 Section 3.3.2
|
20
22
|
return if !cookie.request_match?(request_uri) || !(cookie.domain =~ /.+\..+/ || cookie.domain == 'localhost')
|
21
23
|
|
22
24
|
# reject cookies over the max-bytes
|
23
25
|
return if cookie.to_s.size > MAX_COOKIE_LENGTH
|
24
26
|
|
25
|
-
add(cookie)
|
27
|
+
add(cookie)
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
data/lib/cookie_store/cookie.rb
CHANGED
@@ -1,37 +1,7 @@
|
|
1
1
|
class CookieStore::Cookie
|
2
2
|
|
3
|
-
|
4
|
-
LWS = "\\r\\n(?:[ \\t]+)"
|
5
|
-
QDTEXT = "[\\t\\x20-\\x21\\x23-\\x3A\\x3C-\\x7E\\x80-\\xFF]|(?:#{LWS})"
|
6
|
-
QUOTED_TEXT = "(?:#{QUOTED_PAIR}|#{QDTEXT})*"
|
7
|
-
IPADDR = /\A#{URI::REGEXP::PATTERN::IPV4ADDR}\Z|\A#{URI::REGEXP::PATTERN::IPV6ADDR}\Z/
|
8
|
-
|
9
|
-
TOKEN = '[^(),\/<>@;:\\\"\[\]?={}\s]+'
|
10
|
-
VALUE = "(?:#{TOKEN}|#{IPADDR}|[^,;\\s]+)"
|
11
|
-
EXPIRES_AT_VALUE = '[A-Za-z]{3},\ \d{2}[-\ ][A-Za-z]{3}[-\ ]\d{4}\ \d{2}:\d{2}:\d{2}\ (?:[A-Z]{3}|[-+]\d{4})'
|
12
|
-
NUMERICAL_TIMEZONE = /[-+]\d{4}$/
|
13
|
-
|
14
|
-
|
15
|
-
COOKIE = /(?<name>#{TOKEN})=(?:"(?<quoted_value>#{QUOTED_TEXT})"|(?<value>#{VALUE}))(?<attributes>.*)/n
|
16
|
-
COOKIE_AV = %r{
|
17
|
-
;\s+
|
18
|
-
(?<key>#{TOKEN})
|
19
|
-
(?:
|
20
|
-
=
|
21
|
-
(?:
|
22
|
-
"(?<quoted_value>#{QUOTED_TEXT})"
|
23
|
-
|
|
24
|
-
(?<value>#{EXPIRES_AT_VALUE}|#{VALUE})
|
25
|
-
)
|
26
|
-
){0,1}
|
27
|
-
}nx
|
28
|
-
COOKIES = %r{
|
29
|
-
#{TOKEN}=(?:"#{QUOTED_TEXT}"|#{VALUE})
|
30
|
-
(?:;\s+#{TOKEN}(?:=(?:"#{QUOTED_TEXT}"|(?:#{EXPIRES_AT_VALUE}|#{VALUE}))){0,1})*
|
31
|
-
}nx
|
32
|
-
|
3
|
+
IPADDR = /\A#{URI::REGEXP::PATTERN::IPV4ADDR}\Z|\A#{URI::REGEXP::PATTERN::IPV6ADDR}\Z/
|
33
4
|
|
34
|
-
|
35
5
|
# [String] The name of the cookie.
|
36
6
|
attr_reader :name
|
37
7
|
|
@@ -87,7 +57,7 @@ class CookieStore::Cookie
|
|
87
57
|
# [Time] Time when this cookie was first evaluated and created.
|
88
58
|
attr_reader :created_at
|
89
59
|
|
90
|
-
def initialize(name, value,
|
60
|
+
def initialize(name, value, attributes={})
|
91
61
|
@name = name
|
92
62
|
@value = value
|
93
63
|
@secure = false
|
@@ -96,8 +66,12 @@ class CookieStore::Cookie
|
|
96
66
|
@discard = false
|
97
67
|
@created_at = Time.now
|
98
68
|
|
99
|
-
|
100
|
-
|
69
|
+
@attributes = attributes
|
70
|
+
|
71
|
+
%i{name value domain path secure http_only version comment comment_url discard ports expires max_age created_at}.each do |attr_name|
|
72
|
+
if attributes.has_key?(attr_name)
|
73
|
+
self.instance_variable_set(:"@#{attr_name}", attributes[attr_name])
|
74
|
+
end
|
101
75
|
end
|
102
76
|
end
|
103
77
|
|
@@ -186,70 +160,28 @@ class CookieStore::Cookie
|
|
186
160
|
ports.include?(request_port)
|
187
161
|
end
|
188
162
|
|
189
|
-
def self.
|
190
|
-
|
191
|
-
cookies = []
|
192
|
-
set_cookie_value.scan(COOKIES) do |cookie|
|
193
|
-
cookies << parse(uri, cookie)
|
194
|
-
end
|
195
|
-
cookies
|
163
|
+
def self.parse(request_uri, set_cookie_value)
|
164
|
+
parse_cookies(request_uri, set_cookie_value).first
|
196
165
|
end
|
197
166
|
|
198
|
-
def self.
|
167
|
+
def self.parse_cookies(request_uri, set_cookie_value)
|
199
168
|
uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
|
200
|
-
data = COOKIE.match(set_cookie_value)
|
201
|
-
options = {}
|
202
|
-
|
203
|
-
if !data
|
204
|
-
raise Net::HTTPHeaderSyntaxError.new("Invalid Set-Cookie header format")
|
205
|
-
end
|
206
169
|
|
207
|
-
|
208
|
-
|
209
|
-
|
170
|
+
cookies = []
|
171
|
+
CookieStore::CookieParser.parse(set_cookie_value) do |parsed|
|
172
|
+
parsed[:attributes][:domain] ||= uri.host.downcase
|
173
|
+
parsed[:attributes][:path] ||= uri.path
|
174
|
+
|
175
|
+
cookie = CookieStore::Cookie.new(parsed[:key], parsed[:value], parsed[:attributes])
|
210
176
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
when 'commenturl'
|
216
|
-
options[:comment_url] = value
|
217
|
-
when 'discard'
|
218
|
-
options[:discard] = true
|
219
|
-
when 'domain'
|
220
|
-
if value =~ IPADDR
|
221
|
-
options[:domain] = value
|
222
|
-
else
|
223
|
-
# As per RFC2965 if a host name contains no dots, the effective host name is
|
224
|
-
# that name with the string .local appended to it.
|
225
|
-
value = "#{value}.local" if !value.include?('.')
|
226
|
-
options[:domain] = (value.start_with?('.') ? value : ".#{value}").downcase
|
227
|
-
end
|
228
|
-
when 'expires'
|
229
|
-
if value.include?('-') && !value.match(NUMERICAL_TIMEZONE)
|
230
|
-
options[:expires] = DateTime.strptime(value, '%a, %d-%b-%Y %H:%M:%S %Z')
|
231
|
-
else
|
232
|
-
options[:expires] = DateTime.strptime(value, '%a, %d %b %Y %H:%M:%S %Z')
|
233
|
-
end
|
234
|
-
when 'max-age'
|
235
|
-
options[:max_age] = value.to_i
|
236
|
-
when 'path'
|
237
|
-
options[:path] = value
|
238
|
-
when 'port'
|
239
|
-
options[:ports] = value.split(',').map(&:to_i)
|
240
|
-
when 'secure'
|
241
|
-
options[:secure] = true
|
242
|
-
when 'httponly'
|
243
|
-
options[:http_only] = true
|
244
|
-
when 'version'
|
245
|
-
options[:version] = value.to_i
|
246
|
-
end
|
177
|
+
cookies << if block_given?
|
178
|
+
yield(cookie)
|
179
|
+
else
|
180
|
+
cookie
|
247
181
|
end
|
248
182
|
end
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
CookieStore::Cookie.new(data[:name], data[:value] || data[:quoted_value].gsub(/\\(.)/, '\1'), options)
|
183
|
+
|
184
|
+
cookies
|
253
185
|
end
|
254
186
|
|
255
187
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'stream_parser'
|
2
|
+
|
3
|
+
class CookieStore::CookieParser
|
4
|
+
|
5
|
+
include StreamParser
|
6
|
+
|
7
|
+
NUMERICAL_TIMEZONE = /[-+]\d{4}\Z/
|
8
|
+
|
9
|
+
def parse
|
10
|
+
cookie = {attributes: {}}
|
11
|
+
|
12
|
+
@stack = [:cookie_name]
|
13
|
+
while !eos?
|
14
|
+
case @stack.last
|
15
|
+
when :cookie_name
|
16
|
+
scan_until(/\s*=\s*/)
|
17
|
+
if match == '='
|
18
|
+
@stack << :cookie_value
|
19
|
+
cookie[:key] = pre_match
|
20
|
+
end
|
21
|
+
when :cookie_value
|
22
|
+
scan_until(/\s*(['";]\s*|\Z)/)
|
23
|
+
if match.strip == '"' || match.strip == "'"
|
24
|
+
cookie[:value] = quoted_value(match.strip)
|
25
|
+
@stack.pop
|
26
|
+
@stack << :cookie_attributes
|
27
|
+
elsif match
|
28
|
+
cookie[:value] = pre_match
|
29
|
+
@stack.pop
|
30
|
+
@stack << :cookie_attributes
|
31
|
+
end
|
32
|
+
when :cookie_attributes
|
33
|
+
# RFC 2109 4.1, Attributes (names) are case-insensitive
|
34
|
+
scan_until(/[,=;]\s*/)
|
35
|
+
if match&.start_with?('=')
|
36
|
+
key = normalize_key(pre_match)
|
37
|
+
scan_until(key == :expires ? /\s*((?<!\w{3}),|['";])\s*/ : /\s*(['";,]\s*|\Z)/)
|
38
|
+
if match =~ /["']\s*\Z/
|
39
|
+
cookie[:attributes][key] = normalize_attribute_value(key, quoted_value(match.strip))
|
40
|
+
elsif match =~ /,\s*\Z/
|
41
|
+
cookie[:attributes][key] = normalize_attribute_value(key, pre_match)
|
42
|
+
yield(cookie)
|
43
|
+
cookie = {attributes: {}}
|
44
|
+
@stack.pop
|
45
|
+
else
|
46
|
+
cookie[:attributes][key] = normalize_attribute_value(key, pre_match)
|
47
|
+
end
|
48
|
+
elsif match&.start_with?(',')
|
49
|
+
yield(cookie)
|
50
|
+
cookie = {attributes: {}}
|
51
|
+
@stack.pop
|
52
|
+
else
|
53
|
+
cookie[:attributes][normalize_key(pre_match)] = true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
yield(cookie)
|
59
|
+
end
|
60
|
+
|
61
|
+
def normalize_key(key)
|
62
|
+
key = key.downcase.gsub('-','_')
|
63
|
+
if key == 'port'
|
64
|
+
:ports
|
65
|
+
elsif key == 'httponly'
|
66
|
+
:http_only
|
67
|
+
elsif key == 'commenturl'
|
68
|
+
:comment_url
|
69
|
+
else
|
70
|
+
key.to_sym
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def normalize_attribute_value(key, value)
|
75
|
+
case key
|
76
|
+
when :domain
|
77
|
+
if value =~ CookieStore::Cookie::IPADDR
|
78
|
+
value
|
79
|
+
else
|
80
|
+
# As per RFC2965 if a host name contains no dots, the effective host
|
81
|
+
# name is that name with the string .local appended to it.
|
82
|
+
value = "#{value}.local" if !value.include?('.')
|
83
|
+
(value.start_with?('.') ? value : ".#{value}").downcase
|
84
|
+
end
|
85
|
+
when :expires
|
86
|
+
byebug if $debug
|
87
|
+
case value
|
88
|
+
when /\w{3}, \d{2}-\w{3}-\d{2} /
|
89
|
+
DateTime.strptime(value, '%a, %d-%b-%y %H:%M:%S %Z')
|
90
|
+
when /\w{3}, \d{2}-\w{3}-\d{4} /
|
91
|
+
DateTime.strptime(value, '%a, %d-%b-%Y %H:%M:%S %Z')
|
92
|
+
when /\w{3}, \d{2} \w{3} \d{2} /
|
93
|
+
DateTime.strptime(value, '%a, %d %b %y %H:%M:%S %Z')
|
94
|
+
when /\w{3}, \d{2} \w{3} \d{4} /
|
95
|
+
DateTime.strptime(value, '%a, %d %b %Y %H:%M:%S %Z')
|
96
|
+
else
|
97
|
+
DateTime.parse(value)
|
98
|
+
end
|
99
|
+
when :max_age
|
100
|
+
value&.to_i
|
101
|
+
when :ports
|
102
|
+
value.split(',').map(&:to_i)
|
103
|
+
when :version
|
104
|
+
value.to_i
|
105
|
+
else
|
106
|
+
value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -13,7 +13,7 @@ class CookieStore::CookieTest < Minitest::Test
|
|
13
13
|
|
14
14
|
test "::new(name, value, options)" do
|
15
15
|
#TODO: test all options are set
|
16
|
-
cookie = CookieStore::Cookie.new('foo', 'bar', :
|
16
|
+
cookie = CookieStore::Cookie.new('foo', 'bar', domain: 'test.com')
|
17
17
|
|
18
18
|
assert_equal 'test.com', cookie.domain
|
19
19
|
end
|
@@ -27,7 +27,7 @@ class CookieStore::CookieTest < Minitest::Test
|
|
27
27
|
'123.456.57.21' => '123.456.57.21'
|
28
28
|
#TODO: not sure how ipv6 works '[E3D7::51F4:9BC8:C0A8:6420]' => '[E3D7::51F4:9BC8:C0A8:6420]'
|
29
29
|
}.each do |host, cookie_host|
|
30
|
-
cookie = CookieStore::Cookie.new('key', 'value', :
|
30
|
+
cookie = CookieStore::Cookie.new('key', 'value', domain: cookie_host)
|
31
31
|
assert_equal true, cookie.domain_match(host)
|
32
32
|
end
|
33
33
|
|
@@ -43,7 +43,7 @@ class CookieStore::CookieTest < Minitest::Test
|
|
43
43
|
'123.456.57.21' => '.123.456.57.21'
|
44
44
|
#TODO: not sure how ipv6 works '[E3D7::51F4:9BC8:C0A8:6420]' => '[E3D7::51F4:9BC8:C0A8:6421]'
|
45
45
|
}.each do |host, cookie_host|
|
46
|
-
cookie = CookieStore::Cookie.new('key', 'value', :
|
46
|
+
cookie = CookieStore::Cookie.new('key', 'value', domain: cookie_host)
|
47
47
|
assert_equal false, cookie.domain_match(host)
|
48
48
|
end
|
49
49
|
end
|
@@ -55,7 +55,7 @@ class CookieStore::CookieTest < Minitest::Test
|
|
55
55
|
'/test' => '/',
|
56
56
|
'/this/is/my/url' => '/this/is'
|
57
57
|
}.each do |path, cookie_path|
|
58
|
-
cookie = CookieStore::Cookie.new('key', 'value', :
|
58
|
+
cookie = CookieStore::Cookie.new('key', 'value', path: cookie_path)
|
59
59
|
assert_equal true, cookie.path_match(path)
|
60
60
|
end
|
61
61
|
|
@@ -63,7 +63,7 @@ class CookieStore::CookieTest < Minitest::Test
|
|
63
63
|
'/test' => '/rest',
|
64
64
|
'/' => '/test'
|
65
65
|
}.each do |path, cookie_path|
|
66
|
-
cookie = CookieStore::Cookie.new('key', 'value', :
|
66
|
+
cookie = CookieStore::Cookie.new('key', 'value', path: cookie_path)
|
67
67
|
assert_equal false, cookie.path_match(path)
|
68
68
|
end
|
69
69
|
end
|
@@ -76,7 +76,7 @@ class CookieStore::CookieTest < Minitest::Test
|
|
76
76
|
end
|
77
77
|
|
78
78
|
test "::port_match(request_port) with ports attribute set" do
|
79
|
-
cookie = CookieStore::Cookie.new('key', 'value', :
|
79
|
+
cookie = CookieStore::Cookie.new('key', 'value', ports: [80, 8700])
|
80
80
|
assert_equal true, cookie.port_match(8700)
|
81
81
|
assert_equal false, cookie.port_match(87)
|
82
82
|
end
|
@@ -97,14 +97,19 @@ class CookieStore::CookieTest < Minitest::Test
|
|
97
97
|
|
98
98
|
test "#expires_at perfers max-age to expires" do
|
99
99
|
travel_to Time.new(2013, 12, 13, 8, 26, 12, 0) do
|
100
|
-
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Max-Age=3600 Expires="Wed, 13 Jan 2021 22:23:01 GMT"')
|
100
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Max-Age=3600; Expires="Wed, 13 Jan 2021 22:23:01 GMT"')
|
101
101
|
assert_equal Time.new(2013, 12, 13, 9, 26, 12, 0), cookie.expires_at
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
105
|
test "#expires_at returns nil if no max-age or expires attribute" do
|
106
106
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar')
|
107
|
-
|
107
|
+
assert_nil cookie.expires_at
|
108
|
+
end
|
109
|
+
|
110
|
+
test "date formats" do
|
111
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foor=bar; expires=Fri, 04-Jun-21 14:13:58 GMT; path=/;')
|
112
|
+
assert_equal DateTime.new(2021, 6, 04, 14, 13, 58, 0), cookie.expires_at
|
108
113
|
end
|
109
114
|
|
110
115
|
# CookieStore::Cookie.expired? =========================================================
|
@@ -188,13 +193,13 @@ class CookieStore::CookieTest < Minitest::Test
|
|
188
193
|
assert_equal '/test', cookie.path
|
189
194
|
assert_equal false, cookie.secure
|
190
195
|
assert_equal false, cookie.http_only
|
191
|
-
|
192
|
-
|
196
|
+
assert_nil cookie.comment
|
197
|
+
assert_nil cookie.comment_url
|
193
198
|
assert_equal 1, cookie.version
|
194
199
|
assert_equal false, cookie.discard
|
195
|
-
|
196
|
-
|
197
|
-
|
200
|
+
assert_nil cookie.ports
|
201
|
+
assert_nil cookie.expires
|
202
|
+
assert_nil cookie.max_age
|
198
203
|
end
|
199
204
|
|
200
205
|
test "::parse a cookie with options" do
|
@@ -206,13 +211,13 @@ class CookieStore::CookieTest < Minitest::Test
|
|
206
211
|
assert_equal '/', cookie.path
|
207
212
|
assert_equal false, cookie.secure
|
208
213
|
assert_equal true, cookie.http_only
|
209
|
-
|
210
|
-
|
214
|
+
assert_nil cookie.comment
|
215
|
+
assert_nil cookie.comment_url
|
211
216
|
assert_equal 1, cookie.version
|
212
217
|
assert_equal false, cookie.discard
|
213
|
-
|
214
|
-
|
215
|
-
|
218
|
+
assert_nil cookie.ports
|
219
|
+
assert_nil cookie.expires
|
220
|
+
assert_nil cookie.max_age
|
216
221
|
end
|
217
222
|
|
218
223
|
test "::parse normalizes the request domain" do
|
@@ -234,9 +239,9 @@ class CookieStore::CookieTest < Minitest::Test
|
|
234
239
|
test "::parse a simple quoted cookie" do
|
235
240
|
cookie = CookieStore::Cookie.parse('http://google.com/test', 'foo="b\"ar"')
|
236
241
|
|
237
|
-
assert_equal 'google.com',
|
238
|
-
assert_equal 'foo',
|
239
|
-
assert_equal 'b"ar',
|
242
|
+
assert_equal 'google.com', cookie.domain
|
243
|
+
assert_equal 'foo', cookie.name
|
244
|
+
assert_equal 'b"ar', cookie.value
|
240
245
|
end
|
241
246
|
|
242
247
|
test "::parse domain attribute without leading ." do
|
@@ -312,6 +317,19 @@ class CookieStore::CookieTest < Minitest::Test
|
|
312
317
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 2021 22:23:01 GMT"')
|
313
318
|
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
314
319
|
|
320
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13 Jan 2021 22:23:01 GMT'")
|
321
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
322
|
+
|
323
|
+
# Wed, 13 Jan 21 22:23:01 GMT format
|
324
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13 Jan 21 22:23:01 GMT')
|
325
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
326
|
+
|
327
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 21 22:23:01 GMT"')
|
328
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
329
|
+
|
330
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13 Jan 21 22:23:01 GMT'")
|
331
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
332
|
+
|
315
333
|
# Wed, 13-Jan-2021 22:23:01 GMT format
|
316
334
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13-Jan-2021 22:23:01 GMT')
|
317
335
|
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
@@ -319,12 +337,38 @@ class CookieStore::CookieTest < Minitest::Test
|
|
319
337
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13-Jan-2021 22:23:01 GMT"')
|
320
338
|
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
321
339
|
|
340
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13-Jan-2021 22:23:01 GMT'")
|
341
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
342
|
+
|
343
|
+
# Wed, 13-Jan-21 22:23:01 GMT format
|
344
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13-Jan-21 22:23:01 GMT')
|
345
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
346
|
+
|
347
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13-Jan-21 22:23:01 GMT"')
|
348
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
349
|
+
|
350
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13-Jan-21 22:23:01 GMT'")
|
351
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
352
|
+
|
322
353
|
# Wed, 13 Jan 2021 22:23:01 -0000 format
|
323
354
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13 Jan 2021 22:23:01 -0000')
|
324
355
|
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
325
356
|
|
326
357
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 2021 22:23:01 +0000"')
|
327
358
|
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
359
|
+
|
360
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13 Jan 2021 22:23:01 +0000'")
|
361
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
362
|
+
|
363
|
+
# Wed, 13 Jan 21 22:23:01 -0000 format
|
364
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13 Jan 21 22:23:01 -0000')
|
365
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
366
|
+
|
367
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 21 22:23:01 +0000"')
|
368
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
369
|
+
|
370
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13 Jan 21 22:23:01 +0000'")
|
371
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
328
372
|
end
|
329
373
|
|
330
374
|
test "::parse max_age attribute" do
|
@@ -354,7 +398,15 @@ class CookieStore::CookieTest < Minitest::Test
|
|
354
398
|
assert_equal true, cookies[1].http_only
|
355
399
|
end
|
356
400
|
|
357
|
-
#
|
358
|
-
|
401
|
+
# CookieStore::Cookie parse invalid cookies =========================================================
|
402
|
+
test "unclosed quotes" do
|
403
|
+
assert_raises Net::HTTPHeaderSyntaxError do
|
404
|
+
CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Max-Age="3660')
|
405
|
+
end
|
406
|
+
|
407
|
+
assert_raises Net::HTTPHeaderSyntaxError do
|
408
|
+
CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Max-Age='3660")
|
409
|
+
end
|
410
|
+
end
|
359
411
|
|
360
412
|
end
|
data/test/test_helper.rb
CHANGED
@@ -6,6 +6,9 @@ lib = File.expand_path(File.join(root, 'lib'))
|
|
6
6
|
|
7
7
|
$LOAD_PATH << lib
|
8
8
|
|
9
|
+
require 'simplecov'
|
10
|
+
SimpleCov.start
|
11
|
+
|
9
12
|
require 'cookie_store'
|
10
13
|
require "minitest/autorun"
|
11
14
|
require 'minitest/unit'
|
@@ -13,12 +16,18 @@ require 'minitest/reporters'
|
|
13
16
|
require 'faker'
|
14
17
|
require 'webmock/minitest'
|
15
18
|
require "mocha"
|
16
|
-
require "mocha/
|
19
|
+
require "mocha/minitest"
|
17
20
|
require 'active_support/time'
|
18
21
|
require 'active_support/testing/time_helpers'
|
22
|
+
require "byebug"
|
19
23
|
|
20
24
|
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
21
25
|
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
$debug = false
|
30
|
+
|
22
31
|
# File 'lib/active_support/testing/declarative.rb', somewhere in rails....
|
23
32
|
class Minitest::Test
|
24
33
|
include ActiveSupport::Testing::TimeHelpers
|
@@ -36,4 +45,12 @@ class Minitest::Test
|
|
36
45
|
end
|
37
46
|
end
|
38
47
|
|
48
|
+
def debug
|
49
|
+
$debug = true
|
50
|
+
puts '=========================='
|
51
|
+
yield
|
52
|
+
ensure
|
53
|
+
puts '=========================='
|
54
|
+
$debug = false
|
55
|
+
end
|
39
56
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cookie_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Bracy
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: stream_parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.2'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rake
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +38,20 @@ dependencies:
|
|
24
38
|
- - ">="
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: minitest
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +136,20 @@ dependencies:
|
|
108
136
|
- - ">="
|
109
137
|
- !ruby/object:Gem::Version
|
110
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: simplecov
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
111
153
|
description: A Ruby library to handle client-side HTTP cookies
|
112
154
|
email:
|
113
155
|
- jonbracy@gmail.com
|
@@ -115,15 +157,19 @@ executables: []
|
|
115
157
|
extensions: []
|
116
158
|
extra_rdoc_files: []
|
117
159
|
files:
|
160
|
+
- ".github/workflows/ci.yml"
|
161
|
+
- ".gitignore"
|
162
|
+
- ".tm_properties"
|
118
163
|
- Gemfile
|
119
|
-
- Gemfile.lock
|
120
164
|
- LICENSE
|
121
165
|
- README.md
|
122
166
|
- Rakefile
|
123
167
|
- cookie_store.gemspec
|
124
168
|
- lib/cookie_store.rb
|
125
169
|
- lib/cookie_store/cookie.rb
|
170
|
+
- lib/cookie_store/cookie_parser.rb
|
126
171
|
- lib/cookie_store/hash_store.rb
|
172
|
+
- lib/cookie_store/version.rb
|
127
173
|
- test/cookie_store/cookie_test.rb
|
128
174
|
- test/cookie_store/hash_store_test.rb
|
129
175
|
- test/cookie_store_test.rb
|
@@ -131,7 +177,7 @@ files:
|
|
131
177
|
homepage: https://github.com/malomalo/cookie_store
|
132
178
|
licenses: []
|
133
179
|
metadata: {}
|
134
|
-
post_install_message:
|
180
|
+
post_install_message:
|
135
181
|
rdoc_options: []
|
136
182
|
require_paths:
|
137
183
|
- lib
|
@@ -146,9 +192,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
192
|
- !ruby/object:Gem::Version
|
147
193
|
version: '0'
|
148
194
|
requirements: []
|
149
|
-
|
150
|
-
|
151
|
-
signing_key:
|
195
|
+
rubygems_version: 3.2.3
|
196
|
+
signing_key:
|
152
197
|
specification_version: 4
|
153
198
|
summary: A Ruby library to handle client-side HTTP cookies
|
154
199
|
test_files:
|
data/Gemfile.lock
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
cookie_store (0.1.4)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
activesupport (4.1.8)
|
10
|
-
i18n (~> 0.6, >= 0.6.9)
|
11
|
-
json (~> 1.7, >= 1.7.7)
|
12
|
-
minitest (~> 5.1)
|
13
|
-
thread_safe (~> 0.1)
|
14
|
-
tzinfo (~> 1.1)
|
15
|
-
addressable (2.3.6)
|
16
|
-
ansi (1.4.3)
|
17
|
-
builder (3.2.2)
|
18
|
-
crack (0.4.2)
|
19
|
-
safe_yaml (~> 1.0.0)
|
20
|
-
faker (1.4.3)
|
21
|
-
i18n (~> 0.5)
|
22
|
-
i18n (0.6.11)
|
23
|
-
json (1.8.1)
|
24
|
-
metaclass (0.0.4)
|
25
|
-
minitest (5.5.0)
|
26
|
-
minitest-reporters (1.0.8)
|
27
|
-
ansi
|
28
|
-
builder
|
29
|
-
minitest (>= 5.0)
|
30
|
-
ruby-progressbar
|
31
|
-
mocha (1.1.0)
|
32
|
-
metaclass (~> 0.0.1)
|
33
|
-
rake (10.4.2)
|
34
|
-
ruby-progressbar (1.7.0)
|
35
|
-
safe_yaml (1.0.4)
|
36
|
-
thread_safe (0.3.4)
|
37
|
-
tzinfo (1.2.2)
|
38
|
-
thread_safe (~> 0.1)
|
39
|
-
webmock (1.20.4)
|
40
|
-
addressable (>= 2.3.6)
|
41
|
-
crack (>= 0.3.2)
|
42
|
-
|
43
|
-
PLATFORMS
|
44
|
-
ruby
|
45
|
-
|
46
|
-
DEPENDENCIES
|
47
|
-
activesupport
|
48
|
-
cookie_store!
|
49
|
-
faker
|
50
|
-
minitest
|
51
|
-
minitest-reporters
|
52
|
-
mocha
|
53
|
-
rake
|
54
|
-
webmock
|
55
|
-
|
56
|
-
BUNDLED WITH
|
57
|
-
1.10.4
|