mirror of
https://github.com/samsonjs/http-cookie.git
synced 2026-04-27 14:57:46 +00:00
Allow assigning nil to the cookie value to make an expiration cookie.
Cookie.new(): Make the value parameter can be omittable.
This commit is contained in:
parent
8c30527293
commit
82e65b4a9b
2 changed files with 95 additions and 17 deletions
|
|
@ -65,6 +65,23 @@ class HTTP::Cookie
|
||||||
end
|
end
|
||||||
private :check_string_type
|
private :check_string_type
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Hash.respond_to?(:try_convert)
|
||||||
|
def check_hash_type(object)
|
||||||
|
Hash.try_convert(object)
|
||||||
|
end
|
||||||
|
private :check_hash_type
|
||||||
|
else
|
||||||
|
def check_hash_type(object)
|
||||||
|
if object.is_a?(Hash) ||
|
||||||
|
(object.respond_to?(:to_h) && (object = object.to_str).is_a?(Hash))
|
||||||
|
object
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
private :check_hash_type
|
||||||
|
end
|
||||||
# :startdoc:
|
# :startdoc:
|
||||||
|
|
||||||
# The cookie name. It may not be nil or empty.
|
# The cookie name. It may not be nil or empty.
|
||||||
|
|
@ -84,6 +101,10 @@ class HTTP::Cookie
|
||||||
# Assign a string containing a control character (`\x00-\x1F` and
|
# Assign a string containing a control character (`\x00-\x1F` and
|
||||||
# `\x7F`) will raise ArgumentError.
|
# `\x7F`) will raise ArgumentError.
|
||||||
#
|
#
|
||||||
|
# Assigning nil sets the value to an empty string and the expiration
|
||||||
|
# date to the Unix epoch. This is a handy way to make a cookie for
|
||||||
|
# expiration.
|
||||||
|
#
|
||||||
# Note that RFC 6265 4.1.1 lists more characters disallowed for use
|
# Note that RFC 6265 4.1.1 lists more characters disallowed for use
|
||||||
# in a cookie value, which are these: ` ",;\`. Using these
|
# in a cookie value, which are these: ` ",;\`. Using these
|
||||||
# characters will reduce interoperability.
|
# characters will reduce interoperability.
|
||||||
|
|
@ -136,9 +157,9 @@ class HTTP::Cookie
|
||||||
# :attr_accessor: max_age
|
# :attr_accessor: max_age
|
||||||
|
|
||||||
# :call-seq:
|
# :call-seq:
|
||||||
# new(name, value)
|
# new(name, value = nil)
|
||||||
# new(name, value, attr_hash)
|
# new(name, value = nil, **attr_hash)
|
||||||
# new(attr_hash)
|
# new(**attr_hash)
|
||||||
#
|
#
|
||||||
# Creates a cookie object. For each key of `attr_hash`, the setter
|
# Creates a cookie object. For each key of `attr_hash`, the setter
|
||||||
# is called if defined. Each key can be either a symbol or a
|
# is called if defined. Each key can be either a symbol or a
|
||||||
|
|
@ -148,6 +169,9 @@ class HTTP::Cookie
|
||||||
# is defined. Beware, however, any error (typically ArgumentError)
|
# is defined. Beware, however, any error (typically ArgumentError)
|
||||||
# a setter method raises will be passed through.
|
# a setter method raises will be passed through.
|
||||||
#
|
#
|
||||||
|
# If `value` is omitted or it is nil, an expiration cookie is
|
||||||
|
# created unless `max_age` or `expires` (`expires_at`) is given.
|
||||||
|
#
|
||||||
# e.g.
|
# e.g.
|
||||||
#
|
#
|
||||||
# new("uid", "a12345")
|
# new("uid", "a12345")
|
||||||
|
|
@ -158,21 +182,29 @@ class HTTP::Cookie
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
@origin = @domain = @path =
|
@origin = @domain = @path =
|
||||||
@expires = @max_age = nil
|
@expires = @max_age = nil
|
||||||
@secure = @httponly = false
|
@for_domain = @secure = @httponly = false
|
||||||
@session = true
|
@session = true
|
||||||
@created_at = @accessed_at = Time.now
|
@created_at = @accessed_at = Time.now
|
||||||
|
case argc = args.size
|
||||||
case args.size
|
|
||||||
when 2
|
|
||||||
self.name, self.value = *args
|
|
||||||
@for_domain = false
|
|
||||||
return
|
|
||||||
when 3
|
|
||||||
self.name, self.value, attr_hash = *args
|
|
||||||
when 1
|
when 1
|
||||||
attr_hash = args.first
|
if attr_hash = check_hash_type(args.last)
|
||||||
|
args.pop
|
||||||
else
|
else
|
||||||
raise ArgumentError, "wrong number of arguments (#{args.size} for 1-3)"
|
self.name, self.value = args # value is set to nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
when 2..3
|
||||||
|
if attr_hash = check_hash_type(args.last)
|
||||||
|
args.pop
|
||||||
|
self.name, value = args
|
||||||
|
else
|
||||||
|
argc == 2 or
|
||||||
|
raise ArgumentError, "wrong number of arguments (#{argc} for 1-3)"
|
||||||
|
self.name, self.value = args
|
||||||
|
return
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise ArgumentError, "wrong number of arguments (#{argc} for 1-3)"
|
||||||
end
|
end
|
||||||
for_domain = false
|
for_domain = false
|
||||||
domain = max_age = origin = nil
|
domain = max_age = origin = nil
|
||||||
|
|
@ -182,6 +214,8 @@ class HTTP::Cookie
|
||||||
val = val ? true : false
|
val = val ? true : false
|
||||||
end
|
end
|
||||||
case skey
|
case skey
|
||||||
|
when 'value'
|
||||||
|
value = val
|
||||||
when 'for_domain'
|
when 'for_domain'
|
||||||
for_domain = !!val
|
for_domain = !!val
|
||||||
when 'domain'
|
when 'domain'
|
||||||
|
|
@ -196,13 +230,14 @@ class HTTP::Cookie
|
||||||
__send__(setter, val) if respond_to?(setter)
|
__send__(setter, val) if respond_to?(setter)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
if @name.nil? || @value.nil?
|
if @name.nil?
|
||||||
raise ArgumentError, "at least name and value must be specified"
|
raise ArgumentError, "name must be specified"
|
||||||
end
|
end
|
||||||
@for_domain = for_domain
|
@for_domain = for_domain
|
||||||
self.domain = domain if domain
|
self.domain = domain if domain
|
||||||
self.origin = origin if origin
|
self.origin = origin if origin
|
||||||
self.max_age = max_age if max_age
|
self.max_age = max_age if max_age
|
||||||
|
self.value = value.nil? && (@expires || @max_age) ? '' : value
|
||||||
end
|
end
|
||||||
|
|
||||||
autoload :Scanner, 'http/cookie/scanner'
|
autoload :Scanner, 'http/cookie/scanner'
|
||||||
|
|
@ -343,6 +378,10 @@ class HTTP::Cookie
|
||||||
|
|
||||||
# See #value.
|
# See #value.
|
||||||
def value=(value)
|
def value=(value)
|
||||||
|
if value.nil?
|
||||||
|
self.expires = UNIX_EPOCH
|
||||||
|
return @value = ''
|
||||||
|
end
|
||||||
value = check_string_type(value) or
|
value = check_string_type(value) or
|
||||||
raise TypeError, "#{value.class} is not a String"
|
raise TypeError, "#{value.class} is not a String"
|
||||||
if value.match(/[\x00-\x1F\x7F]/)
|
if value.match(/[\x00-\x1F\x7F]/)
|
||||||
|
|
|
||||||
|
|
@ -510,11 +510,34 @@ class TestHTTPCookie < Test::Unit::TestCase
|
||||||
cookie.acceptable?
|
cookie.acceptable?
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_raises(ArgumentError) { HTTP::Cookie.new(:name => 'name') }
|
assert_raises(ArgumentError) { HTTP::Cookie.new() }
|
||||||
assert_raises(ArgumentError) { HTTP::Cookie.new(:value => 'value') }
|
assert_raises(ArgumentError) { HTTP::Cookie.new(:value => 'value') }
|
||||||
assert_raises(ArgumentError) { HTTP::Cookie.new('', 'value') }
|
assert_raises(ArgumentError) { HTTP::Cookie.new('', 'value') }
|
||||||
assert_raises(ArgumentError) { HTTP::Cookie.new('key=key', 'value') }
|
assert_raises(ArgumentError) { HTTP::Cookie.new('key=key', 'value') }
|
||||||
assert_raises(ArgumentError) { HTTP::Cookie.new("key\tkey", 'value') }
|
assert_raises(ArgumentError) { HTTP::Cookie.new("key\tkey", 'value') }
|
||||||
|
assert_raises(ArgumentError) { HTTP::Cookie.new('key', 'value', 'something') }
|
||||||
|
assert_raises(ArgumentError) { HTTP::Cookie.new('key', 'value', {}, 'something') }
|
||||||
|
|
||||||
|
[
|
||||||
|
HTTP::Cookie.new(:name => 'name'),
|
||||||
|
HTTP::Cookie.new("key", nil, :for_domain => true),
|
||||||
|
HTTP::Cookie.new("key", nil),
|
||||||
|
HTTP::Cookie.new("key", :secure => true),
|
||||||
|
HTTP::Cookie.new("key"),
|
||||||
|
].each { |cookie|
|
||||||
|
assert_equal '', cookie.value
|
||||||
|
assert_equal true, cookie.expired?
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
HTTP::Cookie.new(:name => 'name', :max_age => 3600),
|
||||||
|
HTTP::Cookie.new("key", nil, :expires => Time.now + 3600),
|
||||||
|
HTTP::Cookie.new("key", :expires => Time.now + 3600),
|
||||||
|
HTTP::Cookie.new("key", :expires => Time.now + 3600, :value => nil),
|
||||||
|
].each { |cookie|
|
||||||
|
assert_equal '', cookie.value
|
||||||
|
assert_equal false, cookie.expired?
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def cookie_values(options = {})
|
def cookie_values(options = {})
|
||||||
|
|
@ -681,6 +704,22 @@ class TestHTTPCookie < Test::Unit::TestCase
|
||||||
assert_equal false, cookie.acceptable?
|
assert_equal false, cookie.acceptable?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_value
|
||||||
|
cookie = HTTP::Cookie.new('name', 'value')
|
||||||
|
assert_equal 'value', cookie.value
|
||||||
|
|
||||||
|
cookie.value = 'new value'
|
||||||
|
assert_equal 'new value', cookie.value
|
||||||
|
|
||||||
|
assert_raises(ArgumentError) { cookie.value = "a\tb" }
|
||||||
|
assert_raises(ArgumentError) { cookie.value = "a\nb" }
|
||||||
|
|
||||||
|
assert_equal false, cookie.expired?
|
||||||
|
cookie.value = nil
|
||||||
|
assert_equal '', cookie.value
|
||||||
|
assert_equal true, cookie.expired?
|
||||||
|
end
|
||||||
|
|
||||||
def test_path
|
def test_path
|
||||||
uri = URI.parse('http://example.com/foo/bar')
|
uri = URI.parse('http://example.com/foo/bar')
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue