Skip to content

feat: add zstd content-encoding decompression support#6837

Closed
StilesCrisis wants to merge 2 commits into
cloudflare:mainfrom
StilesCrisis:fix/zstd-decode
Closed

feat: add zstd content-encoding decompression support#6837
StilesCrisis wants to merge 2 commits into
cloudflare:mainfrom
StilesCrisis:fix/zstd-decode

Conversation

@StilesCrisis

Copy link
Copy Markdown

Summary

Before this PR, responses with Content-Encoding: zstd were passed through as raw compressed bytes — workerd had no zstd decompression support. Workers calling .text(), .json(), etc. on such responses received garbled data.

  • Add ZstdAsyncInputStream streaming decompressor in system-streams.c++ and readable-source.c++, modeled after the existing gzip/brotli implementations
  • Wire "zstd" into getContentEncoding() so the encoding is recognised and the body is auto-decoded
  • Add zstd @3 to the StreamEncoding capnp enum
  • Add KJ_FAIL_REQUIRE for the unsupported zstd output-compression path in EncodedAsyncOutputStream

Follow-up hardening (compat flag, DevTools inspector, empty-body edge case, RPC robustness) is in a separate PR stacked on top of this one.

Test plan

  • system-streams-test: ZstdAsyncInputStream decompresses correctly
  • readable-source-test: Zstd encoded stream, (pumpTo), (pumpTo same encoding), (pumpTo different encoding)
  • writable-sink-test: Zstd-encoding sink, Zstd-encoding sink (identity)
  • server-test: Server: encodeResponseBody: zstd response body is decompressed

🤖 Generated with Claude Code

johnstiles-google and others added 2 commits June 21, 2026 14:39
…ncoding header

When a fetch() subrequest returns Content-Encoding: zstd, workerd now:
1. Decompresses the body transparently via a new ZstdAsyncInputStream class
2. Strips the Content-Encoding header from the Response so downstream code
   (e.g. Cache API) doesn't re-interpret the already-decoded body as zstd

This mirrors the existing gzip and brotli auto-decode behavior. Adds ZSTD to
the StreamEncoding capnp enum, implements ZstdAsyncInputStream using the zstd
streaming API in both system-streams.c++ and readable-source.c++, and adds
KJ_FAIL_REQUIRE for the unsupported zstd output compression path.

Fixes: cloudflare#5112

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds 4 readable-source tests and 2 writable-sink tests mirroring the
existing gzip test suite:
- Zstd encoded stream (readAllBytes)
- Zstd encoded stream (pumpTo)
- Zstd encoded stream (pumpTo same encoding passthrough)
- Zstd encoded stream (pumpTo different encoding → gzip)
- Zstd-encoding sink (throws for unsupported output compression)
- Zstd-encoding sink (identity passthrough via disownEncodingResponsibility)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@StilesCrisis StilesCrisis requested review from a team as code owners June 21, 2026 19:24
@github-actions

Copy link
Copy Markdown


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants