fix(static): don'\''t let zstd_static suppress the gzip fallback#76
Merged
Conversation
ngx_http_zstd_ok() latches r->gzip_tested=1 / r->gzip_ok=0 as a side effect (inherited from tokers/zstd-nginx-module). The static handler called it under `zstd_static on` BEFORE checking whether the .zst file exists. When the .zst was absent the handler declined — but gzip had already been latched "not ok" for the request, so a later gzip filter or gzip_static handler short-circuited on the cached decision and served identity instead of gzip. The client lost its gzip fallback purely because the zstd module was enabled. Split the shared helper: ngx_http_zstd_accepts() is a side-effect-free acceptance predicate for callers that only need the decision (the static module); ngx_http_zstd_ok() keeps the latching behaviour for the on-the-fly filter, which commits to Content-Encoding: zstd immediately after and must keep gzip off. ngx_http_zstd_ok() is now ngx_inline: the static TU includes the header but no longer calls it, and a plain `static` definition would trip -Werror=unused-function there; an inline definition is exempt. Tests (t/01-static.t): - TEST 26 — zstd_static on, request a plain file with NO sibling .zst through the always-present gzip *filter*; asserts Content-Encoding: gzip. Verified to fail on pre-fix code (gzip suppressed -> identity). - TEST 27 — coexistence with the gzip_static *module*. Documents that gzip_static (a built-in CONTENT_PHASE handler) runs before the dynamic zstd_static handler and so was never bitten by the latch; kept as a coexistence contract (passes on both pre-fix and fixed trees).
eilandert
force-pushed
the
fix/gzip-fallback-latch
branch
from
July 7, 2026 19:48
4e0b805 to
ec21a07
Compare
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.
MINOR from module audit.
Problem
ngx_http_zstd_ok()latchesr->gzip_tested=1/r->gzip_ok=0as a side effect. The static handler called it underzstd_static onbefore checking whether the.zstexists. When the.zstwas absent the handler declined — but gzip was already latched "not ok" for the request, so a later gzip filter / gzip_static handler short-circuited and served identity instead of gzip. The client lost its gzip fallback purely because the zstd module was enabled.Fix
Split the shared helper:
ngx_http_zstd_accepts()— side-effect-free acceptance predicate, used by the static module (decision only).ngx_http_zstd_ok()— keeps the latching behaviour for the on-the-fly filter, which commits toContent-Encoding: zstdimmediately after and must keep gzip off. Nowngx_inlineso the static TU (which includes the header but no longer calls it) does not trip-Werror=unused-function.Tests
t/01-static.tTEST 26 —zstd_static on, plain file with no sibling.zst, through the gzip filter; assertsContent-Encoding: gzip. Verified to fail on pre-fix code.gzip_staticmodule. Documents that gzip_static (a built-in CONTENT_PHASE handler) runs before the dynamic zstd_static handler and was never bitten by the latch; kept as a coexistence contract (passes pre-fix and post-fix).Local:
prove t/00 t/01= 1224/1224 PASS.