[Zope3-checkins] SVN: Zope3/trunk/src/zope/publisher/ Add tests and
refactor cookie handling to use standard library Cookie.py
Stuart Bishop
stuart at stuartbishop.net
Wed Jul 14 23:08:12 EDT 2004
Log message for revision 26545:
Add tests and refactor cookie handling to use standard library Cookie.py
so that they pass
Changed:
U Zope3/trunk/src/zope/publisher/http.py
U Zope3/trunk/src/zope/publisher/tests/test_http.py
-=-
Modified: Zope3/trunk/src/zope/publisher/http.py
===================================================================
--- Zope3/trunk/src/zope/publisher/http.py 2004-07-15 02:45:08 UTC (rev 26544)
+++ Zope3/trunk/src/zope/publisher/http.py 2004-07-15 03:08:12 UTC (rev 26545)
@@ -19,6 +19,7 @@
from urllib import quote, unquote, splitport
from types import StringTypes, ClassType
from cgi import escape
+from Cookie import SimpleCookie
from zope.interface import implements
@@ -324,37 +325,16 @@
return '%s://%s' % (protocol, host)
- _cookieFormat = re.compile('[\x00- ]*'
- # Cookie name
- '([^\x00- ;,="]+)='
- # Cookie value (either correct quoted or MSIE)
- '(?:"([^"]*)"|([^\x00- ;,"]*))'
- '(?:[\x00- ]*[;,])?[\x00- ]*')
-
def _parseCookies(self, text, result=None):
"""Parse 'text' and return found cookies as 'result' dictionary."""
if result is None:
result = {}
- cookieFormat = self._cookieFormat
+ c = SimpleCookie(text)
+ for k,v in c.items():
+ result[unicode(k, ENCODING)] = unicode(v.value, ENCODING)
- pos = 0
- ln = len(text)
- while pos < ln:
- match = cookieFormat.match(text, pos)
- if match is None:
- break
-
- name = unicode(match.group(1), ENCODING)
- if name not in result:
- value, ms_value = match.group(2, 3)
- if value is None:
- value = ms_value
- result[name] = unicode(value, ENCODING)
-
- pos = match.end()
-
return result
def __setupCookies(self):
@@ -720,7 +700,7 @@
for k, v in kw.items():
if v is not None:
- cookie[k] = v
+ cookie[k.lower()] = v
cookie['value'] = value
@@ -829,36 +809,25 @@
return location
def _cookie_list(self):
- cookie_list = []
+ c = SimpleCookie()
for name, attrs in self._cookies.items():
+ name = str(name)
+ c[name] = attrs['value'].encode(ENCODING)
+ for k,v in attrs.items():
+ if k == 'value':
+ continue
+ if k == 'secure':
+ if v:
+ c[name]['secure'] = True
+ continue
+ if k == 'max_age':
+ k = 'max-age'
+ elif k == 'comment':
+ # Encode rather than throw an exception
+ v = quote(v.encode('utf-8'), safe="/?:@&+")
+ c[name][k] = str(v)
+ return str(c).splitlines()
- # Note that as of May 98, IE4 ignores cookies with
- # quoted cookie attr values, so only the value part
- # of name=value pairs may be quoted.
-
- cookie='Set-Cookie: %s="%s"' % (name, attrs['value'])
- for name, value in attrs.items():
- name = name.lower()
- if name == 'expires':
- cookie = '%s; Expires=%s' % (cookie,value)
- elif name == 'domain':
- cookie = '%s; Domain=%s' % (cookie,value)
- elif name == 'path':
- cookie = '%s; Path=%s' % (cookie,value)
- elif name == 'max_age':
- cookie = '%s; Max-Age=%s' % (cookie,value)
- elif name == 'comment':
- cookie = '%s; Comment=%s' % (cookie,value)
- elif name == 'secure' and value:
- cookie = '%s; Secure' % cookie
- cookie_list.append(cookie)
-
- # TODO: Should really check size of cookies here!
- # Why?
-
- return cookie_list
-
-
def getHeaderText(self, m):
lst = ['Status: %s %s' % (self._status, self._reason)]
items = m.items()
Modified: Zope3/trunk/src/zope/publisher/tests/test_http.py
===================================================================
--- Zope3/trunk/src/zope/publisher/tests/test_http.py 2004-07-15 02:45:08 UTC (rev 26544)
+++ Zope3/trunk/src/zope/publisher/tests/test_http.py 2004-07-15 03:08:12 UTC (rev 26545)
@@ -32,6 +32,7 @@
from zope.interface.verify import verifyObject
from StringIO import StringIO
+from Cookie import SimpleCookie, CookieError
class UserStub:
@@ -212,7 +213,8 @@
def testCookies(self):
cookies = {
- 'HTTP_COOKIE': 'foo=bar; spam="eggs", this="Should be accepted"'
+ 'HTTP_COOKIE':
+ 'foo=bar; path=/; spam="eggs", this="Should be accepted"'
}
req = self._createRequest(extra_env=cookies)
@@ -225,6 +227,15 @@
self.assertEquals(req.cookies[u'this'], u'Should be accepted')
self.assertEquals(req[u'this'], u'Should be accepted')
+ # Reserved key
+ self.failIf(req.cookies.has_key('path'))
+
+ def testCookiesUnicode(self):
+ # Cookie values are assumed to be UTF-8 encoded
+ cookies = {'HTTP_COOKIE': r'key="\342\230\243";'}
+ req = self._createRequest(extra_env=cookies)
+ self.assertEquals(req.cookies[u'key'], u'\N{BIOHAZARD SIGN}')
+
def testHeaders(self):
headers = {
'TEST_HEADER': 'test',
@@ -421,7 +432,15 @@
headers = {}
for line in hdrs_text.splitlines():
key, val = line.split(":", 1)
- headers[key.strip()] = val.strip()
+ key = key.strip()
+ val = val.strip()
+ if headers.has_key(key):
+ if type(headers[key]) == type([]):
+ headers[key].append(val)
+ else:
+ headers[key] = [headers[key], val]
+ else:
+ headers[key] = val
return headers, body
def _getResultFromResponse(self, body, charset=None, headers=None):
@@ -476,7 +495,68 @@
eq("image/gif", headers["Content-Type"])
eq("test", body)
+ def _getCookieFromResponse(self, cookies):
+ # Shove the cookies through request, parse the Set-Cookie header
+ # and spit out a list of headers for examination
+ response, stream = self._createResponse()
+ for name, value, kw in cookies:
+ response.setCookie(name, value, **kw)
+ response.setBody('test')
+ response.outputBody()
+ headers, body = self._parseResult(stream.getvalue())
+ c = SimpleCookie()
+ cookie_headers = headers["Set-Cookie"]
+ if type(cookie_headers) != type([]):
+ cookie_headers = [cookie_headers]
+ return cookie_headers
+ def testSetCookie(self):
+ c = self._getCookieFromResponse([
+ ('foo', 'bar', {}),
+ ])
+ self.failUnless('foo=bar;' in c, 'foo=bar not in %r' % c)
+
+ c = self._getCookieFromResponse([
+ ('foo', 'bar', {}),
+ ('alpha', 'beta', {}),
+ ])
+ self.failUnless('foo=bar;' in c)
+ self.failUnless('alpha=beta;' in c)
+
+ c = self._getCookieFromResponse([
+ ('sign', u'\N{BIOHAZARD SIGN}', {}),
+ ])
+ self.failUnless(r'sign="\342\230\243";' in c)
+
+ self.assertRaises(
+ CookieError,
+ self._getCookieFromResponse,
+ [('path', 'invalid key', {}),]
+ )
+
+ c = self._getCookieFromResponse([
+ ('foo', 'bar', {
+ 'Expires': 'Sat, 12 Jul 2014 23:26:28 GMT',
+ 'domain': 'example.com',
+ 'pAth': '/froboz',
+ 'max_age': 3600,
+ 'comment': u'blah;\N{BIOHAZARD SIGN}?',
+ 'seCure': True,
+ }),
+ ])[0]
+ self.failUnless('foo=bar;' in c)
+ self.failUnless('expires=Sat, 12 Jul 2014 23:26:28 GMT;' in c, repr(c))
+ self.failUnless('Domain=example.com;' in c)
+ self.failUnless('Path=/froboz;' in c)
+ self.failUnless('Max-Age=3600;' in c)
+ self.failUnless('Comment=blah%3B%E2%98%A3?;' in c, repr(c))
+ self.failUnless('secure;' in c)
+
+ c = self._getCookieFromResponse([('foo', 'bar', {'secure': False})])[0]
+ self.failUnless('foo=bar;' in c)
+ self.failIf('secure' in c)
+
+
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ConcreteHTTPTests))
More information about the Zope3-Checkins
mailing list