Skip to content

Commit fe1edc0

Browse files
fix(event_handler): skip compression when the response has no body (#8485)
Co-authored-by: Leandro Damascena <lcdama@amazon.pt>
1 parent c8d9937 commit fe1edc0

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

‎aws_lambda_powertools/event_handler/api_gateway.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,11 @@ def _has_compression_enabled(
810810

811811
def _compress(self):
812812
"""Compress the response body, but only if `Accept-Encoding` headers includes gzip."""
813+
# A response without a body, such as 204 No Content or 304 Not Modified, has nothing to compress
814+
if self.response.body is None:
815+
logger.debug("Response has no body; skipping compression")
816+
return
817+
813818
self.response.headers["Content-Encoding"] = "gzip"
814819
if isinstance(self.response.body, str):
815820
logger.debug("Converting string response to bytes before compressing it")

‎tests/functional/event_handler/required_dependencies/test_api_gateway.py‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,72 @@ def return_text() -> Response:
606606
assert result["body"] == expected_value
607607

608608

609+
@pytest.mark.parametrize("status_code", [204, 304])
610+
def test_compress_route_with_body_less_response(status_code: int):
611+
# GIVEN a function with compress=True returning a Response without a body
612+
# AND an event with an "Accept-Encoding" that includes gzip
613+
app = ApiGatewayResolver()
614+
mock_event = {"path": "/my/path", "httpMethod": "GET", "headers": {"Accept-Encoding": "deflate, gzip"}}
615+
616+
@app.get("/my/path", compress=True)
617+
def no_content() -> Response:
618+
return Response(status_code=status_code)
619+
620+
# WHEN calling the event handler
621+
result = app(mock_event, None)
622+
623+
# THEN don't perform any gzip compression
624+
assert result["statusCode"] == status_code
625+
assert result["body"] is None
626+
assert result["isBase64Encoded"] is False
627+
assert "Content-Encoding" not in result["multiValueHeaders"]
628+
629+
630+
def test_compress_response_with_body_less_response():
631+
# GIVEN a function returning a Response with compress=True and no body
632+
# AND an event with an "Accept-Encoding" that includes gzip
633+
app = ApiGatewayResolver()
634+
mock_event = {"path": "/my/path", "httpMethod": "GET", "headers": {"Accept-Encoding": "deflate, gzip"}}
635+
636+
@app.get("/my/path")
637+
def no_content() -> Response:
638+
return Response(status_code=204, compress=True)
639+
640+
# WHEN calling the event handler
641+
result = app(mock_event, None)
642+
643+
# THEN don't perform any gzip compression
644+
assert result["statusCode"] == 204
645+
assert result["body"] is None
646+
assert result["isBase64Encoded"] is False
647+
assert "Content-Encoding" not in result["multiValueHeaders"]
648+
649+
650+
def test_compress_exception_handler_with_body_less_response():
651+
# GIVEN a function with compress=True whose exception handler returns a Response without a body
652+
# AND an event with an "Accept-Encoding" that includes gzip
653+
app = ApiGatewayResolver()
654+
mock_event = {"path": "/my/path", "httpMethod": "GET", "headers": {"Accept-Encoding": "deflate, gzip"}}
655+
656+
@app.exception_handler(ValueError)
657+
def handle_value_error(ex: ValueError):
658+
return Response(status_code=410)
659+
660+
@app.get("/my/path", compress=True)
661+
def raise_value_error() -> Response:
662+
raise ValueError("Foo!")
663+
664+
# WHEN calling the event handler
665+
# AND a ValueError is raised
666+
result = app(mock_event, None)
667+
668+
# THEN call the exception_handler and don't perform any gzip compression
669+
assert result["statusCode"] == 410
670+
assert result["body"] is None
671+
assert result["isBase64Encoded"] is False
672+
assert "Content-Encoding" not in result["multiValueHeaders"]
673+
674+
609675
def test_cache_control_200():
610676
# GIVEN a function with cache_control set
611677
app = ApiGatewayResolver()

0 commit comments

Comments
 (0)