]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Accept Content-Length headers in 304 responses.
authorBen Darnell <ben@bendarnell.com>
Sun, 25 Nov 2012 16:26:13 +0000 (11:26 -0500)
committerBen Darnell <ben@bendarnell.com>
Sun, 25 Nov 2012 16:26:13 +0000 (11:26 -0500)
Closes #639.

tornado/simple_httpclient.py
tornado/test/httpclient_test.py
website/sphinx/releases/next.rst

index be5fb6737d62ea683d24311a4cd159963ab74e17..faff83c8f06eb35c4eddbb016a8a470c38a2ade9 100644 (file)
@@ -365,12 +365,12 @@ class _HTTPConnection(object):
                 self.request.header_callback("%s: %s\r\n" % (k, v))
             self.request.header_callback('\r\n')
 
-        if self.request.method == "HEAD":
-            # HEAD requests never have content, even though they may have
-            # content-length headers
+        if self.request.method == "HEAD" or self.code == 304:
+            # HEAD requests and 304 responses never have content, even
+            # though they may have content-length headers
             self._on_body(b(""))
             return
-        if 100 <= self.code < 200 or self.code in (204, 304):
+        if 100 <= self.code < 200 or self.code == 204:
             # These response codes never have bodies
             # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
             if ("Transfer-Encoding" in self.headers or
index 88a85882422228b99fcce1ed89f9a5be56c2b3d0..6cc43171523abd4b4c935cd6642cca3035692cab 100644 (file)
@@ -63,6 +63,17 @@ class UserAgentHandler(RequestHandler):
         self.write(self.request.headers.get('User-Agent', 'User agent not set'))
 
 
+class ContentLength304Handler(RequestHandler):
+    def get(self):
+        self.set_status(304)
+        self.set_header('Content-Length', 42)
+
+    def _clear_headers_for_304(self):
+        # Tornado strips content-length from 304 responses, but here we
+        # want to simulate servers that include the headers anyway.
+        pass
+
+
 # These tests end up getting run redundantly: once here with the default
 # HTTPClient implementation, and then again in each implementation's own
 # test suite.
@@ -78,6 +89,7 @@ class HTTPClientCommonTestCase(AsyncHTTPTestCase):
             url("/countdown/([0-9]+)", CountdownHandler, name="countdown"),
             url("/echopost", EchoPostHandler),
             url("/user_agent", UserAgentHandler),
+            url("/304_with_content_length", ContentLength304Handler),
             ], gzip=True)
 
     def test_hello_world(self):
@@ -268,6 +280,14 @@ Transfer-Encoding: chunked
         response = self.wait()
         self.assertEqual(response.body, b('TestDefaultUserAgent'))
 
+    def test_304_with_content_length(self):
+        # According to the spec 304 responses SHOULD NOT include
+        # Content-Length or other entity headers, but some servers do it
+        # anyway.
+        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
+        response = self.fetch('/304_with_content_length')
+        self.assertEqual(response.code, 304)
+        self.assertEqual(response.headers['Content-Length'], '42')
 
 class RequestProxyTest(unittest.TestCase):
     def test_request_set(self):
index 36bfaa130f720115b19cc649b8bc49d0ee13e088..32ea2b81989e0393b0d7dc6eaeccca322543d0fa 100644 (file)
@@ -178,3 +178,5 @@ In progress
   ``use_gzip``, ``proxy_password``, ``allow_nonstandard_methods``,
   and ``validate_cert`` have been moved from `HTTPRequest` to the
   client implementations.
+* `simple_httpclient` now accepts responses with a 304 status code that
+  include a ``Content-Length`` header.