Add Cookie.cookie_value and Cookie.cookie_value_to_hash.

This commit is contained in:
Akinori MUSHA 2013-04-12 02:15:13 +09:00
parent 82e65b4a9b
commit e1857d76a4
3 changed files with 72 additions and 6 deletions

View file

@ -313,9 +313,7 @@ class HTTP::Cookie
origin = URI(origin)
[].tap { |cookies|
s = Scanner.new(set_cookie, logger)
until s.eos?
name, value, attrs = s.scan_cookie
Scanner.new(set_cookie, logger).scan_set_cookie { |name, value, attrs|
break if name.nil? || name.empty?
cookie = new(name, value)
@ -352,7 +350,24 @@ class HTTP::Cookie
yield cookie if block_given?
cookies << cookie
end
}
}
end
# Takes an array of cookies and returns a string for use in the
# Cookie header, like "name1=value2; name2=value2".
def cookie_value(cookies)
cookies.join('; ')
end
# Parses a Cookie header value into a hash of name-value string
# pairs. The first appearance takes precedence if multiple pairs
# with the same name occur.
def cookie_value_to_hash(cookie_value)
{}.tap { |hash|
Scanner.new(cookie_value).scan_cookie { |name, value|
hash[name] ||= value
}
}
end
end

View file

@ -150,7 +150,14 @@ class HTTP::Cookie::Scanner < StringScanner
tuple_to_time(day_of_month, month, year, time)
end
def scan_cookie
def scan_set_cookie
unless block_given?
scan_set_cookie { |*values|
return values
}
return
end
# RFC 6265 4.1.1 & 5.2
until eos?
start = pos
@ -211,7 +218,29 @@ class HTTP::Cookie::Scanner < StringScanner
next
end
return [name, value, attrs] if value
yield name, value, attrs if value
end
end
def scan_cookie
unless block_given?
scan_cookie { |*values|
return values
}
return
end
# RFC 6265 4.1.1 & 5.4
until eos?
skip_wsp
name, value = scan_name_value
yield name, value if name && value
# The comma is used as separator for concatenating multiple
# values of a header.
skip(/[;,]/)
end
end
end

View file

@ -400,6 +400,28 @@ class TestHTTPCookie < Test::Unit::TestCase
cookie = HTTP::Cookie.new('foo', value)
assert_equal(cookie_value, cookie.cookie_value)
}
pairs = [
['Foo', 'value1'],
['Bar', 'value 2'],
['Baz', 'value3'],
['Bar', 'value"4'],
]
cookie_value = HTTP::Cookie.cookie_value(pairs.map { |name, value|
HTTP::Cookie.new(:name => name, :value => value)
})
assert_equal 'Foo=value1; Bar="value 2"; Baz=value3; Bar="value\\"4"', cookie_value
hash = HTTP::Cookie.cookie_value_to_hash(cookie_value)
assert_equal 3, hash.size
hash.each_pair { |name, value|
_, pvalue = pairs.assoc(name)
assert_equal pvalue, value
}
end
def test_set_cookie_value