Skip to content

Commit 9e99ee7

Browse files
Quidgemonkut
andcommitted
Use Content-Encoding to identify if data is binary
When using _whitenoise_ for caching, which provides compression, binary types may include mimetypes, "text/", "application/json": - response.mimetype.startswith("text/") - response.mimetype == "application/json" Assuming that Content-Encoding will be set (as whitenoise apparently does) this allows compression to be applied by the application for "text/" and "application/json". About Content-Encoding: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding --- The above commit message and functional code change to zappa/handler.py was written by GH user @monkut and a PR was provided with Miserlou/Zappa#2170. That PR was not merged in before the fork from Miserlou/zappa to Zappa/zappa. This commit copies the code from that PR, adds a comment line referencing the new migrated issue, and additionally adds tests to confirm behavior. Co-authored-by: monkut <shane.cousins@gmail.com>
1 parent 366cc3c commit 9e99ee7

3 files changed

Lines changed: 43 additions & 1 deletion

File tree

tests/test_handler.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,24 @@ def test_wsgi_script_binary_support_base64_behavior(self):
297297
self.assertTrue(response['isBase64Encoded'])
298298
self.assertTrue(is_base64(response['body']))
299299

300+
content_encoded_json = {**text_plain_event, **{'path': '/content_encoding_header_json1'}}
301+
302+
response = lh.handler(content_encoded_json, None)
303+
304+
self.assertEqual(response['statusCode'], 200)
305+
self.assertIn('isBase64Encoded', response)
306+
self.assertTrue(response['isBase64Encoded'])
307+
self.assertTrue(is_base64(response['body']))
308+
309+
content_encoded_text_arbitrary = {**text_plain_event, **{'path': '/content_encoding_header_textarbitrary1'}}
310+
311+
response = lh.handler(content_encoded_text_arbitrary, None)
312+
313+
self.assertEqual(response['statusCode'], 200)
314+
self.assertIn('isBase64Encoded', response)
315+
self.assertTrue(response['isBase64Encoded'])
316+
self.assertTrue(is_base64(response['body']))
317+
300318
def test_wsgi_script_on_cognito_event_request(self):
301319
"""
302320
Ensure that requests sent by cognito behave sensibly

tests/test_wsgi_binary_support_app.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,21 @@ def json_mimetype_response_1():
2828
@app.route('/arbitrarybinary_mimetype_response1', methods=['GET'])
2929
def arbitrary_mimetype_response_1():
3030
return Response(response=b"some binary data", mimetype="arbitrary/binary_mimetype")
31+
32+
33+
@app.route('/content_encoding_header_json1', methods=['GET'])
34+
def response_with_content_encoding_mimetype1():
35+
return Response(
36+
response=json.dumps({'some': 'data'}),
37+
mimetype="application/json",
38+
headers={'Content-Encoding': 'gzip'}
39+
)
40+
41+
42+
@app.route('/content_encoding_header_textarbitrary1', methods=['GET'])
43+
def response_with_content_encoding_mimetype2():
44+
return Response(
45+
response="OK",
46+
mimetype="text/arbitrary",
47+
headers={'Content-Encoding': 'shouldnt_matter'}
48+
)

zappa/handler.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,13 @@ def handler(self, event, context):
551551
zappa_returndict.setdefault('statusDescription', response.status)
552552

553553
if response.data:
554-
if settings.BINARY_SUPPORT and \
554+
if settings.BINARY_SUPPORT and response.headers.get("Content-Encoding"):
555+
# We could have a text response that's gzip
556+
# encoded. Therefore, we base-64 encode it.
557+
# Related: https://github.com/zappa/Zappa/issues/908
558+
zappa_returndict['body'] = base64.b64encode(response.data).decode('utf-8')
559+
zappa_returndict["isBase64Encoded"] = True
560+
elif settings.BINARY_SUPPORT and \
555561
not response.mimetype.startswith("text/") \
556562
and response.mimetype != "application/json":
557563
zappa_returndict['body'] = base64.b64encode(response.data).decode('utf-8')

0 commit comments

Comments
 (0)