]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
http1connection: Fix a bug with redirects and chunked requests
authorBen Darnell <ben@bendarnell.com>
Tue, 1 Jan 2019 17:50:07 +0000 (12:50 -0500)
committerBen Darnell <ben@bendarnell.com>
Tue, 1 Jan 2019 17:50:07 +0000 (12:50 -0500)
After a redirect, the chunked-encoding header is already set and would
not be detected correctly. This affects empty bodies with
allow_nonstandard_methods and any use of body_producer.

tornado/http1connection.py
tornado/test/httpclient_test.py

index 30f2a172eee77fe1f4c596a5206b437e34ec5793..fd63be62759efa8dc7a34b3d10a1546820bff011 100644 (file)
@@ -390,7 +390,10 @@ class HTTP1Connection(httputil.HTTPConnection):
             self._chunking_output = (
                 start_line.method in ("POST", "PUT", "PATCH")
                 and "Content-Length" not in headers
-                and "Transfer-Encoding" not in headers
+                and (
+                    "Transfer-Encoding" not in headers
+                    or headers["Transfer-Encoding"] == "chunked"
+                )
             )
         else:
             assert isinstance(start_line, httputil.ResponseStartLine)
index 29319c743a7b32ff0520d940fadf221c2e9a67c7..9adbcea46d4d152cc99046dc9d6df0729a8436d6 100644 (file)
@@ -307,6 +307,21 @@ Transfer-Encoding: chunked
         # don't either).
         self.assertEqual(301, response.code)
 
+    def test_redirect_put_with_body(self):
+        response = self.fetch(
+            "/redirect?url=/put&status=307", method="PUT", body="hello"
+        )
+        self.assertEqual(response.body, b"Put body: hello")
+
+    def test_redirect_put_without_body(self):
+        # This "without body" edge case is similar to what happens with body_producer.
+        response = self.fetch(
+            "/redirect?url=/put&status=307",
+            method="PUT",
+            allow_nonstandard_methods=True,
+        )
+        self.assertEqual(response.body, b"Put body: ")
+
     def test_credentials_in_url(self):
         url = self.get_url("/auth").replace("http://", "http://me:secret@")
         response = self.fetch(url)