Skip to content

Commit

Permalink
Bypass GZipMiddleware when response includes Content-Encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Oct 13, 2022
1 parent 5eae07a commit 616a23e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
8 changes: 8 additions & 0 deletions asgi_gzip/__init__.py
Expand Up @@ -30,6 +30,7 @@ def __init__(self, app, minimum_size: int, compresslevel: int = 9) -> None:
self.send = unattached_send
self.initial_message = {}
self.started = False
self.content_encoding_set = False
self.gzip_buffer = io.BytesIO()
self.gzip_file = gzip.GzipFile(
mode="wb", fileobj=self.gzip_buffer, compresslevel=compresslevel
Expand All @@ -45,6 +46,13 @@ async def send_with_gzip(self, message) -> None:
# Don't send the initial message until we've determined how to
# modify the outgoing headers correctly.
self.initial_message = message
headers = Headers(raw=self.initial_message["headers"])
self.content_encoding_set = "content-encoding" in headers
elif message_type == "http.response.body" and self.content_encoding_set:
if not self.started:
self.started = True
await self.send(self.initial_message)
await self.send(message)
elif message_type == "http.response.body" and not self.started:
self.started = True
body = message.get("body", b"")
Expand Down
24 changes: 24 additions & 0 deletions tests/test_asgi_gzip.py
Expand Up @@ -76,3 +76,27 @@ async def generator(bytes, count):
assert response.text == "x" * 4000
assert response.headers["Content-Encoding"] == "gzip"
assert "Content-Length" not in response.headers


def test_gzip_ignored_for_responses_with_encoding_set(test_client_factory):
def homepage(request):
async def generator(bytes, count):
for index in range(count):
yield bytes

streaming = generator(bytes=b"x" * 400, count=10)
return StreamingResponse(
streaming, status_code=200, headers={"Content-Encoding": "br"}
)

app = Starlette(
routes=[Route("/", endpoint=homepage)],
middleware=[Middleware(GZipMiddleware)],
)

client = test_client_factory(app)
response = client.get("/", headers={"accept-encoding": "gzip, br"})
assert response.status_code == 200
assert response.text == "x" * 4000
assert response.headers["Content-Encoding"] == "br"
assert "Content-Length" not in response.headers

0 comments on commit 616a23e

Please sign in to comment.