From: Ben Darnell Date: Sat, 23 Aug 2014 22:12:19 +0000 (-0400) Subject: Fix a regression in gzip output for StaticFileHandler. X-Git-Tag: v4.1.0b1~105 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e88847320f095d3d0f18e0a1d4f1462d61d34e6a;p=thirdparty%2Ftornado.git Fix a regression in gzip output for StaticFileHandler. 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. --- diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index 02e38033c..3e7176cef 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -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) diff --git a/tornado/web.py b/tornado/web.py index 4dfd2ec83..aa7c0134a 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -2552,7 +2552,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" @@ -2560,7 +2559,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):