Summary
A content-type allowlist (#609) is not always enough to control compression: dynamic text/html (BREACH-exposed) and static text/html share the same MIME type, and JSON/XML APIs may be sensitive only on some endpoints. Compression should be controllable per route.
Proposal
Add per-action override action.<i>.compression.enabled (default true). Actions already define how a response is served (cf. action.<i>.customHeaders), and one action is reusable from N routes, so the action is the right granularity.
Sketch:
- parse + validate in
StandardEndpointMapper, new field on ActionConfiguration;
- propagate through
MapResult;
- in
ProxyRequestsManager, after mapping, call response.compression(false) when disabled.
Implementation notes
Always configure both compress(N) and compress(BiPredicate) on the server, in particular for response.compression.threshold=0!
With compress(0) alone, Reactor Netty on HTTP/1.1 appears to install the compression handler once per connection rather than evaluating per response; once removed via response.compression(false), it is never re-added for subsequent responses on the same keep-alive connection. HTTP/2 (H2/H2C) is immune since the pipeline is per-stream.
Setting a trivial compress((req, res) -> true) predicate should do the trick.
Summary
A content-type allowlist (#609) is not always enough to control compression: dynamic
text/html(BREACH-exposed) and statictext/htmlshare the same MIME type, and JSON/XML APIs may be sensitive only on some endpoints. Compression should be controllable per route.Proposal
Add per-action override
action.<i>.compression.enabled(defaulttrue). Actions already define how a response is served (cf.action.<i>.customHeaders), and one action is reusable from N routes, so the action is the right granularity.Sketch:
StandardEndpointMapper, new field onActionConfiguration;MapResult;ProxyRequestsManager, after mapping, callresponse.compression(false)when disabled.Implementation notes
Always configure both
compress(N)andcompress(BiPredicate)on the server, in particular forresponse.compression.threshold=0!With
compress(0)alone, Reactor Netty on HTTP/1.1 appears to install the compression handler once per connection rather than evaluating per response; once removed viaresponse.compression(false), it is never re-added for subsequent responses on the same keep-alive connection. HTTP/2 (H2/H2C) is immune since the pipeline is per-stream.Setting a trivial
compress((req, res) -> true)predicate should do the trick.