http-cookie 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aacf47668ef161f9e46f07ed44bd6e145c805c14
4
- data.tar.gz: 92c544f479f357ad08e66a8a3827e1edaca35c2e
3
+ metadata.gz: e01904534ca62610f72b5aba64d20f403ef41334
4
+ data.tar.gz: b7194473dbb2106fc6fea76fc8077135721518a3
5
5
  SHA512:
6
- metadata.gz: 7cc1fc98627c5167e3eb410359b00a868f849d10458ca0b1881efdb6ab94bf51d300f732f9b3de52edec2e21934553f937cb38e416af18e103ca923e70285c58
7
- data.tar.gz: 3fef65c59da56daba7cb4d571b034cecab3b66cb656811fe9644d99404a152b5656dc04d2a501a3a6b74cf75cb5bcdde91c87f3d5b470d8ba1ffcd515498c421
6
+ metadata.gz: 11de16cdf76a561e3dfcf5af1fcc78d6231a352cba9460fed867b4a6a4548dd71b6615c75eb70507599f23906877c05e878b1ed1b5abb33ddcf3410cf5d2794e
7
+ data.tar.gz: 9cd258c417a7f5f80a5b718a6f4c3b1a59086c871ae62500b3809fce95bbd57a75e45dd9d11deced0052996fa12e32769aae9f7547f82efbab4d1f1a4a2c68a7
@@ -0,0 +1,10 @@
1
+ ## 1.0.1 (2013-04-21)
2
+
3
+ - Minor error handling improvements and documentation updates.
4
+
5
+ - Argument error regarding specifying store/saver classes no longer
6
+ raises IndexError, but either ArgumentError or TypeError.
7
+
8
+ ## 1.0.0 (2013-04-17)
9
+
10
+ - Initial Release.
data/README.md CHANGED
@@ -8,6 +8,34 @@ It was originally a part of the
8
8
  separated as an independent library in the hope of serving as a common
9
9
  component that is reusable from any HTTP related piece of software.
10
10
 
11
+ The following is an incomplete list of its features:
12
+
13
+ * Its behavior is highly compatible with that of today's major web
14
+ browsers.
15
+
16
+ * It is based on and conforms to RFC 6265 (the latest standard for the
17
+ HTTP cookie mechanism) to a high extent, with real world conventions
18
+ deeply in mind.
19
+
20
+ * It takes eTLD (effective TLD, also known as "Public Suffix") into
21
+ account just as major browsers do, to reject cookies with an eTLD
22
+ domain like "org", "co.jp", or "appspot.com". This feature is
23
+ brought to you by the domain_name gem.
24
+
25
+ * The number of cookies and the size are properly capped so that a
26
+ cookie store does not get flooded.
27
+
28
+ * It supports the legacy Netscape cookies.txt format for
29
+ serialization, maximizing the interoperability with other
30
+ implementations.
31
+
32
+ * It supports the cookies.sqlite format adopted by Mozilla Firefox for
33
+ backend store database which can be shared among multiple program
34
+ instances.
35
+
36
+ * It is relatively easy to add a new serialization format or a backend
37
+ store because of its modular API.
38
+
11
39
  ## Installation
12
40
 
13
41
  Add this line to your application's `Gemfile`:
@@ -13,8 +13,8 @@ Gem::Specification.new do |gem|
13
13
  'Mike Dalessio' => 'mike.dalessio@gmail.com',
14
14
  }.instance_eval { [keys, values] }
15
15
 
16
- gem.description = %q{A Ruby library to handle HTTP Cookies}
17
- gem.summary = %q{A Ruby library to handle HTTP Cookies}
16
+ gem.description = %q{HTTP::Cookie is a Ruby library to handle HTTP Cookies based on RFC 6265. It has with security, standards compliance and compatibility in mind, to behave just the same as today's major web browsers. It has builtin support for the legacy cookies.txt and the latest cookies.sqlite formats of Mozilla Firefox, and its modular API makes it easy to add support for a new backend store.}
17
+ gem.summary = %q{A Ruby library to handle HTTP Cookies based on RFC 6265}
18
18
  gem.homepage = "https://github.com/sparklemotion/http-cookie"
19
19
 
20
20
  gem.files = `git ls-files`.split($/)
@@ -174,7 +174,7 @@ class HTTP::Cookie
174
174
  # Let max_age take precedence over expires
175
175
  max_age = val
176
176
  when :expires, :expires_at
177
- self.expires = val
177
+ self.expires = val unless max_age
178
178
  when :httponly, :httponly?
179
179
  @httponly = val
180
180
  when :secure, :secure?
@@ -288,7 +288,9 @@ class HTTP::Cookie
288
288
  case aname
289
289
  when 'domain'
290
290
  cookie.for_domain = true
291
- cookie.domain = avalue # This may negate @for_domain
291
+ # The following may negate @for_domain if the value is
292
+ # an eTLD or IP address, hence this order.
293
+ cookie.domain = avalue
292
294
  when 'path'
293
295
  cookie.path = avalue
294
296
  when 'expires'
@@ -447,6 +449,7 @@ class HTTP::Cookie
447
449
  return origin if origin == @origin
448
450
  @origin.nil? or
449
451
  raise ArgumentError, "origin cannot be changed once it is set"
452
+ # Delay setting @origin because #domain= or #path= may fail
450
453
  origin = URI(origin)
451
454
  if URI::HTTP === origin
452
455
  self.domain ||= origin.host
@@ -497,7 +500,6 @@ class HTTP::Cookie
497
500
 
498
501
  # See #max_age.
499
502
  def max_age= sec
500
- @expires = nil
501
503
  case sec
502
504
  when Integer, nil
503
505
  else
@@ -507,6 +509,7 @@ class HTTP::Cookie
507
509
  raise ArgumentError, "invalid Max-Age: #{sec.inspect}"
508
510
  sec = str.to_i
509
511
  end
512
+ @expires = nil
510
513
  if @session = sec.nil?
511
514
  @max_age = nil
512
515
  else
@@ -600,7 +603,7 @@ class HTTP::Cookie
600
603
  if @domain
601
604
  string << "; Domain=#{@domain}"
602
605
  else
603
- raise "for_domain is specified but domain is known"
606
+ raise "for_domain is specified but domain is unknown"
604
607
  end
605
608
  end
606
609
  if @path
@@ -608,7 +611,7 @@ class HTTP::Cookie
608
611
  string << "; Path=#{@path}"
609
612
  end
610
613
  else
611
- raise "path is known"
614
+ raise "path is unknown"
612
615
  end
613
616
  if @max_age
614
617
  string << "; Max-Age=#{@max_age}"
@@ -1,5 +1,5 @@
1
1
  module HTTP
2
2
  class Cookie
3
- VERSION = "1.0.0"
3
+ VERSION = "1.0.1"
4
4
  end
5
5
  end
@@ -29,16 +29,38 @@ class HTTP::CookieJar
29
29
 
30
30
  attr_reader :store
31
31
 
32
+ def get_impl(base, value, *args)
33
+ case value
34
+ when base
35
+ value
36
+ when Symbol
37
+ begin
38
+ base.implementation(value).new(*args)
39
+ rescue IndexError => e
40
+ raise ArgumentError, e.message
41
+ end
42
+ when Class
43
+ if base >= value
44
+ value.new(*args)
45
+ else
46
+ raise TypeError, 'not a subclass of %s: %s' % [base, value]
47
+ end
48
+ else
49
+ raise TypeError, 'invalid object: %s' % value.inspect
50
+ end
51
+ end
52
+ private :get_impl
53
+
32
54
  # Generates a new cookie jar.
33
55
  #
34
56
  # Available option keywords are as below:
35
57
  #
36
58
  # :store
37
59
  # : The store class that backs this jar. (default: `:hash`)
38
- # A symbol or an instance of a store class is accepted. Symbols are
39
- # mapped to store classes, like `:hash` to
40
- # HTTP::CookieJar::HashStore and `:mozilla` to
41
- # HTTP::CookieJar::MozillaStore.
60
+ # A symbol addressing a store class, a store class, or an instance
61
+ # of a store class is accepted. Symbols are mapped to store
62
+ # classes, like `:hash` to HTTP::CookieJar::HashStore and `:mozilla`
63
+ # to HTTP::CookieJar::MozillaStore.
42
64
  #
43
65
  # Any options given are passed through to the initializer of the
44
66
  # specified store class. For example, the `:mozilla`
@@ -49,14 +71,7 @@ class HTTP::CookieJar
49
71
  :store => :hash,
50
72
  }
51
73
  opthash.update(options) if options
52
- case store = opthash[:store]
53
- when Symbol
54
- @store = AbstractStore.implementation(store).new(opthash)
55
- when AbstractStore
56
- @store = store
57
- else
58
- raise TypeError, 'wrong object given as cookie store: %s' % store.inspect
59
- end
74
+ @store = get_impl(AbstractStore, opthash[:store], opthash)
60
75
  end
61
76
 
62
77
  # The copy constructor. Not all backend store classes support cloning.
@@ -191,6 +206,10 @@ class HTTP::CookieJar
191
206
  #
192
207
  # * `:format`
193
208
  #
209
+ # Specifies the format for saving. A saver class, a symbol
210
+ # addressing a saver class, or a pre-generated instance of a
211
+ # saver class is accepted.
212
+ #
194
213
  # <dl class="rdoc-list note-list">
195
214
  # <dt>:yaml</dt>
196
215
  # <dd>YAML structure (default)</dd>
@@ -221,20 +240,20 @@ class HTTP::CookieJar
221
240
  when Symbol
222
241
  opthash[:format] = options
223
242
  else
224
- opthash.update(options) if options
243
+ if hash = Hash.try_convert(options)
244
+ opthash.update(hash)
245
+ end
225
246
  end
226
247
  when 2
227
248
  opthash[:format], options = options
228
- opthash.update(options) if options
249
+ if hash = Hash.try_convert(options)
250
+ opthash.update(hash)
251
+ end
229
252
  else
230
253
  raise ArgumentError, 'wrong number of arguments (%d for 1-3)' % (1 + options.size)
231
254
  end
232
255
 
233
- begin
234
- saver = AbstractSaver.implementation(opthash[:format]).new(opthash)
235
- rescue IndexError => e
236
- raise ArgumentError, e.message
237
- end
256
+ saver = get_impl(AbstractSaver, opthash[:format], opthash)
238
257
 
239
258
  if writable.respond_to?(:write)
240
259
  saver.save(writable, self)
@@ -259,6 +278,10 @@ class HTTP::CookieJar
259
278
  #
260
279
  # * `:format`
261
280
  #
281
+ # Specifies the format for loading. A saver class, a symbol
282
+ # addressing a saver class, or a pre-generated instance of a
283
+ # saver class is accepted.
284
+ #
262
285
  # <dl class="rdoc-list note-list">
263
286
  # <dt>:yaml</dt>
264
287
  # <dd>YAML structure (default)</dd>
@@ -280,20 +303,20 @@ class HTTP::CookieJar
280
303
  when Symbol
281
304
  opthash[:format] = options
282
305
  else
283
- opthash.update(options) if options
306
+ if hash = Hash.try_convert(options)
307
+ opthash.update(hash)
308
+ end
284
309
  end
285
310
  when 2
286
311
  opthash[:format], options = options
287
- opthash.update(options) if options
312
+ if hash = Hash.try_convert(options)
313
+ opthash.update(hash)
314
+ end
288
315
  else
289
316
  raise ArgumentError, 'wrong number of arguments (%d for 1-3)' % (1 + options.size)
290
317
  end
291
318
 
292
- begin
293
- saver = AbstractSaver.implementation(opthash[:format]).new(opthash)
294
- rescue IndexError => e
295
- raise ArgumentError, e.message
296
- end
319
+ saver = get_impl(AbstractSaver, opthash[:format], opthash)
297
320
 
298
321
  if readable.respond_to?(:write)
299
322
  saver.load(readable, self)
@@ -692,19 +692,32 @@ class TestHTTPCookie < Test::Unit::TestCase
692
692
 
693
693
  def test_max_age=
694
694
  cookie = HTTP::Cookie.new(cookie_values)
695
+ expires = cookie.expires
695
696
 
696
697
  assert_raises(ArgumentError) {
697
698
  cookie.max_age = "+1"
698
699
  }
700
+ # make sure #expires is not destroyed
701
+ assert_equal expires, cookie.expires
702
+
699
703
  assert_raises(ArgumentError) {
700
704
  cookie.max_age = "1.5"
701
705
  }
706
+ # make sure #expires is not destroyed
707
+ assert_equal expires, cookie.expires
708
+
702
709
  assert_raises(ArgumentError) {
703
710
  cookie.max_age = "1 day"
704
711
  }
712
+ # make sure #expires is not destroyed
713
+ assert_equal expires, cookie.expires
714
+
705
715
  assert_raises(TypeError) {
706
716
  cookie.max_age = [1]
707
717
  }
718
+ # make sure #expires is not destroyed
719
+ assert_equal expires, cookie.expires
720
+
708
721
  cookie.max_age = "12"
709
722
  assert_equal 12, cookie.max_age
710
723
 
@@ -355,14 +355,6 @@ module TestHTTPCookieJar
355
355
  assert_equal(0, @jar.cookies(url).length)
356
356
  end
357
357
 
358
- def test_save_nonexistent_saver
359
- Dir.mktmpdir { |dir|
360
- assert_raises(ArgumentError) {
361
- @jar.save(File.join(dir, "file"), :nonexistent)
362
- }
363
- }
364
- end
365
-
366
358
  def test_save_cookies_yaml
367
359
  url = URI 'http://rubyforge.org/'
368
360
 
@@ -403,12 +395,18 @@ module TestHTTPCookieJar
403
395
  @jar.save(filename, :format => :cookiestxt)
404
396
  @jar.save(filename, :cookiestxt, :session => true)
405
397
  @jar.save(filename, :cookiestxt)
398
+ @jar.save(filename, HTTP::CookieJar::CookiestxtSaver)
399
+ @jar.save(filename, HTTP::CookieJar::CookiestxtSaver.new)
406
400
  @jar.save(filename, :session => true)
407
401
  @jar.save(filename)
402
+
408
403
  assert_raises(ArgumentError) {
409
404
  @jar.save()
410
405
  }
411
406
  assert_raises(ArgumentError) {
407
+ @jar.save(filename, :nonexistent)
408
+ }
409
+ assert_raises(TypeError) {
412
410
  @jar.save(filename, { :format => :cookiestxt }, { :session => true })
413
411
  }
414
412
  assert_raises(ArgumentError) {
@@ -418,6 +416,8 @@ module TestHTTPCookieJar
418
416
  @jar.load(filename, :format => :cookiestxt, :linefeed => "\n")
419
417
  @jar.load(filename, :format => :cookiestxt, :linefeed => "\n")
420
418
  @jar.load(filename, :format => :cookiestxt)
419
+ @jar.load(filename, HTTP::CookieJar::CookiestxtSaver)
420
+ @jar.load(filename, HTTP::CookieJar::CookiestxtSaver.new)
421
421
  @jar.load(filename, :cookiestxt, :linefeed => "\n")
422
422
  @jar.load(filename, :cookiestxt)
423
423
  @jar.load(filename, :linefeed => "\n")
@@ -426,6 +426,9 @@ module TestHTTPCookieJar
426
426
  @jar.load()
427
427
  }
428
428
  assert_raises(ArgumentError) {
429
+ @jar.load(filename, :nonexistent)
430
+ }
431
+ assert_raises(TypeError) {
429
432
  @jar.load(filename, { :format => :cookiestxt }, { :linefeed => "\n" })
430
433
  }
431
434
  assert_raises(ArgumentError) {
@@ -850,16 +853,14 @@ module TestHTTPCookieJar
850
853
  jar = HTTP::CookieJar.new(:store => :hash)
851
854
  assert_instance_of HTTP::CookieJar::HashStore, jar.store
852
855
 
853
- assert_raises(IndexError) {
856
+ assert_raises(ArgumentError) {
854
857
  jar = HTTP::CookieJar.new(:store => :nonexistent)
855
858
  }
856
859
 
857
860
  jar = HTTP::CookieJar.new(:store => HTTP::CookieJar::HashStore.new)
858
861
  assert_instance_of HTTP::CookieJar::HashStore, jar.store
859
862
 
860
- assert_raises(TypeError) {
861
- jar = HTTP::CookieJar.new(:store => HTTP::CookieJar::HashStore)
862
- }
863
+ jar = HTTP::CookieJar.new(:store => HTTP::CookieJar::HashStore)
863
864
  end
864
865
 
865
866
  def test_clone
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-cookie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akinori MUSHA
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-04-17 00:00:00.000000000 Z
14
+ date: 2013-04-21 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: domain_name
@@ -111,7 +111,11 @@ dependencies:
111
111
  - - '>='
112
112
  - !ruby/object:Gem::Version
113
113
  version: '0'
114
- description: A Ruby library to handle HTTP Cookies
114
+ description: HTTP::Cookie is a Ruby library to handle HTTP Cookies based on RFC 6265. It
115
+ has with security, standards compliance and compatibility in mind, to behave just
116
+ the same as today's major web browsers. It has builtin support for the legacy cookies.txt
117
+ and the latest cookies.sqlite formats of Mozilla Firefox, and its modular API makes
118
+ it easy to add support for a new backend store.
115
119
  email:
116
120
  - knu@idaemons.org
117
121
  - aaronp@rubyforge.org
@@ -125,6 +129,7 @@ extra_rdoc_files:
125
129
  files:
126
130
  - .gitignore
127
131
  - .travis.yml
132
+ - CHANGELOG.md
128
133
  - Gemfile
129
134
  - LICENSE.txt
130
135
  - README.md
@@ -169,7 +174,7 @@ rubyforge_project:
169
174
  rubygems_version: 2.0.3
170
175
  signing_key:
171
176
  specification_version: 4
172
- summary: A Ruby library to handle HTTP Cookies
177
+ summary: A Ruby library to handle HTTP Cookies based on RFC 6265
173
178
  test_files:
174
179
  - test/helper.rb
175
180
  - test/mechanize.yml