]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Fix a regression in gzip output for StaticFileHandler.
authorBen Darnell <ben@bendarnell.com>
Sat, 23 Aug 2014 22:12:19 +0000 (18:12 -0400)
committerBen Darnell <ben@bendarnell.com>
Sun, 24 Aug 2014 16:02:01 +0000 (12:02 -0400)
Streaming static responses confused the gzip output transform since
it could no longer set the correct outgoing content-length.  Now
it will fall back to chunked encoding in this case.

Closes #1156.

tornado/test/web_test.py
tornado/web.py

index 496ae2e8fcd1a01be15a7a7d6c324df1c71fe2cc..b8ee49f578f35191f8d8072f8bb3ad67382ed805 100644 (file)
@@ -1348,7 +1348,9 @@ class GzipTestCase(SimpleHandlerTestCase):
             self.write('hello world')
 
     def get_app_kwargs(self):
-        return dict(gzip=True)
+        return dict(
+            gzip=True,
+            static_path=os.path.join(os.path.dirname(__file__), 'static'))
 
     def test_gzip(self):
         response = self.fetch('/')
@@ -1361,6 +1363,17 @@ class GzipTestCase(SimpleHandlerTestCase):
             'gzip')
         self.assertEqual(response.headers['Vary'], 'Accept-Encoding')
 
+    def test_gzip_static(self):
+        # The streaming responses in StaticFileHandler have subtle
+        # interactions with the gzip output so test this case separately.
+        response = self.fetch('/robots.txt')
+        self.assertEqual(
+            response.headers.get(
+                'Content-Encoding',
+                response.headers.get('X-Consumed-Content-Encoding')),
+            'gzip')
+        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')
+
     def test_gzip_not_requested(self):
         response = self.fetch('/', use_gzip=False)
         self.assertNotIn('Content-Encoding', response.headers)
index 25ac56ebe14aaa7beb1388876a6cc985b5aaf8a9..a66335150771ebf77e830348134e1d3685e04d42 100644 (file)
@@ -2548,7 +2548,6 @@ class GZipContentEncoding(OutputTransform):
             ctype = _unicode(headers.get("Content-Type", "")).split(";")[0]
             self._gzipping = self._compressible_type(ctype) and \
                 (not finishing or len(chunk) >= self.MIN_LENGTH) and \
-                (finishing or "Content-Length" not in headers) and \
                 ("Content-Encoding" not in headers)
         if self._gzipping:
             headers["Content-Encoding"] = "gzip"
@@ -2556,7 +2555,14 @@ class GZipContentEncoding(OutputTransform):
             self._gzip_file = gzip.GzipFile(mode="w", fileobj=self._gzip_value)
             chunk = self.transform_chunk(chunk, finishing)
             if "Content-Length" in headers:
-                headers["Content-Length"] = str(len(chunk))
+                # The original content length is no longer correct.
+                # If this is the last (and only) chunk, we can set the new
+                # content-length; otherwise we remove it and fall back to
+                # chunked encoding.
+                if finishing:
+                    headers["Content-Length"] = str(len(chunk))
+                else:
+                    del headers["Content-Length"]
         return status_code, headers, chunk
 
     def transform_chunk(self, chunk, finishing):