secobarbital-cookiejar 0.2.9.1
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.
- data/lib/cookiejar/cookie.rb +252 -0
- data/lib/cookiejar/cookie_validation.rb +400 -0
- data/lib/cookiejar/jar.rb +308 -0
- data/lib/cookiejar.rb +2 -0
- data/test/cookie_test.rb +176 -0
- data/test/cookie_validation_test.rb +251 -0
- data/test/jar_test.rb +226 -0
- metadata +73 -0
@@ -0,0 +1,308 @@
|
|
1
|
+
require 'cookiejar/cookie'
|
2
|
+
|
3
|
+
module CookieJar
|
4
|
+
# A cookie store for client side usage.
|
5
|
+
# - Enforces cookie validity rules
|
6
|
+
# - Returns just the cookies valid for a given URI
|
7
|
+
# - Handles expiration of cookies
|
8
|
+
# - Allows for persistence of cookie data (with or without session)
|
9
|
+
#
|
10
|
+
#--
|
11
|
+
#
|
12
|
+
# Internal format:
|
13
|
+
#
|
14
|
+
# Internally, the data structure is a set of nested hashes.
|
15
|
+
# Domain Level:
|
16
|
+
# At the domain level, the hashes are of individual domains,
|
17
|
+
# down-cased and without any leading period. For instance, imagine cookies
|
18
|
+
# for .foo.com, .bar.com, and .auth.bar.com:
|
19
|
+
#
|
20
|
+
# {
|
21
|
+
# "foo.com" : (host data),
|
22
|
+
# "bar.com" : (host data),
|
23
|
+
# "auth.bar.com" : (host data)
|
24
|
+
# }
|
25
|
+
#
|
26
|
+
# Lookups are done both for the matching entry, and for an entry without
|
27
|
+
# the first segment up to the dot, ie. for /^\.?[^\.]+\.(.*)$/.
|
28
|
+
# A lookup of auth.bar.com would match both bar.com and
|
29
|
+
# auth.bar.com, but not entries for com or www.auth.bar.com.
|
30
|
+
#
|
31
|
+
# Host Level:
|
32
|
+
# Entries are in an hash, with keys of the path and values of a hash of
|
33
|
+
# cookie names to cookie object
|
34
|
+
#
|
35
|
+
# {
|
36
|
+
# "/" : {"session" : (Cookie object), "cart_id" : (Cookie object)}
|
37
|
+
# "/protected" : {"authentication" : (Cookie Object)}
|
38
|
+
# }
|
39
|
+
#
|
40
|
+
# Paths are given a straight prefix string comparison to match.
|
41
|
+
# Further filters <secure, http only, ports> are not represented in this
|
42
|
+
# heirarchy.
|
43
|
+
#
|
44
|
+
# Cookies returned are ordered solely by specificity (length) of the
|
45
|
+
# path.
|
46
|
+
class Jar
|
47
|
+
# Create a new empty Jar
|
48
|
+
def initialize
|
49
|
+
@domains = {}
|
50
|
+
end
|
51
|
+
|
52
|
+
# Given a request URI and a literal Set-Cookie header value, attempt to
|
53
|
+
# add the cookie to the cookie store.
|
54
|
+
#
|
55
|
+
# @param [String, URI] request_uri the resource returning the header
|
56
|
+
# @param [String] cookie_header_value the contents of the Set-Cookie
|
57
|
+
# @return [Cookie] which was created and stored
|
58
|
+
# @raise [InvalidCookieError] if the cookie header did not validate
|
59
|
+
def set_cookie request_uri, cookie_header_value
|
60
|
+
cookie = Cookie.from_set_cookie request_uri, cookie_header_value
|
61
|
+
add_cookie cookie
|
62
|
+
end
|
63
|
+
|
64
|
+
# Given a request URI and a literal Set-Cookie2 header value, attempt to
|
65
|
+
# add the cookie to the cookie store.
|
66
|
+
#
|
67
|
+
# @param [String, URI] request_uri the resource returning the header
|
68
|
+
# @param [String] cookie_header_value the contents of the Set-Cookie2
|
69
|
+
# @return [Cookie] which was created and stored
|
70
|
+
# @raise [InvalidCookieError] if the cookie header did not validate
|
71
|
+
def set_cookie2 request_uri, cookie_header_value
|
72
|
+
cookie = Cookie.from_set_cookie2 request_uri, cookie_header_value
|
73
|
+
add_cookie cookie
|
74
|
+
end
|
75
|
+
|
76
|
+
# Given a request URI and some HTTP headers, attempt to add the cookie(s)
|
77
|
+
# (from Set-Cookie or Set-Cookie2 headers) to the cookie store. If a
|
78
|
+
# cookie is defined (by equivalent name, domain, and path) via Set-Cookie
|
79
|
+
# and Set-Cookie2, the Set-Cookie version is ignored.
|
80
|
+
#
|
81
|
+
# @param [String, URI] request_uri the resource returning the header
|
82
|
+
# @param [Hash<String,[String,Array<String>]>] http_headers a Hash
|
83
|
+
# which may have a key of "Set-Cookie" or "Set-Cookie2", and values of
|
84
|
+
# either strings or arrays of strings
|
85
|
+
# @return [Array<Cookie>,nil] the cookies created, or nil if none found.
|
86
|
+
# @raise [InvalidCookieError] if one of the cookie headers contained
|
87
|
+
# invalid formatting or data
|
88
|
+
def set_cookies_from_headers request_uri, http_headers
|
89
|
+
set_cookie_key = http_headers.keys.detect { |k| /\ASet-Cookie\Z/i.match k }
|
90
|
+
cookies = gather_header_values http_headers[set_cookie_key] do |value|
|
91
|
+
begin
|
92
|
+
Cookie.from_set_cookie request_uri, value
|
93
|
+
rescue InvalidCookieError
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
set_cookie2_key = http_headers.keys.detect { |k| /\ASet-Cookie2\Z/i.match k }
|
98
|
+
cookies += gather_header_values(http_headers[set_cookie2_key]) do |value|
|
99
|
+
begin
|
100
|
+
Cookie.from_set_cookie2 request_uri, value
|
101
|
+
rescue InvalidCookieError
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# build the list of cookies, using a Jar. Since Set-Cookie2 values
|
106
|
+
# come second, they will replace the Set-Cookie versions.
|
107
|
+
jar = Jar.new
|
108
|
+
cookies.each do |cookie|
|
109
|
+
jar.add_cookie cookie
|
110
|
+
end
|
111
|
+
cookies = jar.to_a
|
112
|
+
|
113
|
+
# now add them all to our own store.
|
114
|
+
cookies.each do |cookie|
|
115
|
+
add_cookie cookie
|
116
|
+
end
|
117
|
+
cookies
|
118
|
+
end
|
119
|
+
|
120
|
+
# Add a pre-existing cookie object to the jar.
|
121
|
+
#
|
122
|
+
# @param [Cookie] cookie a pre-existing cookie object
|
123
|
+
# @return [Cookie] the cookie added to the store
|
124
|
+
def add_cookie cookie
|
125
|
+
domain_paths = find_or_add_domain_for_cookie cookie
|
126
|
+
add_cookie_to_path domain_paths, cookie
|
127
|
+
cookie
|
128
|
+
end
|
129
|
+
|
130
|
+
# Return an array of all cookie objects in the jar
|
131
|
+
#
|
132
|
+
# @return [Array<Cookie>] all cookies. Includes any expired cookies
|
133
|
+
# which have not yet been removed with expire_cookies
|
134
|
+
def to_a
|
135
|
+
result = []
|
136
|
+
@domains.values.each do |paths|
|
137
|
+
paths.values.each do |cookies|
|
138
|
+
cookies.values.inject result, :<<
|
139
|
+
end
|
140
|
+
end
|
141
|
+
result
|
142
|
+
end
|
143
|
+
|
144
|
+
# Return a JSON 'object' for the various data values. Allows for
|
145
|
+
# persistence of the cookie information
|
146
|
+
#
|
147
|
+
# @param [Array] a options controlling output JSON text
|
148
|
+
# (usually a State and a depth)
|
149
|
+
# @return [String] JSON representation of object data
|
150
|
+
def to_json *a
|
151
|
+
{
|
152
|
+
'json_class' => self.class.name,
|
153
|
+
'cookies' => (to_a.to_json *a)
|
154
|
+
}.to_json *a
|
155
|
+
end
|
156
|
+
|
157
|
+
# Create a new Jar from a JSON-backed hash
|
158
|
+
#
|
159
|
+
# @param o [Hash] the expanded JSON object
|
160
|
+
# @return [CookieJar] a new CookieJar instance
|
161
|
+
def self.json_create o
|
162
|
+
if o.is_a? Hash
|
163
|
+
o = o['cookies']
|
164
|
+
end
|
165
|
+
cookies = o.inject [] do |result, cookie_json|
|
166
|
+
result << (Cookie.json_create cookie_json)
|
167
|
+
end
|
168
|
+
self.from_a cookies
|
169
|
+
end
|
170
|
+
|
171
|
+
# Create a new Jar from an array of Cookie objects. Expired cookies
|
172
|
+
# will still be added to the archive, and conflicting cookies will
|
173
|
+
# be overwritten by the last cookie in the array.
|
174
|
+
#
|
175
|
+
# @param [Array<Cookie>] cookies array of cookie objects
|
176
|
+
# @return [CookieJar] a new CookieJar instance
|
177
|
+
def self.from_a cookies
|
178
|
+
jar = new
|
179
|
+
cookies.each do |cookie|
|
180
|
+
jar.add_cookie cookie
|
181
|
+
end
|
182
|
+
jar
|
183
|
+
end
|
184
|
+
|
185
|
+
# Look through the jar for any cookies which have passed their expiration
|
186
|
+
# date, or session cookies from a previous session
|
187
|
+
#
|
188
|
+
# @param session [Boolean] whether session cookies should be expired,
|
189
|
+
# or just cookies past their expiration date.
|
190
|
+
def expire_cookies session = false
|
191
|
+
@domains.delete_if do |domain, paths|
|
192
|
+
paths.delete_if do |path, cookies|
|
193
|
+
cookies.delete_if do |cookie_name, cookie|
|
194
|
+
cookie.expired? || (session && cookie.session?)
|
195
|
+
end
|
196
|
+
cookies.empty?
|
197
|
+
end
|
198
|
+
paths.empty?
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# Given a request URI, return a sorted list of Cookie objects. Cookies
|
203
|
+
# will be in order per RFC 2965 - sorted by longest path length, but
|
204
|
+
# otherwise unordered.
|
205
|
+
#
|
206
|
+
# @param [String, URI] request_uri the address the HTTP request will be
|
207
|
+
# sent to
|
208
|
+
# @param [Hash] opts options controlling returned cookies
|
209
|
+
# @option opts [Boolean] :script (false) Cookies marked HTTP-only will be ignored
|
210
|
+
# if true
|
211
|
+
# @return [Array<Cookie>] cookies which should be sent in the HTTP request
|
212
|
+
def get_cookies request_uri, opts = { }
|
213
|
+
uri = to_uri request_uri
|
214
|
+
hosts = Cookie.compute_search_domains uri
|
215
|
+
|
216
|
+
results = []
|
217
|
+
hosts.each do |host|
|
218
|
+
domain = find_domain host
|
219
|
+
domain.each do |path, cookies|
|
220
|
+
if uri.path.start_with? path
|
221
|
+
results += cookies.values.select do |cookie|
|
222
|
+
cookie.should_send? uri, opts[:script]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
#Sort by path length, longest first
|
228
|
+
results.sort do |lhs, rhs|
|
229
|
+
rhs.path.length <=> lhs.path.length
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Given a request URI, return a string Cookie header.Cookies will be in
|
234
|
+
# order per RFC 2965 - sorted by longest path length, but otherwise
|
235
|
+
# unordered.
|
236
|
+
#
|
237
|
+
# @param [String, URI] request_uri the address the HTTP request will be
|
238
|
+
# sent to
|
239
|
+
# @param [Hash] opts options controlling returned cookies
|
240
|
+
# @option opts [Boolean] :script (false) Cookies marked HTTP-only will be ignored
|
241
|
+
# if true
|
242
|
+
# @return String value of the Cookie header which should be sent on the
|
243
|
+
# HTTP request
|
244
|
+
def get_cookie_header request_uri, opts = { }
|
245
|
+
cookies = get_cookies request_uri, opts
|
246
|
+
version = 0
|
247
|
+
ver = [[],[]]
|
248
|
+
cookies.each do |cookie|
|
249
|
+
ver[cookie.version] << cookie
|
250
|
+
end
|
251
|
+
if (ver[1].empty?)
|
252
|
+
# can do a netscape-style cookie header, relish the opportunity
|
253
|
+
cookies.map do |cookie|
|
254
|
+
cookie.to_s
|
255
|
+
end.join ";"
|
256
|
+
else
|
257
|
+
# build a RFC 2965-style cookie header. Split the cookies into
|
258
|
+
# version 0 and 1 groups so that we can reuse the '$Version' header
|
259
|
+
result = ''
|
260
|
+
unless ver[0].empty?
|
261
|
+
result << '$Version=0;'
|
262
|
+
result << ver[0].map do |cookie|
|
263
|
+
(cookie.to_s 1,false)
|
264
|
+
end.join(';')
|
265
|
+
# separate version 0 and 1 with a comma
|
266
|
+
result << ','
|
267
|
+
end
|
268
|
+
result << '$Version=1;'
|
269
|
+
ver[1].map do |cookie|
|
270
|
+
result << (cookie.to_s 1,false)
|
271
|
+
end
|
272
|
+
result
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
protected
|
277
|
+
|
278
|
+
def gather_header_values http_header_value, &block
|
279
|
+
result = []
|
280
|
+
http_header_value
|
281
|
+
if http_header_value.is_a? Array
|
282
|
+
http_header_value.each do |value|
|
283
|
+
result << block.call(value)
|
284
|
+
end
|
285
|
+
elsif http_header_value.is_a? String
|
286
|
+
result << block.call(http_header_value)
|
287
|
+
end
|
288
|
+
result.compact
|
289
|
+
end
|
290
|
+
|
291
|
+
def to_uri request_uri
|
292
|
+
(request_uri.is_a? URI)? request_uri : (URI.parse request_uri)
|
293
|
+
end
|
294
|
+
|
295
|
+
def find_domain host
|
296
|
+
@domains[host] || {}
|
297
|
+
end
|
298
|
+
|
299
|
+
def find_or_add_domain_for_cookie cookie
|
300
|
+
@domains[cookie.domain] ||= {}
|
301
|
+
end
|
302
|
+
|
303
|
+
def add_cookie_to_path paths, cookie
|
304
|
+
path_entry = (paths[cookie.path] ||= {})
|
305
|
+
path_entry[cookie.name] = cookie
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
data/lib/cookiejar.rb
ADDED
data/test/cookie_test.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'cookiejar'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
include CookieJar
|
5
|
+
|
6
|
+
FOO_URL = 'http://localhost/foo'
|
7
|
+
AMMO_URL = 'http://localhost/ammo'
|
8
|
+
NETSCAPE_SPEC_SET_COOKIE_HEADERS =
|
9
|
+
[['CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT',
|
10
|
+
FOO_URL],
|
11
|
+
['PART_NUMBER=ROCKET_LAUNCHER_0001; path=/',
|
12
|
+
FOO_URL],
|
13
|
+
['SHIPPING=FEDEX; path=/foo',
|
14
|
+
FOO_URL],
|
15
|
+
['PART_NUMBER=ROCKET_LAUNCHER_0001; path=/',
|
16
|
+
FOO_URL],
|
17
|
+
['PART_NUMBER=RIDING_ROCKET_0023; path=/ammo',
|
18
|
+
AMMO_URL]]
|
19
|
+
|
20
|
+
describe Cookie do
|
21
|
+
describe "#from_set_cookie" do
|
22
|
+
it "should handle cookies from the netscape spec" do
|
23
|
+
NETSCAPE_SPEC_SET_COOKIE_HEADERS.each do |value|
|
24
|
+
header, url = *value
|
25
|
+
cookie = Cookie.from_set_cookie url, header
|
26
|
+
end
|
27
|
+
end
|
28
|
+
it "should give back the input names and values" do
|
29
|
+
cookie = Cookie.from_set_cookie 'http://localhost/', 'foo=bar'
|
30
|
+
cookie.name.should == 'foo'
|
31
|
+
cookie.value.should == 'bar'
|
32
|
+
end
|
33
|
+
it "should normalize domain names" do
|
34
|
+
cookie = Cookie.from_set_cookie 'http://localhost/', 'foo=Bar;domain=LoCaLHoSt.local'
|
35
|
+
cookie.domain.should == '.localhost.local'
|
36
|
+
end
|
37
|
+
it "should accept non-normalized .local" do
|
38
|
+
cookie = Cookie.from_set_cookie 'http://localhost/', 'foo=bar;domain=.local'
|
39
|
+
cookie.domain.should == '.local'
|
40
|
+
end
|
41
|
+
it "should accept secure cookies" do
|
42
|
+
cookie = Cookie.from_set_cookie 'https://www.google.com/a/blah', 'GALX=RgmSftjnbPM;Path=/a/;Secure'
|
43
|
+
cookie.name.should == 'GALX'
|
44
|
+
cookie.secure.should be_true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
describe "#from_set_cookie2" do
|
48
|
+
it "should give back the input names and values" do
|
49
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'foo=bar;Version=1'
|
50
|
+
cookie.name.should == 'foo'
|
51
|
+
cookie.value.should == 'bar'
|
52
|
+
end
|
53
|
+
it "should normalize domain names" do
|
54
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'foo=Bar;domain=LoCaLHoSt.local;Version=1'
|
55
|
+
cookie.domain.should == '.localhost.local'
|
56
|
+
end
|
57
|
+
it "should accept non-normalized .local" do
|
58
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'foo=bar;domain=.local;Version=1'
|
59
|
+
cookie.domain.should == '.local'
|
60
|
+
end
|
61
|
+
it "should accept secure cookies" do
|
62
|
+
cookie = Cookie.from_set_cookie2 'https://www.google.com/a/blah', 'GALX=RgmSftjnbPM;Path="/a/";Secure;Version=1'
|
63
|
+
cookie.name.should == 'GALX'
|
64
|
+
cookie.path.should == '/a/'
|
65
|
+
cookie.secure.should be_true
|
66
|
+
end
|
67
|
+
it "should fail on unquoted paths" do
|
68
|
+
lambda do
|
69
|
+
Cookie.from_set_cookie2 'https://www.google.com/a/blah',
|
70
|
+
'GALX=RgmSftjnbPM;Path=/a/;Secure;Version=1'
|
71
|
+
end.should raise_error InvalidCookieError
|
72
|
+
end
|
73
|
+
it "should accept quoted values" do
|
74
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'foo="bar";Version=1'
|
75
|
+
cookie.name.should == 'foo'
|
76
|
+
cookie.value.should == '"bar"'
|
77
|
+
end
|
78
|
+
it "should accept poorly chosen names" do
|
79
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'Version=mine;Version=1'
|
80
|
+
cookie.name.should == 'Version'
|
81
|
+
cookie.value.should == 'mine'
|
82
|
+
end
|
83
|
+
it "should accept quoted parameter values" do
|
84
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'foo=bar;Version="1"'
|
85
|
+
end
|
86
|
+
it "should honor the discard and max-age parameters" do
|
87
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f=b;max-age=100;discard;Version=1'
|
88
|
+
cookie.should be_session
|
89
|
+
cookie.should_not be_expired
|
90
|
+
|
91
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f=b;max-age=100;Version=1'
|
92
|
+
cookie.should_not be_session
|
93
|
+
|
94
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f=b;Version=1'
|
95
|
+
cookie.should be_session
|
96
|
+
end
|
97
|
+
it "should handle quotable quotes" do
|
98
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f="\"";Version=1'
|
99
|
+
cookie.value.should eql '"\""'
|
100
|
+
end
|
101
|
+
it "should handle quotable apostrophes" do
|
102
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f="\;";Version=1'
|
103
|
+
cookie.value.should eql '"\;"'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
describe '#decoded_value' do
|
107
|
+
it "should leave normal values alone" do
|
108
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f=b;Version=1'
|
109
|
+
cookie.decoded_value.should eql 'b'
|
110
|
+
end
|
111
|
+
it "should attempt to unencode quoted values" do
|
112
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f="\"b";Version=1'
|
113
|
+
cookie.value.should eql '"\"b"'
|
114
|
+
cookie.decoded_value.should eql '"b'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
describe '#to_s' do
|
118
|
+
it "should handle a simple cookie" do
|
119
|
+
cookie = Cookie.from_set_cookie 'http://localhost/', 'f=b'
|
120
|
+
cookie.to_s.should == 'f=b'
|
121
|
+
cookie.to_s(1).should == '$Version=0;f=b;$Path="/"'
|
122
|
+
end
|
123
|
+
it "should report an explicit domain" do
|
124
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f=b;Version=1;Domain=.local'
|
125
|
+
cookie.to_s(1).should == '$Version=1;f=b;$Path="/";$Domain=.local'
|
126
|
+
end
|
127
|
+
it "should return specified ports" do
|
128
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f=b;Version=1;Port="80,443"'
|
129
|
+
cookie.to_s(1).should == '$Version=1;f=b;$Path="/";$Port="80,443"'
|
130
|
+
end
|
131
|
+
it "should handle specified paths" do
|
132
|
+
cookie = Cookie.from_set_cookie 'http://localhost/bar/', 'f=b;path=/bar/'
|
133
|
+
cookie.to_s.should == 'f=b'
|
134
|
+
cookie.to_s(1).should == '$Version=0;f=b;$Path="/bar/"'
|
135
|
+
end
|
136
|
+
it "should omit $Version header when asked" do
|
137
|
+
cookie = Cookie.from_set_cookie 'http://localhost/', 'f=b'
|
138
|
+
cookie.to_s(1,false).should == 'f=b;$Path="/"'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
describe '#should_send?' do
|
142
|
+
it "should not send if ports do not match" do
|
143
|
+
cookie = Cookie.from_set_cookie2 'http://localhost/', 'f=b;Version=1;Port="80"'
|
144
|
+
cookie.should_send?("http://localhost/", false).should be_true
|
145
|
+
cookie.should_send?("https://localhost/", false).should be_false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
begin
|
149
|
+
require 'json'
|
150
|
+
describe ".to_json" do
|
151
|
+
it "should serialize a cookie to JSON" do
|
152
|
+
c = Cookie.from_set_cookie 'https://localhost/', 'foo=bar;secure;expires=Fri, September 11 2009 18:10:00 -0700'
|
153
|
+
json = c.to_json
|
154
|
+
json.should be_a String
|
155
|
+
end
|
156
|
+
end
|
157
|
+
describe ".json_create" do
|
158
|
+
it "should deserialize JSON to a cookie" do
|
159
|
+
json = "{\"name\":\"foo\",\"value\":\"bar\",\"domain\":\"localhost.local\",\"path\":\"\\/\",\"created_at\":\"2009-09-11 12:51:03 -0600\",\"expiry\":\"2009-09-11 19:10:00 -0600\",\"secure\":true}"
|
160
|
+
hash = JSON.parse json
|
161
|
+
c = Cookie.json_create hash
|
162
|
+
CookieValidation.validate_cookie 'https://localhost/', c
|
163
|
+
end
|
164
|
+
it "should automatically deserialize to a cookie" do
|
165
|
+
json = "{\"json_class\":\"CookieJar::Cookie\",\"name\":\"foo\",\"value\":\"bar\",\"domain\":\"localhost.local\",\"path\":\"\\/\",\"created_at\":\"2009-09-11 12:51:03 -0600\",\"expiry\":\"2009-09-11 19:10:00 -0600\",\"secure\":true}"
|
166
|
+
c = JSON.parse json
|
167
|
+
c.should be_a Cookie
|
168
|
+
CookieValidation.validate_cookie 'https://localhost/', c
|
169
|
+
end
|
170
|
+
end
|
171
|
+
rescue LoadError
|
172
|
+
it "does not appear the JSON library is installed" do
|
173
|
+
raise "please install the JSON library"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|