From ae4a9d8d40e6855fbbd05e3d92f202123d61bafc Mon Sep 17 00:00:00 2001 From: Akinori MUSHA Date: Mon, 22 Oct 2012 00:56:06 +0900 Subject: [PATCH] Make HTTP::Cookie Comparable. --- lib/http/cookie.rb | 11 +++++++++++ lib/http/cookie_jar.rb | 6 +----- test/test_http_cookie_jar.rb | 21 +++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/http/cookie.rb b/lib/http/cookie.rb index 6c9e579..a9c1533 100644 --- a/lib/http/cookie.rb +++ b/lib/http/cookie.rb @@ -300,6 +300,17 @@ class HTTP::Cookie "#{@name}=#{@value}" end + # Compares the cookie with another. When there are many cookies with + # the same name for a URL, the value of the smallest must be used. + def <=>(other) + # RFC 6265 5.4 + # Precedence: 1. longer path 2. older creation + (@name <=> other.name).nonzero? || + (other.path.length <=> @path.length).nonzero? || + @created_at <=> other.created_at + end + include Comparable + # YAML serialization helper for Syck. def to_yaml_properties PERSISTENT_PROPERTIES.map { |name| "@#{name}" } diff --git a/lib/http/cookie_jar.rb b/lib/http/cookie_jar.rb index 1195b36..52c8d12 100644 --- a/lib/http/cookie_jar.rb +++ b/lib/http/cookie_jar.rb @@ -51,11 +51,7 @@ class HTTP::CookieJar select { |cookie| !cookie.expired? && cookie.valid_for_uri?(url) && (cookie.accessed_at = now) - }.sort_by { |cookie| - # RFC 6265 5.4 - # Precedence: 1. longer path 2. older creation - [-cookie.path.length, cookie.created_at] - } + }.sort end def empty?(url) diff --git a/test/test_http_cookie_jar.rb b/test/test_http_cookie_jar.rb index 7a2bda7..0e53d89 100644 --- a/test/test_http_cookie_jar.rb +++ b/test/test_http_cookie_jar.rb @@ -123,6 +123,27 @@ class TestHTTPCookieJar < Test::Unit::TestCase assert_equal(0, @jar.cookies(URI('http://google.com/')).length) end + def test_add_multiple_cookies_with_the_same_name + now = Time.now + + cookies = [ + { :value => 'a', :path => '/', }, + { :value => 'b', :path => '/abc/def/', :created_at => now - 1 }, + { :value => 'c', :path => '/abc/def/', :domain => 'www.rubyforge.org', :created_at => now }, + { :value => 'd', :path => '/abc/' }, + ].map { |attrs| + HTTP::Cookie.new(cookie_values(attrs)) + } + + url = URI 'http://www.rubyforge.org/abc/def/ghi' + + cookies.permutation(cookies.size) { |shuffled| + @jar.clear + shuffled.each { |cookie| @jar.add(url, cookie) } + assert_equal %w[b c d a], @jar.cookies(url).map { |cookie| cookie.value } + } + end + def test_add_rejects_cookies_that_do_not_contain_an_embedded_dot url = URI 'http://rubyforge.org/'