]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Support Content-Length headers that have been duplicated by a proxy.
authorBen Darnell <ben@bendarnell.com>
Mon, 25 Jul 2011 02:59:14 +0000 (19:59 -0700)
committerBen Darnell <ben@bendarnell.com>
Mon, 25 Jul 2011 02:59:14 +0000 (19:59 -0700)
Closes #249.

tornado/simple_httpclient.py
tornado/test/simple_httpclient_test.py

index c072cf52ca66044c433837fbe3ff4793b258f823..c684e745da5550bab28d088adb5e6ba852b8044e 100644 (file)
@@ -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:
index 0c14806eb967a9d9c00e0d681079d5541f718248..bdea4fc70f6ec99e186b047288c3527b33ce44d6 100644 (file)
@@ -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)