cookie_store 0.1.0 → 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/Gemfile +4 -0
- data/README.md +1 -1
- data/cookie_store.gemspec +10 -5
- data/lib/cookie_store.rb +10 -7
- data/lib/cookie_store/cookie.rb +25 -76
- data/lib/cookie_store/cookie_parser.rb +110 -0
- data/lib/cookie_store/version.rb +3 -0
- data/test/cookie_store/cookie_test.rb +117 -18
- data/test/cookie_store_test.rb +10 -1
- data/test/test_helper.rb +19 -1
- metadata +98 -11
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/Gemfile
ADDED
data/README.md
CHANGED
data/cookie_store.gemspec
CHANGED
@@ -1,25 +1,30 @@
|
|
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 =
|
7
|
-
s.licenses = ['MIT']
|
5
|
+
s.version = CookieStore::VERSION
|
8
6
|
s.authors = ["Jon Bracy"]
|
9
7
|
s.email = ["jonbracy@gmail.com"]
|
10
8
|
s.homepage = "https://github.com/malomalo/cookie_store"
|
11
9
|
s.summary = %q{A Ruby library to handle client-side HTTP cookies}
|
12
|
-
s.description = %q{A Ruby library to handle
|
10
|
+
s.description = %q{A Ruby library to handle client-side HTTP cookies}
|
13
11
|
|
14
12
|
s.files = `git ls-files`.split("\n")
|
15
13
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
14
|
s.require_paths = ["lib"]
|
17
15
|
|
16
|
+
s.add_runtime_dependency 'stream_parser', '>= 0.2'
|
17
|
+
|
18
18
|
# Developoment
|
19
19
|
s.add_development_dependency 'rake'
|
20
|
+
s.add_development_dependency 'byebug'
|
20
21
|
# s.add_development_dependency 'rdoc'
|
21
22
|
# s.add_development_dependency 'sdoc'
|
22
23
|
s.add_development_dependency 'minitest'
|
23
24
|
s.add_development_dependency 'minitest-reporters'
|
24
25
|
s.add_development_dependency 'mocha'
|
26
|
+
s.add_development_dependency 'faker'
|
27
|
+
s.add_development_dependency 'webmock'
|
28
|
+
s.add_development_dependency 'activesupport'
|
29
|
+
s.add_development_dependency 'simplecov'
|
25
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
|
@@ -14,15 +16,16 @@ class CookieStore
|
|
14
16
|
# Read and set the cookie from the Set-Cookie header
|
15
17
|
def set_cookie(request_uri, set_cookie_value)
|
16
18
|
request_uri = URI.parse(request_uri)
|
17
|
-
cookie = CookieStore::Cookie.parse(request_uri, set_cookie_value)
|
18
|
-
|
19
|
-
# reject as per RFC2965 Section 3.3.2
|
20
|
-
return if !cookie.request_match?(request_uri) || !(cookie.domain =~ /.+\..+/)
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
CookieStore::Cookie.parse_cookies(request_uri, set_cookie_value) do |cookie|
|
21
|
+
# reject as per RFC2965 Section 3.3.2
|
22
|
+
return if !cookie.request_match?(request_uri) || !(cookie.domain =~ /.+\..+/ || cookie.domain == 'localhost')
|
24
23
|
|
25
|
-
|
24
|
+
# reject cookies over the max-bytes
|
25
|
+
return if cookie.to_s.size > MAX_COOKIE_LENGTH
|
26
|
+
|
27
|
+
add(cookie)
|
28
|
+
end
|
26
29
|
end
|
27
30
|
|
28
31
|
def cookie_header_for(request_uri)
|
data/lib/cookie_store/cookie.rb
CHANGED
@@ -1,29 +1,7 @@
|
|
1
1
|
class CookieStore::Cookie
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
QDTEXT = "[\\t\\x20-\\x21\\x23-\\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}|#{QUOTED_TEXT})"
|
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}'
|
12
|
-
|
13
|
-
COOKIE = /(?<name>#{TOKEN})=(?:"(?<quoted_value>#{QUOTED_TEXT})"|(?<value>#{VALUE}))(?<attributes>.*)/n
|
14
|
-
COOKIE_AV = %r{
|
15
|
-
;\s+
|
16
|
-
(?<key>#{TOKEN})
|
17
|
-
(?:
|
18
|
-
=
|
19
|
-
(?:
|
20
|
-
"(?<quoted_value>#{QUOTED_TEXT})"
|
21
|
-
|
|
22
|
-
(?<value>#{EXPIRES_AT_VALUE}|#{VALUE})
|
23
|
-
)
|
24
|
-
){0,1}
|
25
|
-
}nx
|
26
|
-
|
3
|
+
IPADDR = /\A#{URI::REGEXP::PATTERN::IPV4ADDR}\Z|\A#{URI::REGEXP::PATTERN::IPV6ADDR}\Z/
|
4
|
+
|
27
5
|
# [String] The name of the cookie.
|
28
6
|
attr_reader :name
|
29
7
|
|
@@ -79,7 +57,7 @@ class CookieStore::Cookie
|
|
79
57
|
# [Time] Time when this cookie was first evaluated and created.
|
80
58
|
attr_reader :created_at
|
81
59
|
|
82
|
-
def initialize(name, value,
|
60
|
+
def initialize(name, value, attributes={})
|
83
61
|
@name = name
|
84
62
|
@value = value
|
85
63
|
@secure = false
|
@@ -88,8 +66,12 @@ class CookieStore::Cookie
|
|
88
66
|
@discard = false
|
89
67
|
@created_at = Time.now
|
90
68
|
|
91
|
-
|
92
|
-
|
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
|
93
75
|
end
|
94
76
|
end
|
95
77
|
|
@@ -179,60 +161,27 @@ class CookieStore::Cookie
|
|
179
161
|
end
|
180
162
|
|
181
163
|
def self.parse(request_uri, set_cookie_value)
|
164
|
+
parse_cookies(request_uri, set_cookie_value).first
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.parse_cookies(request_uri, set_cookie_value)
|
182
168
|
uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
|
183
|
-
data = COOKIE.match(set_cookie_value)
|
184
|
-
options = {}
|
185
|
-
|
186
|
-
if !data
|
187
|
-
raise Net::HTTPHeaderSyntaxError.new("Invalid Set-Cookie header format")
|
188
|
-
end
|
189
169
|
|
190
|
-
|
191
|
-
|
192
|
-
|
170
|
+
cookies = []
|
171
|
+
CookieStore::CookieParser.parse(set_cookie_value) do |parsed|
|
172
|
+
parsed[:attributes][:domain] ||= uri.host.downcase
|
173
|
+
parsed[:attributes][:path] ||= uri.path
|
193
174
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
when 'discard'
|
201
|
-
options[:discard] = true
|
202
|
-
when 'domain'
|
203
|
-
if value =~ IPADDR
|
204
|
-
options[:domain] = value
|
205
|
-
else
|
206
|
-
# As per RFC2965 if a host name contains no dots, the effective host name is
|
207
|
-
# that name with the string .local appended to it.
|
208
|
-
value = "#{value}.local" if !value.include?('.')
|
209
|
-
options[:domain] = (value.start_with?('.') ? value : ".#{value}").downcase
|
210
|
-
end
|
211
|
-
when 'expires'
|
212
|
-
if value.include?('-')
|
213
|
-
options[:expires] = DateTime.strptime(value, '%a, %d-%b-%Y %H:%M:%S %Z')
|
214
|
-
else
|
215
|
-
options[:expires] = DateTime.strptime(value, '%a, %d %b %Y %H:%M:%S %Z')
|
216
|
-
end
|
217
|
-
when 'max-age'
|
218
|
-
options[:max_age] = value.to_i
|
219
|
-
when 'path'
|
220
|
-
options[:path] = value
|
221
|
-
when 'port'
|
222
|
-
options[:ports] = value.split(',').map(&:to_i)
|
223
|
-
when 'secure'
|
224
|
-
options[:secure] = true
|
225
|
-
when 'httponly'
|
226
|
-
options[:http_only] = true
|
227
|
-
when 'version'
|
228
|
-
options[:version] = value.to_i
|
229
|
-
end
|
175
|
+
cookie = CookieStore::Cookie.new(parsed[:key], parsed[:value], parsed[:attributes])
|
176
|
+
|
177
|
+
cookies << if block_given?
|
178
|
+
yield(cookie)
|
179
|
+
else
|
180
|
+
cookie
|
230
181
|
end
|
231
182
|
end
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
CookieStore::Cookie.new(data[:name], data[:value] || data[:quoted_value].gsub(/\\(.)/, '\1'), options)
|
183
|
+
|
184
|
+
cookies
|
236
185
|
end
|
237
186
|
|
238
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,31 @@ 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
|
198
|
+
assert_equal 1, cookie.version
|
199
|
+
assert_equal false, cookie.discard
|
200
|
+
assert_nil cookie.ports
|
201
|
+
assert_nil cookie.expires
|
202
|
+
assert_nil cookie.max_age
|
203
|
+
end
|
204
|
+
|
205
|
+
test "::parse a cookie with options" do
|
206
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test', "foo=bar; path=/; HttpOnly")
|
207
|
+
|
208
|
+
assert_equal 'foo', cookie.name
|
209
|
+
assert_equal 'bar', cookie.value
|
210
|
+
assert_equal 'google.com', cookie.domain
|
211
|
+
assert_equal '/', cookie.path
|
212
|
+
assert_equal false, cookie.secure
|
213
|
+
assert_equal true, cookie.http_only
|
214
|
+
assert_nil cookie.comment
|
215
|
+
assert_nil cookie.comment_url
|
193
216
|
assert_equal 1, cookie.version
|
194
217
|
assert_equal false, cookie.discard
|
195
|
-
|
196
|
-
|
197
|
-
|
218
|
+
assert_nil cookie.ports
|
219
|
+
assert_nil cookie.expires
|
220
|
+
assert_nil cookie.max_age
|
198
221
|
end
|
199
222
|
|
200
223
|
test "::parse normalizes the request domain" do
|
@@ -216,9 +239,9 @@ class CookieStore::CookieTest < Minitest::Test
|
|
216
239
|
test "::parse a simple quoted cookie" do
|
217
240
|
cookie = CookieStore::Cookie.parse('http://google.com/test', 'foo="b\"ar"')
|
218
241
|
|
219
|
-
assert_equal 'google.com',
|
220
|
-
assert_equal 'foo',
|
221
|
-
assert_equal 'b"ar',
|
242
|
+
assert_equal 'google.com', cookie.domain
|
243
|
+
assert_equal 'foo', cookie.name
|
244
|
+
assert_equal 'b"ar', cookie.value
|
222
245
|
end
|
223
246
|
|
224
247
|
test "::parse domain attribute without leading ." do
|
@@ -294,20 +317,96 @@ class CookieStore::CookieTest < Minitest::Test
|
|
294
317
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 2021 22:23:01 GMT"')
|
295
318
|
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
296
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
|
+
|
297
333
|
# Wed, 13-Jan-2021 22:23:01 GMT format
|
298
334
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13-Jan-2021 22:23:01 GMT')
|
299
335
|
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
300
336
|
|
301
337
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13-Jan-2021 22:23:01 GMT"')
|
302
338
|
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
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
|
+
|
353
|
+
# Wed, 13 Jan 2021 22:23:01 -0000 format
|
354
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13 Jan 2021 22:23:01 -0000')
|
355
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
|
356
|
+
|
357
|
+
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 2021 22:23:01 +0000"')
|
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
|
303
372
|
end
|
304
373
|
|
305
374
|
test "::parse max_age attribute" do
|
306
375
|
cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Max-Age=3660')
|
307
376
|
assert_equal 3660, cookie.max_age
|
308
377
|
end
|
378
|
+
|
379
|
+
test "::parse_cookies with one cookie" do
|
380
|
+
cookies = CookieStore::Cookie.parse_cookies("http://google.com/test/this", "current_account_id=2449; path=/")
|
381
|
+
|
382
|
+
assert_equal "current_account_id", cookies.first.name
|
383
|
+
assert_equal "2449", cookies.first.value
|
384
|
+
assert_equal "/", cookies.first.path
|
385
|
+
end
|
386
|
+
|
387
|
+
test "::parse_cookies with multiple cookies" do
|
388
|
+
cookies = CookieStore::Cookie.parse_cookies("http://google.com/test/this", "current_account_id=2449; path=/, _session=QUZwVE5jNjB; path=/test; expires=Wed, 13-Jan-2021 22:23:01 GMT; HttpOnly")
|
389
|
+
|
390
|
+
assert_equal "current_account_id", cookies.first.name
|
391
|
+
assert_equal "2449", cookies.first.value
|
392
|
+
assert_equal "/", cookies.first.path
|
393
|
+
|
394
|
+
assert_equal "_session", cookies[1].name
|
395
|
+
assert_equal "QUZwVE5jNjB", cookies[1].value
|
396
|
+
assert_equal "/test", cookies[1].path
|
397
|
+
assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookies[1].expires
|
398
|
+
assert_equal true, cookies[1].http_only
|
399
|
+
end
|
309
400
|
|
310
|
-
#
|
311
|
-
|
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
|
312
411
|
|
313
412
|
end
|
data/test/cookie_store_test.rb
CHANGED
@@ -6,9 +6,18 @@ class CookieStoreTest < Minitest::Test
|
|
6
6
|
|
7
7
|
test "#set_cookie" do
|
8
8
|
store = CookieStore.new
|
9
|
-
store.expects(:add)
|
9
|
+
store.expects(:add).times(3)
|
10
10
|
|
11
11
|
store.set_cookie('http://google.com/test/this', 'foo=bar; Max-Age=3600')
|
12
|
+
store.set_cookie('http://localhost/test/this', 'foo=bar; Max-Age=3600')
|
13
|
+
store.set_cookie('http://127.0.0.1/test/this', 'foo=bar; Max-Age=3600')
|
14
|
+
end
|
15
|
+
|
16
|
+
test "#set_cookie contains multiple cookies" do
|
17
|
+
store = CookieStore.new
|
18
|
+
store.expects(:add).times(2)
|
19
|
+
|
20
|
+
store.set_cookie("http://google.com/test/this", "current_account_id=2449; path=/, _session=QUZwVE5jNjB; path=/test; expires=Wed, 13-Jan-2021 22:23:01 GMT; HttpOnly")
|
12
21
|
end
|
13
22
|
|
14
23
|
test "#set_cookie rejects cookies where the value for the Domain attribute contains no embedded dots" do
|
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,11 +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"
|
20
|
+
require 'active_support/time'
|
17
21
|
require 'active_support/testing/time_helpers'
|
22
|
+
require "byebug"
|
18
23
|
|
19
24
|
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
20
25
|
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
$debug = false
|
30
|
+
|
21
31
|
# File 'lib/active_support/testing/declarative.rb', somewhere in rails....
|
22
32
|
class Minitest::Test
|
23
33
|
include ActiveSupport::Testing::TimeHelpers
|
@@ -35,4 +45,12 @@ class Minitest::Test
|
|
35
45
|
end
|
36
46
|
end
|
37
47
|
|
48
|
+
def debug
|
49
|
+
$debug = true
|
50
|
+
puts '=========================='
|
51
|
+
yield
|
52
|
+
ensure
|
53
|
+
puts '=========================='
|
54
|
+
$debug = false
|
55
|
+
end
|
38
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
|
@@ -66,29 +94,90 @@ dependencies:
|
|
66
94
|
- - ">="
|
67
95
|
- !ruby/object:Gem::Version
|
68
96
|
version: '0'
|
69
|
-
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: faker
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: webmock
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: activesupport
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
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'
|
153
|
+
description: A Ruby library to handle client-side HTTP cookies
|
70
154
|
email:
|
71
155
|
- jonbracy@gmail.com
|
72
156
|
executables: []
|
73
157
|
extensions: []
|
74
158
|
extra_rdoc_files: []
|
75
159
|
files:
|
160
|
+
- ".github/workflows/ci.yml"
|
161
|
+
- ".gitignore"
|
162
|
+
- ".tm_properties"
|
163
|
+
- Gemfile
|
76
164
|
- LICENSE
|
77
165
|
- README.md
|
78
166
|
- Rakefile
|
79
167
|
- cookie_store.gemspec
|
80
168
|
- lib/cookie_store.rb
|
81
169
|
- lib/cookie_store/cookie.rb
|
170
|
+
- lib/cookie_store/cookie_parser.rb
|
82
171
|
- lib/cookie_store/hash_store.rb
|
172
|
+
- lib/cookie_store/version.rb
|
83
173
|
- test/cookie_store/cookie_test.rb
|
84
174
|
- test/cookie_store/hash_store_test.rb
|
85
175
|
- test/cookie_store_test.rb
|
86
176
|
- test/test_helper.rb
|
87
177
|
homepage: https://github.com/malomalo/cookie_store
|
88
|
-
licenses:
|
89
|
-
- MIT
|
178
|
+
licenses: []
|
90
179
|
metadata: {}
|
91
|
-
post_install_message:
|
180
|
+
post_install_message:
|
92
181
|
rdoc_options: []
|
93
182
|
require_paths:
|
94
183
|
- lib
|
@@ -103,9 +192,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
192
|
- !ruby/object:Gem::Version
|
104
193
|
version: '0'
|
105
194
|
requirements: []
|
106
|
-
|
107
|
-
|
108
|
-
signing_key:
|
195
|
+
rubygems_version: 3.2.3
|
196
|
+
signing_key:
|
109
197
|
specification_version: 4
|
110
198
|
summary: A Ruby library to handle client-side HTTP cookies
|
111
199
|
test_files:
|
@@ -113,4 +201,3 @@ test_files:
|
|
113
201
|
- test/cookie_store/hash_store_test.rb
|
114
202
|
- test/cookie_store_test.rb
|
115
203
|
- test/test_helper.rb
|
116
|
-
has_rdoc:
|