cookie_store 0.1.4 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|