Commit 2f653107 authored by Ralf Schmitt's avatar Ralf Schmitt Committed by Denis Bilenko

fix handling of multiline HTTP headers in pywsgi

this is issue https://github.com/SiteSupport/gevent/issues/116

the mimetools Message class isn't of much help here, but replacing it
probably will do more harm than good. so, we parse multiline headers
on our own.

The
,----
| if 'bytearray' in __builtins__.__dict__:
`----
fails when running under py.test, so I replaced that too.
parent 266ab4c3
...@@ -523,6 +523,23 @@ class WSGIHandler(object): ...@@ -523,6 +523,23 @@ class WSGIHandler(object):
self.start_response(_INTERNAL_ERROR_STATUS, _INTERNAL_ERROR_HEADERS) self.start_response(_INTERNAL_ERROR_STATUS, _INTERNAL_ERROR_HEADERS)
self.write(_INTERNAL_ERROR_BODY) self.write(_INTERNAL_ERROR_BODY)
def _headers(self):
key = None
value = None
for header in self.headers.headers:
if key is not None and header[:1] in " \t":
value += header
continue
if key not in (None, 'CONTENT_TYPE', 'CONTENT_LENGTH'):
yield 'HTTP_' + key, value.strip()
key, value = header.split(':', 1)
key = key.replace('-', '_').upper()
if key not in (None, 'CONTENT_TYPE', 'CONTENT_LENGTH'):
yield 'HTTP_' + key, value.strip()
def get_environ(self): def get_environ(self):
env = self.server.get_environ() env = self.server.get_environ()
env['REQUEST_METHOD'] = self.command env['REQUEST_METHOD'] = self.command
...@@ -548,19 +565,14 @@ class WSGIHandler(object): ...@@ -548,19 +565,14 @@ class WSGIHandler(object):
env['REMOTE_ADDR'] = str(client_address[0]) env['REMOTE_ADDR'] = str(client_address[0])
env['REMOTE_PORT'] = str(client_address[1]) env['REMOTE_PORT'] = str(client_address[1])
for header in self.headers.headers: for key, value in self._headers():
key, value = header.split(':', 1) if key in env:
key = key.replace('-', '_').upper() if 'COOKIE' in key:
if key not in ('CONTENT_TYPE', 'CONTENT_LENGTH'): env[key] += '; ' + value
value = value.strip()
key = 'HTTP_' + key
if key in env:
if 'COOKIE' in key:
env[key] += '; ' + value
else:
env[key] += ',' + value
else: else:
env[key] = value env[key] += ',' + value
else:
env[key] = value
if env.get('HTTP_EXPECT') == '100-continue': if env.get('HTTP_EXPECT') == '100-continue':
socket = self.socket socket = self.socket
......
...@@ -371,7 +371,7 @@ class TestYield(CommonTests): ...@@ -371,7 +371,7 @@ class TestYield(CommonTests):
yield "not found" yield "not found"
if 'bytearray' in __builtins__.__dict__: if sys.version_info[:2] >= (2, 6):
class TestBytearray(CommonTests): class TestBytearray(CommonTests):
...@@ -388,6 +388,27 @@ if 'bytearray' in __builtins__.__dict__: ...@@ -388,6 +388,27 @@ if 'bytearray' in __builtins__.__dict__:
return [bytearray("not found")] return [bytearray("not found")]
class MultiLineHeader(TestCase):
@staticmethod
def application(env, start_response):
assert "test.submit" in env["CONTENT_TYPE"]
start_response('200 OK', [('Content-Type', 'text/plain')])
return ["ok"]
def test_multiline_116(self):
"""https://github.com/SiteSupport/gevent/issues/116"""
request = '\r\n'.join((
'POST / HTTP/1.0',
'Host: localhost',
'Content-Type: multipart/related; boundary="====XXXX====";',
' type="text/xml";start="test.submit"',
'Content-Length: 0',
'', ''))
fd = self.makefile()
fd.write(request)
read_http(fd, version='1.0')
class TestGetArg(TestCase): class TestGetArg(TestCase):
@staticmethod @staticmethod
......
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