Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid setting Content-Encoding header for static view responses. #2810

Merged
merged 2 commits into from
Nov 16, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ Bug Fixes
from previous orders have executed.
See https://github.com/Pylons/pyramid/pull/2757

- Fix static view to avoid setting the ``Content-Encoding`` response header
to an encoding guessed using Python's ``mimetypes`` module.
This was causing clients to decode the content of gzipped files
when downloading them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can add a link to the PR here similar to other changes please.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmerickel yep, done

Deprecations
------------

Expand Down
25 changes: 15 additions & 10 deletions pyramid/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,7 @@ class FileResponse(Response):
def __init__(self, path, request=None, cache_max_age=None,
content_type=None, content_encoding=None):
if content_type is None:
content_type, content_encoding = mimetypes.guess_type(
path,
strict=False
)
if content_type is None:
content_type = 'application/octet-stream'
# str-ifying content_type is a workaround for a bug in Python 2.7.7
# on Windows where mimetypes.guess_type returns unicode for the
# content_type.
content_type = str(content_type)
content_type, content_encoding = _guess_type(path)
super(FileResponse, self).__init__(
conditional_response=True,
content_type=content_type,
Expand Down Expand Up @@ -180,3 +171,17 @@ def _get_response_factory(registry):
)

return response_factory


def _guess_type(path):
content_type, content_encoding = mimetypes.guess_type(
path,
strict=False
)
if content_type is None:
content_type = 'application/octet-stream'
# str-ifying content_type is a workaround for a bug in Python 2.7.7
# on Windows where mimetypes.guess_type returns unicode for the
# content_type.
content_type = str(content_type)
return content_type, content_encoding
12 changes: 10 additions & 2 deletions pyramid/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
)

from pyramid.path import caller_package
from pyramid.response import FileResponse

from pyramid.response import (
_guess_type,
FileResponse,
)

from pyramid.traversal import traversal_path_info

slash = text_('/')
Expand Down Expand Up @@ -134,7 +139,10 @@ def __call__(self, context, request):
if not exists(filepath):
raise HTTPNotFound(request.url)

return FileResponse(filepath, request, self.cache_max_age)
content_type, content_encoding = _guess_type(filepath)
return FileResponse(
filepath, request, self.cache_max_age,
content_type, content_encoding=None)

def add_slash_redirect(self, request):
url = request.path_url + '/'
Expand Down
4 changes: 2 additions & 2 deletions pyramid/tests/test_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,14 @@ def test_not_found(self):
from pyramid.httpexceptions import HTTPNotFound
self.assertRaises(HTTPNotFound, inst, context, request)

def test_resource_with_content_encoding(self):
def test_gz_resource_no_content_encoding(self):
inst = self._makeOne('pyramid.tests:fixtures/static')
request = self._makeRequest({'PATH_INFO':'/arcs.svg.tgz'})
context = DummyContext()
response = inst(context, request)
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/x-tar')
self.assertEqual(response.content_encoding, 'gzip')
self.assertEqual(response.content_encoding, None)
response.app_iter.close()

def test_resource_no_content_encoding(self):
Expand Down