From: Ben Darnell Date: Mon, 25 Jul 2011 02:59:14 +0000 (-0700) Subject: Support Content-Length headers that have been duplicated by a proxy. X-Git-Tag: v2.1.0~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6fcc459e43ec1c14bfc3eaa90d669bacf3514751;p=thirdparty%2Ftornado.git Support Content-Length headers that have been duplicated by a proxy. Closes #249. --- diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index c072cf52c..c684e745d 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -309,6 +309,15 @@ class _HTTPConnection(object): self.chunks = [] self.stream.read_until(b("\r\n"), self._on_chunk_length) elif "Content-Length" in self.headers: + if "," in self.headers["Content-Length"]: + # Proxies sometimes cause Content-Length headers to get + # duplicated. If all the values are identical then we can + # use them but if they differ it's an error. + pieces = re.split(r',\s*', self.headers["Content-Length"]) + if any(i != pieces[0] for i in pieces): + raise ValueError("Multiple unequal Content-Lengths: %r" % + self.headers["Content-Length"]) + self.headers["Content-Length"] = pieces[0] self.stream.read_bytes(int(self.headers["Content-Length"]), self._on_body) else: diff --git a/tornado/test/simple_httpclient_test.py b/tornado/test/simple_httpclient_test.py index 0c14806eb..bdea4fc70 100644 --- a/tornado/test/simple_httpclient_test.py +++ b/tornado/test/simple_httpclient_test.py @@ -40,6 +40,11 @@ class HangHandler(RequestHandler): def get(self): pass +class ContentLengthHandler(RequestHandler): + def get(self): + self.set_header("Content-Length", self.get_argument("value")) + self.write("ok") + class SimpleHTTPClientTestCase(AsyncHTTPTestCase, LogTrapTestCase): def get_app(self): # callable objects to finish pending /trigger requests @@ -51,6 +56,7 @@ class SimpleHTTPClientTestCase(AsyncHTTPTestCase, LogTrapTestCase): url("/countdown/([0-9]+)", CountdownHandler, name="countdown"), url("/hang", HangHandler), url("/hello", HelloWorldHandler), + url("/content_length", ContentLengthHandler), ], gzip=True) def test_singleton(self): @@ -161,3 +167,13 @@ class SimpleHTTPClientTestCase(AsyncHTTPTestCase, LogTrapTestCase): response = self.wait() self.assertEqual(response.body, b("Hello world!")) + def test_multiple_content_length_accepted(self): + response = self.fetch("/content_length?value=2,2") + self.assertEqual(response.body, b("ok")) + response = self.fetch("/content_length?value=2,%202,2") + self.assertEqual(response.body, b("ok")) + + response = self.fetch("/content_length?value=2,4") + self.assertEqual(response.code, 599) + response = self.fetch("/content_length?value=2,%202,3") + self.assertEqual(response.code, 599)