Skip to content

Commit 9c6da05

Browse files
authored
Fix double compression issue when enable_compression() is called on pre-encoded responses (aio-libs#10974)
1 parent ff7feaf commit 9c6da05

3 files changed

Lines changed: 33 additions & 0 deletions

File tree

CHANGES/10968.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed double compression issue when :py:meth:`~aiohttp.web.StreamResponse.enable_compression` is called on a response with pre-existing Content-Encoding header -- by :user:`bdraco`.

aiohttp/web_response.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ def enable_compression(
186186
strategy: Optional[int] = None,
187187
) -> None:
188188
"""Enables response compression encoding."""
189+
# Don't enable compression if content is already encoded.
190+
# This prevents double compression and provides a safe, predictable behavior
191+
# without breaking existing code that may call enable_compression() on
192+
# responses that already have Content-Encoding set (e.g., FileResponse
193+
# serving pre-compressed files).
194+
if hdrs.CONTENT_ENCODING in self._headers:
195+
return
189196
self._compression = True
190197
self._compression_force = force
191198
self._compression_strategy = strategy

tests/test_web_response.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,31 @@ async def write_headers(status_line: str, headers: CIMultiDict[str]) -> None:
627627
assert resp.content_length == 6
628628

629629

630+
async def test_enable_compression_with_existing_encoding() -> None:
631+
"""Test that enable_compression does not override existing content encoding."""
632+
writer = mock.Mock()
633+
634+
async def write_headers(status_line: str, headers: CIMultiDict[str]) -> None:
635+
# Should preserve the existing content encoding
636+
assert headers[hdrs.CONTENT_ENCODING] == "gzip"
637+
# Should not have double encoding
638+
assert headers.get(hdrs.CONTENT_ENCODING) != "gzip, deflate"
639+
640+
writer.write_headers.side_effect = write_headers
641+
req = make_request("GET", "/", writer=writer)
642+
resp = web.Response(body=b"answer")
643+
644+
# Manually set content encoding (simulating FileResponse with pre-compressed file)
645+
resp.headers[hdrs.CONTENT_ENCODING] = "gzip"
646+
647+
# Try to enable compression - should be ignored
648+
resp.enable_compression(web.ContentCoding.deflate)
649+
650+
await resp.prepare(req)
651+
# Verify compression was not enabled due to existing encoding
652+
assert not resp.compression
653+
654+
630655
@pytest.mark.usefixtures("parametrize_zlib_backend")
631656
async def test_rm_content_length_if_compression_http11() -> None:
632657
writer = mock.Mock()

0 commit comments

Comments
 (0)