]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Allow 204 responses without Content-Length/Transfer-Encoding
authorNick Coutsos <nick@coutsos.com>
Wed, 8 Jun 2016 01:15:17 +0000 (21:15 -0400)
committerNick Coutsos <nick@coutsos.com>
Wed, 8 Jun 2016 02:02:13 +0000 (22:02 -0400)
tornado/http1connection.py
tornado/test/simple_httpclient_test.py
tornado/test/web_test.py
tornado/web.py

index 43034c6b503d45404c9ef10d7917fcb77d106c45..d0e91b82766259b0c5c003dff523f8ffb3e90636 100644 (file)
@@ -351,7 +351,7 @@ class HTTP1Connection(httputil.HTTPConnection):
                 # 304 responses have no body (not even a zero-length body), and so
                 # should not have either Content-Length or Transfer-Encoding.
                 # headers.
-                start_line.code != 304 and
+                start_line.code not in (204, 304) and
                 # No need to chunk the output if a Content-Length is specified.
                 'Content-Length' not in headers and
                 # Applications are discouraged from touching Transfer-Encoding,
index 74073182d7afb418e7249a70082c39aa681dbf97..58ea14801df1c1e1e492344733a1a3f35d4bd2de 100644 (file)
@@ -73,10 +73,18 @@ class OptionsHandler(RequestHandler):
 
 class NoContentHandler(RequestHandler):
     def get(self):
+        start_line = ResponseStartLine("HTTP/1.1", 204, "No Content")
+        headers = HTTPHeaders()
+        chunk = None
+
         if self.get_argument("error", None):
-            self.set_header("Content-Length", "5")
-            self.write("hello")
-        self.set_status(204)
+            headers['Content-Length'] = "5"
+            chunk = b"hello"
+
+        # write directly to the connection because .write() and .finish() won't
+        # allow us to generate malformed responses
+        self.request.connection.write_headers(start_line, headers, chunk)
+        self.request.finish()
 
 
 class SeeOtherPostHandler(RequestHandler):
@@ -322,12 +330,11 @@ class SimpleHTTPClientTestMixin(object):
     def test_no_content(self):
         response = self.fetch("/no_content")
         self.assertEqual(response.code, 204)
-        # 204 status doesn't need a content-length, but tornado will
-        # add a zero content-length anyway.
+        # 204 status shouldn't have a content-length
         #
         # A test without a content-length header is included below
         # in HTTP204NoContentTestCase.
-        self.assertEqual(response.headers["Content-length"], "0")
+        self.assertNotIn("Content-Length", response.headers)
 
         # 204 status with non-zero content length is malformed
         with ExpectLog(gen_log, "Malformed HTTP message"):
index 744803a1b41944382a5c8f8df81d7a5b3f038a44..745d0fa84e0575150524208bdeee355216da7acd 100644 (file)
@@ -1397,6 +1397,19 @@ class ClearHeaderTest(SimpleHandlerTestCase):
         self.assertEqual(response.headers["h2"], "bar")
 
 
+class Header204Test(SimpleHandlerTestCase):
+    class Handler(RequestHandler):
+        def get(self):
+            self.set_status(204)
+            self.finish()
+
+    def test_204_headers(self):
+        response = self.fetch('/')
+        self.assertEqual(response.code, 204)
+        self.assertNotIn("Content-Length", response.headers)
+        self.assertNotIn("Transfer-Encoding", response.headers)
+
+
 @wsgi_safe
 class Header304Test(SimpleHandlerTestCase):
     class Handler(RequestHandler):
index 254a91ac5df78f1a3f76cc58d2ddf6e3f0ce0c8c..479dd2457cfa4c1cfed3713ed1b97278ed9e8dff 100644 (file)
@@ -935,8 +935,8 @@ class RequestHandler(object):
                 if self.check_etag_header():
                     self._write_buffer = []
                     self.set_status(304)
-            if self._status_code == 304:
-                assert not self._write_buffer, "Cannot send body with 304"
+            if self._status_code in (204, 304):
+                assert not self._write_buffer, "Cannot send body with %s" % self._status_code
                 self._clear_headers_for_304()
             elif "Content-Length" not in self._headers:
                 content_length = sum(len(part) for part in self._write_buffer)