Commit 68deba35 authored by Martijn Pieters's avatar Martijn Pieters

Collector #2300: delimit *all* headers with CRLF; accumulated_headers and...

Collector #2300: delimit *all* headers with CRLF; accumulated_headers and appendHeader use \n for delimeters and never get corrected on output
parent 2032469b
......@@ -4,6 +4,12 @@ Zope Changes
Change information for previous versions of Zope can be found in the
file HISTORY.txt.
Zope 2.9.8 (unreleased)
Bugs fixed
- Collector #2300: delimit *all* HTTP Response headers with CRLF.
Zope 2.9.7 (2007/03/25)
Bugs fixed
......
......@@ -114,8 +114,15 @@ class ZServerHTTPResponse(HTTPResponse):
self._chunking=1
else:
self.setHeader('Connection','close')
for key, val in headers.items():
headers = headers.items()
for line in self.accumulated_headers.splitlines():
if line[0] == '\t':
headers[-1][1] += '\n' + line
continue
headers.append(line.split(': ', 1))
for key, val in headers:
if key.lower()==key:
# only change non-literal header names
key="%s%s" % (key[:1].upper(), key[1:])
......@@ -125,10 +132,13 @@ class ZServerHTTPResponse(HTTPResponse):
key="%s-%s%s" % (key[:l],key[l+1:l+2].upper(),key[l+2:])
start=l+1
l=key.find('-',start)
val = val.replace('\n\t', '\r\n\t')
append("%s: %s" % (key, val))
if self.cookies:
headersl=headersl+self._cookie_list()
headersl[len(headersl):]=[self.accumulated_headers, body]
headersl.extend(self._cookie_list())
append('')
append(body)
return "\r\n".join(headersl)
_tempfile=None
......@@ -151,6 +161,7 @@ class ZServerHTTPResponse(HTTPResponse):
"""
if type(data) != type(''):
raise TypeError('Value must be a string')
......
......@@ -56,7 +56,7 @@ class ZServerResponseTestCase(unittest.TestCase):
one = ZServerHTTPResponse(stdout=DummyChannel())
self.assertRaises(AssertionError,
one.setBody, test_streamiterator())
class DummyChannel:
def __init__(self):
self.out = StringIO()
......@@ -92,8 +92,46 @@ class test_streamiterator:
return self.data
raise StopIteration
class ZServerHTTPResponseTestCase(unittest.TestCase):
"""Test ZServer HTTPResponse object"""
def _makeOne(self):
return ZServerHTTPResponse()
def testToString(self):
response = self._makeOne()
response.headers = {
'content-type': 'text/plain',
'all-lower-case': 'foo',
'Title-Cased': 'bar',
'mixed-CasED': 'spam',
'multilined': 'eggs\n\tham'}
response.accumulated_headers = 'foo-bar: bar\n\tbaz\nFoo-bar: monty\n'
response.cookies = dict(foo=dict(value='bar'))
response.body = 'A body\nwith multiple lines\n'
result = str(response)
headers, body = result.rsplit('\r\n\r\n')
self.assertEqual(body, response.body)
self.assertTrue(headers.startswith('HTTP/1.0 200 OK\r\n'))
# 15 header lines all delimited by \r\n
self.assertEqual(
['\n' in line for line in headers.split('\r\n')],
15 * [False])
self.assertTrue('Multilined: eggs\r\n\tham\r\n' in headers)
self.assertTrue('Foo-Bar: bar\r\n\tbaz\r\n' in headers)
def test_suite():
return unittest.makeSuite(ZServerResponseTestCase)
suite = unittest.TestSuite()
suite.addTests((
unittest.makeSuite(ZServerResponseTestCase),
unittest.makeSuite(ZServerHTTPResponseTestCase)
))
return suite
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment