Skip to content

Commit

Permalink
Fix a regression in gzip output for StaticFileHandler.
Browse files Browse the repository at this point in the history
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 tornadoweb#1156.
  • Loading branch information
bdarnell committed Aug 24, 2014
1 parent ed7bd3a commit d968973
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
15 changes: 14 additions & 1 deletion tornado/test/web_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1348,7 +1348,9 @@ def get(self):
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('/')
Expand All @@ -1361,6 +1363,17 @@ def test_gzip(self):
'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)
Expand Down
10 changes: 8 additions & 2 deletions tornado/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -2548,15 +2548,21 @@ def transform_first_chunk(self, status_code, headers, chunk, finishing):
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"
self._gzip_value = BytesIO()
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):
Expand Down

0 comments on commit d968973

Please sign in to comment.