Skip to content

Commit

Permalink
Use Content-Encoding to identify if data is binary
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
2 people authored and Jonathan Demirgian committed Jun 2, 2021
1 parent 5bfa5dd commit d0cbd16
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
24 changes: 24 additions & 0 deletions tests/test_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,30 @@ def test_wsgi_script_binary_support_base64_behavior(self):
self.assertTrue(response["isBase64Encoded"])
self.assertTrue(is_base64(response["body"]))

content_encoded_json = {
**text_plain_event,
**{"path": "/content_encoding_header_json1"},
}

response = lh.handler(content_encoded_json, None)

self.assertEqual(response["statusCode"], 200)
self.assertIn("isBase64Encoded", response)
self.assertTrue(response["isBase64Encoded"])
self.assertTrue(is_base64(response["body"]))

content_encoded_text_arbitrary = {
**text_plain_event,
**{"path": "/content_encoding_header_textarbitrary1"},
}

response = lh.handler(content_encoded_text_arbitrary, None)

self.assertEqual(response["statusCode"], 200)
self.assertIn("isBase64Encoded", response)
self.assertTrue(response["isBase64Encoded"])
self.assertTrue(is_base64(response["body"]))

def test_wsgi_script_on_cognito_event_request(self):
"""
Ensure that requests sent by cognito behave sensibly
Expand Down
18 changes: 18 additions & 0 deletions tests/test_wsgi_binary_support_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,21 @@ def json_mimetype_response_1():
@app.route("/arbitrarybinary_mimetype_response1", methods=["GET"])
def arbitrary_mimetype_response_1():
return Response(response=b"some binary data", mimetype="arbitrary/binary_mimetype")


@app.route("/content_encoding_header_json1", methods=["GET"])
def response_with_content_encoding_mimetype1():
return Response(
response=json.dumps({"some": "data"}),
mimetype="application/json",
headers={"Content-Encoding": "gzip"},
)


@app.route("/content_encoding_header_textarbitrary1", methods=["GET"])
def response_with_content_encoding_mimetype2():
return Response(
response="OK",
mimetype="text/arbitrary",
headers={"Content-Encoding": "shouldnt_matter"},
)
12 changes: 11 additions & 1 deletion zappa/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,17 @@ def handler(self, event, context):
)

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

0 comments on commit d0cbd16

Please sign in to comment.