summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2014-09-06 14:47:19 +0200
committerMarkus Unterwaditzer <markus@unterwaditzer.net>2014-09-06 16:26:40 +0200
commit45c8ea57e3cac6c204642cb7434244c23cf62a58 (patch)
tree51dfa5f44e1f0d9e6fe00937932071c51ca0cdd2
parente729594dcadb2d20af6f55e2cbce7efb3aaff6b8 (diff)
downloadwerkzeug-header_merging.tar.gz
Added proper header merging to the simple server.header_merging
-rw-r--r--CHANGES1
-rw-r--r--werkzeug/serving.py26
-rw-r--r--werkzeug/testsuite/serving.py21
3 files changed, 46 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 7ebab759..8b15bb9c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -26,6 +26,7 @@ Version 0.9.7
- ``werkzeug.urls.url_fix`` now doesn't crash on malformed URLs anymore, but
returns them unmodified. This is a cheap workaround for ``#582``, the proper
fix is included in version 0.10.
+- Fixed header concatenation on the Werkzeug server.
Version 0.9.6
-------------
diff --git a/werkzeug/serving.py b/werkzeug/serving.py
index 98e9d1f6..76501033 100644
--- a/werkzeug/serving.py
+++ b/werkzeug/serving.py
@@ -61,7 +61,23 @@ from werkzeug._internal import _log
from werkzeug._compat import iteritems, PY2, reraise, text_type, \
wsgi_encoding_dance
from werkzeug.urls import url_parse, url_unquote
-from werkzeug.exceptions import InternalServerError, BadRequest
+from werkzeug.exceptions import InternalServerError
+
+
+def _iter_headers(lineiter):
+ """Super crappy way to iterate over lines that might look like HTTP
+ headers. This must only be used with preparsed HTTP messages. This
+ would be nice if it was not necessary but unfortunately the rfc822
+ Message in the stdlib is not very good.
+ """
+ rv = []
+ for line in lineiter:
+ if not line[:1].isspace():
+ key, value = line.split(':', 1)
+ rv.append((key.strip(), value.strip()))
+ elif rv:
+ rv[-1] = (rv[-1][0], rv[-1][1] + '\n ' + line[1:].strip())
+ return rv
class WSGIRequestHandler(BaseHTTPRequestHandler, object):
@@ -104,9 +120,15 @@ class WSGIRequestHandler(BaseHTTPRequestHandler, object):
'SERVER_PROTOCOL': self.request_version
}
- for key, value in self.headers.items():
+ for key, value in _iter_headers(self.headers.headers):
key = 'HTTP_' + key.upper().replace('-', '_')
if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
+ if key in environ:
+ value = '%s%s%s' % (
+ environ[key],
+ key == 'HTTP_COOKIE' and '; ' or ', ',
+ value,
+ )
environ[key] = value
if request_url.netloc:
diff --git a/werkzeug/testsuite/serving.py b/werkzeug/testsuite/serving.py
index e478de26..0bc1b0b5 100644
--- a/werkzeug/testsuite/serving.py
+++ b/werkzeug/testsuite/serving.py
@@ -110,6 +110,27 @@ class ServingTestCase(WerkzeugTestCase):
res = conn.getresponse()
assert res.read() == b'YES'
+ @silencestderr
+ def test_header_merging(self):
+ def asserting_app(environ, start_response):
+ assert environ['HTTP_X_FOO'] == 'foo, bar'
+ assert environ['HTTP_COOKIE'] == 'foo; bar'
+ assert environ['HTTP_CONT'] == '1 2\n 3'
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ return [b'OK']
+
+ server, addr = run_dev_server(asserting_app)
+ conn = httplib.HTTPConnection(addr)
+ conn.putrequest('GET', '/')
+ conn.putheader('X-Foo', 'foo')
+ conn.putheader('X_Foo', 'bar')
+ conn.putheader('Cookie', 'foo')
+ conn.putheader('Cookie', 'bar')
+ conn.putheader('Cont', '1 2\n 3')
+ conn.endheaders()
+ res = conn.getresponse()
+ assert res.read() == b'OK'
+
def suite():
suite = unittest.TestSuite()