Repository navigation
Conversation
Mechanical changes required by raising the SDK constraint to `>=3.13.5` (next commit, for `brotli_neo`): - `dart format`: the formatter style follows the language version. - `dart fix --code=prefer_initializing_formals`: private named parameters (`this._credential`). The public parameter names are unchanged, so no call site changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- `brotli_neo` (pure Dart) for Brotli, next to GZip, negotiated with the
request's `Accept-Encoding` (q-values, `q=0`, `*`):
- JSON payloads (`AutoCompressSink`), other API responses
(`compressResponse`) and static files (`createCompressionMiddleware`).
- Static files cache: identity, `gzip` and `br` variants (transcoding
`gzip` to `br` when preferred).
- Falls back to the next accepted encoding if the Brotli encoder fails.
- Fix: JSON payloads of 512+ bytes were GZip-compressed even without
`Accept-Encoding: gzip`.
- `Accept-Encoding` parsed (was a substring match).
- `Vary: Accept-Encoding` on compressible responses.
- `APIServerConfig.compressionEncodings` and `brotliQuality`
(args, `server.*` config, JSON).
- `Content-Encoding: br` request payloads (`decompressPayload`), with
`maxPayloadLength` enforced while decoding.
- Dart SDK `>=3.13.5`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #192 +/- ##
==========================================
- Coverage 95.55% 95.54% -0.02%
==========================================
Files 73 74 +1
Lines 25179 25530 +351
==========================================
+ Hits 24061 24393 +332
- Misses 1118 1137 +19
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- `APIBrotli.decode`: retry at `maxOutputSize` (the decoder stopped at the last buffer doubling below the limit, rejecting valid payloads). - ERROR path and `apiResponse2` branch: JSON not compressed in `resolveBody` (its headers were lost: a compressed body without `Content-Encoding`); compressed later by `compressResponse`. - `canCompressResponse`: no `1xx`/`204`/`206`/`304` or `Content-Range`. - Static files: high quality only for cacheable responses (`APIServerResponseCache.isCacheable`, `resolveCompression`). - Cache: failed conversions not retried; compressed `404` keeps its `Content-Encoding` and checks `Accept-Encoding`; `Accept-Encoding` parsed once per request. - `x-gzip` taken as `gzip`. - `resolveCompressionEncodings`: unknown encodings ignored (logged), defaults if none is known (was: compression silently disabled). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
Review fixes (2a85474)A code review found 10 issues. All of them are fixed, each with a regression test:
Local runs: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Brotli (
br) response compression next to GZip, usingbrotli_neo^0.2.0(pure Dart: no native library, no FFI). It also fixes howAccept-Encodingis handled.Accept-Encodingis now parsed properly: q-values,q=0and*. Each response uses the best encoding fromAPIServerConfig.compressionEncodings(default[br, gzip]). On a tie, the server's order wins.AutoCompressSink, which generalizesAutoGZipSink.AutoGZipSinkis kept and works as before.compressResponse).createCompressionMiddleware).gzipandbrvariants per file. Agzipfile is converted tobrwhen the client prefers it.Vary: Accept-Encodingis sent with responses that can be compressed.Content-Encoding: brpayloads are decompressed (decompressPayload), andmaxPayloadLengthis enforced while decoding.server.*config entry and a JSON field:compressionEncodings: an empty list disables compression.brotliQuality:0..11, default5. Cached static files use at least9.Fix: JSON was gzipped without
Accept-Encoding_jsonEncodePayloadgzipped every JSON payload of 512 bytes or more, whatever the client sent inAccept-Encoding. It now compresses only with an encoding the client accepts.APIServer.resolveBody/resolveBodySynccalled without the newcompressionparameter keep the old behavior (always GZip), for direct callers.Breaking: Dart SDK
>=3.13.5brotli_neorequires it. Raising the SDK constraint changes the language version, so this PR also has to:prefer_initializing_formals(private named parameters). Public parameter names are unchanged, so no call site changes;languageVersiongoes from3.10.0to3.13.0).Those are in separate commits, so the feature commit (
v1.28.0: Brotli ...) can be reviewed on its own.Benchmark (JIT, entity-list JSON,
brotli_neovsdart:iogzip level 4)All the outputs were also decoded with the reference
brotliCLI.Tests
test/bones_api_utils_compression_test.dartcoversAccept-Encodingparsing and negotiation, Brotli round trips at every quality,maxOutputSize, corrupted input,compressResponse, the middleware, and interop with thebrotliCLI (skipped when the CLI isn't installed).AutoCompressSink/BrotliSink(sink tests),brcache variants, config args/JSON/apiConfig,brrequest payloads.brJSON/text/static, no compression withoutAccept-Encoding(regression),q=0, a gzip-only server.dart format,dart analyze --fatal-infos,dependency_validatorand the VM unit suite (-x docker -x concurrency) all pass, and so doesensure_build. The Docker DB suites will run in CI.🤖 Generated with Claude Code