Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Change precedence of weaken_etag_on_compress
Updated the compressor filter to clarify the precedence of the `weaken_etag_on_compress` option when both it and `disable_on_etag_header` are enabled. Compression will now be applied, and the ETag will be weakened, allowing for better cache management. Documentation and tests have been updated to reflect this behavior.

Signed-off-by: Rafael Antunes <rafael.gaspar@me.com>
  • Loading branch information
rafaelgaspar committed Mar 10, 2026
commit 2a3d0337c4fd6d1ba14130c03a453f78dff92b4e
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ message Compressor {
// When this field is ``true``, disables compression when the response contains an ``ETag`` header.
// When this field is ``false``, the filter will preserve weak ``ETag`` values and remove those that
// require strong validation (unless ``weaken_etag_on_compress`` is set).
// When both ``disable_on_etag_header`` and ``weaken_etag_on_compress`` are ``true``,
// ``weaken_etag_on_compress`` takes precedence (compression is applied and the ETag is weakened).
bool disable_on_etag_header = 2;

// When this field is ``true``, removes ``Accept-Encoding`` from the request headers before dispatching
Expand Down Expand Up @@ -101,8 +103,9 @@ message Compressor {
// ``ETag``, the filter will weaken the ETag by prepending ``W/`` to its value instead of
// removing it. This allows caching and conditional requests to work while indicating the
// response body was modified by compression. When ``false`` (default), strong ETags are
// removed when compression is applied. This option has no effect when ``disable_on_etag_header``
// is ``true`` (compression is skipped for responses with ETag).
// removed when compression is applied. When both ``weaken_etag_on_compress`` and
// ``disable_on_etag_header`` are ``true``, this field takes precedence so that compression
// is applied and the ETag is weakened, supporting gradual rollout to clients and servers.
bool weaken_etag_on_compress = 6;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move next to the disable_on_etag_header field.

}

Expand Down
3 changes: 2 additions & 1 deletion changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ new_features:
to the :ref:`compressor filter <config_http_filters_compressor>`. When enabled in
``response_direction_config``, strong ``ETag`` response headers are weakened (``W/`` prefix)
instead of removed when compression is applied, allowing caches and conditional requests to
work while indicating the body was modified by compression.
work while indicating the body was modified by compression. When both ``weaken_etag_on_compress``
and ``disable_on_etag_header`` are true, the new field takes precedence.
- area: golang
change: |
Added ``DownstreamSslConnection()`` method to the Golang HTTP filter's ``StreamInfo`` interface,
Expand Down
11 changes: 8 additions & 3 deletions docs/root/configuration/http/http_filters/compressor_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,14 @@ ETag handling
When a response has an ``ETag`` header, the filter's behavior depends on
``response_direction_config``:

- **``disable_on_etag_header: true``** — Compression is *skipped* for responses that
contain an ``ETag``. The response is sent unchanged (including the original ``ETag``).
This avoids changing the entity tag when the body would be modified by compression.
- **When both ``disable_on_etag_header`` and ``weaken_etag_on_compress`` are ``true``** —
``weaken_etag_on_compress`` takes precedence. Compression is applied and the strong
``ETag`` is weakened.

- **``disable_on_etag_header: true``** (and ``weaken_etag_on_compress`` is ``false``) —
Compression is *skipped* for responses that contain an ``ETag``. The response is sent
unchanged (including the original ``ETag``). This avoids changing the entity tag when
the body would be modified by compression.

- **``disable_on_etag_header: false``** (default) — Compression is allowed. When compression
is applied:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -731,8 +731,13 @@ bool CompressorFilter::checkIsEtagAllowedLogResponseStats(Http::ResponseHeaderMa
}

bool CompressorFilter::isEtagAllowed(Http::ResponseHeaderMap& headers) const {
return !(config_->responseDirectionConfig().disableOnEtagHeader() &&
headers.getInline(etag_handle.handle()));
const auto& config = config_->responseDirectionConfig();
// When both disable_on_etag_header and weaken_etag_on_compress are true, the new field
// takes precedence so compression is applied and the ETag is weakened.
if (config.weakenEtagOnCompress()) {
return true;
}
return !(config.disableOnEtagHeader() && headers.getInline(etag_handle.handle()));
}

bool CompressorFilterConfig::ResponseDirectionConfig::areAllResponseCodesCompressible() const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,35 @@ TEST_F(CompressorFilterTest, WeakenEtagOnCompressWithStatusHeaderEnabled) {
EXPECT_TRUE(headers.has("x-envoy-compression-status"));
}

// When both disable_on_etag_header and weaken_etag_on_compress are true, the new field
// takes precedence: compression is applied and the ETag is weakened.
TEST_F(CompressorFilterTest, WeakenEtagOnCompressTakesPrecedenceOverDisableOnEtag) {
setUpFilter(R"EOF(
{
"response_direction_config": {
"disable_on_etag_header": true,
"weaken_etag_on_compress": true
},
"compressor_library": {
"name": "test",
"typed_config": {
"@type": "type.googleapis.com/envoy.extensions.compression.gzip.compressor.v3.Gzip"
}
}
}
)EOF");
response_stats_prefix_ = "response.";

doRequestNoCompression({{":method", "get"}, {"accept-encoding", "test, deflate"}});
Http::TestResponseHeaderMapImpl headers{
{":method", "get"}, {"content-length", "256"}, {"etag", "\"strong-etag\""}};
doResponseCompression(headers, false);
EXPECT_EQ(0, stats_.counter("test.compressor.test.test.response.not_compressed_etag").value());
EXPECT_EQ("test", headers.get_("content-encoding"));
EXPECT_TRUE(headers.has("etag"));
EXPECT_EQ(R"(W/"strong-etag")", headers.get_("etag"));
}

class HasCacheControlNoTransformTest
: public CompressorFilterTest,
public testing::WithParamInterface<std::tuple<std::string, bool>> {};
Expand Down