This class provides a CookieJar object for Mongrels. Just initialize
with response and request objects and then treat like a hash. Does not
depend on cgi.rb
ry
# Provides a Rails-like CookieJar class for Mongrels. (ry dahl, 1187362405)
# Unit tests at the bottom of this file. To execute the unit tests, use
# ruby -r rubygems cookies_for_mongrels.rb
require 'mongrel'
class Time
# Abbreviated day-of-week names specified by RFC 822
RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
# Abbreviated month names specified by RFC 822
RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
# Strange Cookie Expire time format
def gmt_rfc822
t = self.clone.gmtime
return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year, t.hour, t.min, t.sec)
end
end
module Mongrel
module Const # :nodoc:
HTTP_COOKIE = 'HTTP_COOKIE'.freeze
SET_COOKIE = 'Set-Cookie'.freeze
COOKIE_VALUE_EXPIRES = "%s=%s; path=/; expires=%s".freeze # as in Merb
COOKIE_VALUE = "%s=%s; path=/".freeze
COOKIE_EXPIRED_TIME = Time.at(0).freeze
COOKIE_SEPARATOR = ';,'
end
class CookieJar
def initialize(request, response)
@response = response
@cookies = HttpRequest.query_parse(
request.params[Const::HTTP_COOKIE], Const::COOKIE_SEPARATOR)
end
# Returns the value of the cookie by +name+ -- or nil if no such cookie
# exists. You set new cookies using either the cookie method
# or cookies[]= (for simple name/value cookies without options).
def [](name)
@cookies[name]
end
# Determines if a cookie key has been given by request. Does not include
# cookies which have been set during this request
def has_key?(name)
@cookies.has_key?(name)
end
# Gives the size of the number of cookies read. Does not include cookies
# which have been set during this request
def size
@cookies.size
end
# Removes the cookie on the client machine by setting the value to an
# empty string and setting its expiration date into the past.
def delete(name)
set_cookie(name, nil, COOKIE_EXPIRED_TIME)
end
# Sets a (name, value) pair to be stored on as a cookie on the clients
# computer. Optionally provide a Time object as an expiration date.
def set(name, value, expires = nil)
params = [name.to_s, HttpRequest.escape(value)]
@response.header[Const::SET_COOKIE] =
if expires
params << expires.gmt_rfc822
Const::COOKIE_VALUE_EXPIRES % params
else
Const::COOKIE_VALUE % params
end
end
alias_method :[]=, :set
end
end
if __FILE__ == $0
require 'test/unit'
require 'ostruct'
require 'cgi'
include Mongrel
class CookieJarTest < Test::Unit::TestCase
# Wdy, DD Mon YYYY HH:MM:SS GMT
RFC1123_REGEXP = %r{\w\w\w, \d\d \w\w\w \d\d\d\d \d\d:\d\d:\d\d GMT}
def request_mock(cookie_string)
OpenStruct.new(:params => {'HTTP_COOKIE' => cookie_string})
end
def setup
@out = StringIO.new
@response = HttpResponse.new(@out)
end
def test_blank_request
request = request_mock nil
cookies = CookieJar.new(request, @response)
assert_nil cookies['hello']
end
def test_set_single
request = request_mock ''
cookies = CookieJar.new(request, @response)
assert_nil cookies['hello']
cookies['hello'] = 'world'
@response.send_header
@out.rewind
assert_match 'Set-Cookie: hello=world; path=/', @out.read
end
def test_set_multiple
request = request_mock ''
cookies = CookieJar.new(request, @response)
assert_nil cookies['hello']
cookies['hello'] = 'world'
cookies['world'] = 'hello'
@response.send_header
@out.rewind
s = @out.read
assert_match %r{Set-Cookie: hello=world; path=/}, s
assert_match %r{Set-Cookie: world=hello; path=/}, s
assert_no_match %r{expires}, s
end
def test_set_with_expires
request = request_mock ''
cookies = CookieJar.new(request, @response)
cookies.set('hello', 'world', Time.now)
cookies.set('world', 'hello', Time.now)
@response.send_header
@out.rewind
s = @out.read
assert_match %r{Set-Cookie: hello=world; path=/; expires=}, s
assert_match %r{Set-Cookie: world=hello; path=/; expires=}, s
assert_match RFC1123_REGEXP, s
end
def test_read
request = request_mock 'hello=world; my name is=haaaaaapy; world=hello'
cookies = CookieJar.new(request, @response)
assert cookies.has_key?('hello')
assert_equal 'world', cookies['hello']
assert_equal 'haaaaaapy', cookies['my name is']
assert_equal 'hello', cookies['world']
assert_equal 3, cookies.size
end
end
end
_______________________________________________
Mongrel-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/mongrel-users