From 80f303c24faf77522b95cbbf1266356a078849a9 Mon Sep 17 00:00:00 2001 From: Marcel Hellkamp Date: Thu, 27 Oct 2011 17:05:54 +0200 Subject: [PATCH] Fix: Request.set_cookie() now accepts expire=datetime/int and max_age=timedelta, as documented. --- bottle.py | 25 ++++++++++++++++++------- test/test_environ.py | 32 ++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/bottle.py b/bottle.py index accfc0389..208e92b8b 100755 --- a/bottle.py +++ b/bottle.py @@ -39,6 +39,7 @@ import warnings from Cookie import SimpleCookie +from datetime import date as datedate, datetime, timedelta from tempfile import TemporaryFile from traceback import format_exc from urlparse import urljoin, SplitResult as UrlSplitResult @@ -851,7 +852,7 @@ def headers(self): ''' A :class:`WSGIHeaderDict` that provides case-insensitive access to HTTP request headers. ''' return WSGIHeaderDict(self.environ) - + def get_header(self, name, default=None): ''' Return the value of a request header, or a given default value. ''' return self.headers.get(name, default) @@ -1309,11 +1310,11 @@ def COOKIES(self): self._cookies = SimpleCookie() return self._cookies - def set_cookie(self, key, value, secret=None, **options): + def set_cookie(self, name, value, secret=None, **options): ''' Create a new cookie or replace an old one. If the `secret` parameter is set, create a `Signed Cookie` (described below). - :param key: the name of the cookie. + :param name: the name of the cookie. :param value: the value of the cookie. :param secret: a signature key required for signed cookies. @@ -1346,14 +1347,24 @@ def set_cookie(self, key, value, secret=None, **options): self._cookies = SimpleCookie() if secret: - value = touni(cookie_encode((key, value), secret)) + value = touni(cookie_encode((name, value), secret)) elif not isinstance(value, basestring): raise TypeError('Secret key missing for non-string Cookie.') if len(value) > 4096: raise ValueError('Cookie value to long.') - self._cookies[key] = value - for k, v in options.iteritems(): - self._cookies[key][k.replace('_', '-')] = v + self._cookies[name] = value + + for key, value in options.iteritems(): + if key == 'max_age': + if isinstance(value, timedelta): + value = value.seconds + value.days * 24 * 3600 + if key == 'expires': + if isinstance(value, (datedate, datetime)): + value = value.timetuple() + elif isinstance(value, (int, float)): + value = time.gmtime(value) + value = time.strftime("%a, %d %b %Y %H:%M:%S GMT", value) + self._cookies[name][key.replace('_', '-')] = value def delete_cookie(self, key, **kwargs): ''' Delete a cookie. Be sure to use the same `domain` and `path` diff --git a/test/test_environ.py b/test/test_environ.py index ca755c644..81ca69549 100755 --- a/test/test_environ.py +++ b/test/test_environ.py @@ -452,14 +452,34 @@ def test_charset(self): self.assertEqual(rs.charset, 'UTF-8') def test_set_cookie(self): - response = BaseResponse() - response.set_cookie('name', 'value', max_age=5) - response.set_cookie('name2', 'value 2', path='/foo') - cookies = [value for name, value in response.wsgiheader() + r = BaseResponse() + r.set_cookie('name1', 'value', max_age=5) + r.set_cookie('name2', 'value 2', path='/foo') + cookies = [value for name, value in r.headerlist if name.title() == 'Set-Cookie'] cookies.sort() - self.assertTrue(cookies[0], 'name=value; Max-Age=5') - self.assertTrue(cookies[1], 'name2="value 2"; Path=/foo') + self.assertEqual(cookies[0], 'name1=value; Max-Age=5') + self.assertEqual(cookies[1], 'name2="value 2"; Path=/foo') + + def test_set_cookie_maxage(self): + import datetime + r = BaseResponse() + r.set_cookie('name1', 'value', max_age=5) + r.set_cookie('name2', 'value', max_age=datetime.timedelta(days=1)) + cookies = sorted([value for name, value in r.headerlist + if name.title() == 'Set-Cookie']) + self.assertEqual(cookies[0], 'name1=value; Max-Age=5') + self.assertEqual(cookies[1], 'name2=value; Max-Age=86400') + + def test_set_cookie_expires(self): + import datetime + r = BaseResponse() + r.set_cookie('name1', 'value', expires=42) + r.set_cookie('name2', 'value', expires=datetime.datetime(1970,1,1,0,0,43)) + cookies = sorted([value for name, value in r.headerlist + if name.title() == 'Set-Cookie']) + self.assertEqual(cookies[0], 'name1=value; expires=Thu, 01 Jan 1970 00:00:42 GMT') + self.assertEqual(cookies[1], 'name2=value; expires=Thu, 01 Jan 1970 00:00:43 GMT') def test_delete_cookie(self): response = BaseResponse()