Skip to content

Add ETag value normalization to HttpCacheMiddleware - #31

Merged
vjik merged 3 commits into
yiisoft:masterfrom
KalimeroMK:etag-value-normalizer
Aug 24, 2026
Merged

vjik merged 3 commits into
yiisoft:masterfrom
KalimeroMK:etag-value-normalizer

Conversation

@KalimeroMK

@KalimeroMK KalimeroMK commented Aug 20, 2026

Copy link
Copy Markdown
Contributor
Q A
Is bugfix?
New feature? ✔️
Breaks BC?

Fix #11

When a web server compression module (e.g. Apache mod_deflate or mod_brotli) modifies the ETag header value by appending a suffix (-gzip, -br), the client sends the modified value back in If-None-Match and it no longer matches the application generated ETag, so the cache never hits.

Following the direction from #11 (comment) (normalize raw values after retrieving them from the request), this PR adds:

  • ETagValueNormalizerInterface — normalizes raw ETag values obtained from the If-None-Match request header before comparison.
  • NullETagValueNormalizer — default, returns values unmodified.
  • SuffixETagValueNormalizer — removes the first matching suffix from a given list (e.g. ['-gzip', '-br']).
  • New optional HttpCacheMiddleware constructor parameter $eTagValueNormalizer (defaults to NullETagValueNormalizer, no BC break).

Note: the W/ weak prefix (the Nginx case) was already handled by the existing value extraction; this PR covers the suffix case.

Introduce ETagValueNormalizerInterface to normalize raw ETag values from
the If-None-Match request header before comparison. This fixes cache
validation when a web server compression module (e.g. Apache mod_deflate
or mod_brotli) appends a suffix such as -gzip or -br to the ETag value.

Includes NullETagValueNormalizer (default, no changes) and
SuffixETagValueNormalizer (removes the first matching suffix).

Fixes yiisoft#11
@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (2d05f7a) to head (d0d3275).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff             @@
##              master       #31   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
- Complexity       112       117    +5     
===========================================
  Files             23        25    +2     
  Lines            274       282    +8     
===========================================
+ Hits             274       282    +8     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Remove redundant early return for an empty If-None-Match header value:
  in_array() with an empty list already returns false (equivalent mutant
  reported by Infection).
- Add a test asserting the ETag value normalizer is not called for an
  empty If-None-Match header value.

MSI for the file is now 100%.
Comment thread src/HttpCache/ETagValueNormalizer/NullETagValueNormalizer.php Outdated
Comment thread src/HttpCache/ETagValueNormalizer/SuffixETagValueNormalizer.php Outdated
@vjik
vjik requested review from a team and a lite review from Copilot August 23, 2026 11:39
@vjik vjik added the status:code review The pull request needs review. label Aug 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds opt-in normalization of If-None-Match ETag values in HttpCacheMiddleware to handle server-added compression suffixes (e.g. -gzip, -br) so cache validation can still hit.

Changes:

  • Introduces ETagValueNormalizerInterface with NullETagValueNormalizer (default no-op) and SuffixETagValueNormalizer (removes first matching suffix).
  • Extends HttpCacheMiddleware with a new optional $eTagValueNormalizer constructor dependency and applies it when extracting request ETags.
  • Adds unit tests for the new normalizers and middleware behavior, plus documentation and changelog updates.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/HttpCache/HttpCacheMiddlewareTest.php Adds coverage ensuring suffix-normalized If-None-Match matches generated ETags and that empty headers skip normalization.
tests/HttpCache/ETagValueNormalizer/SuffixETagValueNormalizerTest.php Validates suffix stripping behavior, including first-match-only semantics and empty-suffix handling.
tests/HttpCache/ETagValueNormalizer/NullETagValueNormalizerTest.php Confirms the default normalizer is a pass-through.
src/HttpCache/HttpCacheMiddleware.php Wires in the new normalizer and applies it when extracting If-None-Match values.
src/HttpCache/ETagValueNormalizer/SuffixETagValueNormalizer.php Implements configurable suffix removal for raw ETag values.
src/HttpCache/ETagValueNormalizer/NullETagValueNormalizer.php Implements the default no-op normalizer.
src/HttpCache/ETagValueNormalizer/ETagValueNormalizerInterface.php Defines the normalization contract for request ETag values.
docs/guide/en/http-cache-middleware.md Documents the new $eTagValueNormalizer option and provides an example configuration.
CHANGELOG.md Records the new feature under the upcoming release.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@vjik
vjik merged commit ecb80f0 into yiisoft:master Aug 24, 2026
26 checks passed
KalimeroMK pushed a commit to KalimeroMK/KalimeroMK that referenced this pull request Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:code review The pull request needs review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Etag Header Compliance with RFC

5 participants