-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Describe the bug
When a server responds with zstd encoded response in multiple frames, current implementation fails decompressing the second frame here. Internally the exception is Already at the end of a Zstandard frame but it ends up raising a ClientPayloadError.
Python docs mention this issue here and suggest to use compression.zstd.decompress to avoid this limitation. I've tested internally with this change and works fine, but I'm not sure if this should be the way to go or you prefer another solution.
I have seen a similar issue into an unrelated project like kafka-python just in case helps understanding it better.
PS: Unfortunately, I won’t be able to open an MR in the next two weeks, so feel free to fix it yourself if you’d like.
To Reproduce
import asyncio
import aiohttp
from compression.zstd import ZstdCompressor
BODY = b"A" * 50_000 + b"B" * 50_000
def zstd_frame(data: bytes) -> bytes:
c = ZstdCompressor()
return c.compress(data) + c.flush()
async def main() -> None:
frame1 = zstd_frame(BODY[:50_000])
frame2 = zstd_frame(BODY[50_000:])
async def handle(reader, writer):
while (await reader.readline()) != b"\r\n":
pass
writer.write(
b"HTTP/1.1 200 OK\r\n"
b"Content-Type: text/plain\r\n"
b"Content-Encoding: zstd\r\n"
b"Transfer-Encoding: chunked\r\n\r\n"
)
for frame in (frame1, frame2):
writer.write(f"{len(frame):x}\r\n".encode() + frame + b"\r\n")
await writer.drain()
await asyncio.sleep(0.05)
writer.write(b"0\r\n\r\n")
await writer.drain()
writer.close()
server = await asyncio.start_server(handle, "127.0.0.1", 0)
port = server.sockets[0].getsockname()[1]
try:
async with aiohttp.ClientSession() as session:
async with session.get(f"http://127.0.0.1:{port}/") as resp:
body = await resp.read()
assert body == BODY
print("OK")
except aiohttp.ClientPayloadError as e:
print(f"FAILED: {type(e).__name__}: {e}")
finally:
server.close()
await server.wait_closed()
if __name__ == "__main__":
asyncio.run(main())Expected behavior
No failures on multiframed zstd responses
Logs/tracebacks
FAILED: ClientPayloadError: 400, message:
Can not decode content-encoding: zstdPython Version
3.14aiohttp Version
3.13.3multidict Version
6.7.1propcache Version
0.4.1yarl Version
1.23.0OS
macOS
Related component
Client
Additional context
No response
Code of Conduct
- I agree to follow the aio-libs Code of Conduct