Skip to content

Conversation

jlopex
Copy link
Contributor

@jlopex jlopex commented Oct 5, 2025

Flask-Compress always mutates the ETag when it's present and compresses a response. That’s reasonable, but it can lead to surprising behavior (see #65): conditional requests (If-None-Match, ranges) are evaluated against a different representation than the one actually sent, because compression and ETag mutation happen after the app or other middleware ran make_conditional.

This PR add one new default behavioir and an opt-in behavior to make things predictable while preserving backwards compatibility.

What’s new

Preserve weak ETags across encodings

The response already has a weak ETag (W/"..."), Flask-Compress will not append :{algorithm}.

Why: per RFC 7232, weak ETags are semantic validators and can be reused across transfer encodings. With Vary: Accept-Encoding in place, caches and clients behave correctly without per-encoding tag mutations.

Evaluate conditionals on the final, compressed representation

Config: COMPRESS_EVALUATE_CONDITIONAL_REQUEST (default: False)

When True, the extension calls response.make_conditional(request) after it sets the compressed body, Content-Encoding, Content-Length, and (if applicable) the ETag.

Why: this ensures 304 Not Modified and 206 Partial Content are computed against the bytes actually sent on the wire. It fixes the “mutated-after-the-fact” mismatch described in #65 without forcing apps to add their own “finisher” hook.

Both switches are off by default (or “legacy behaviour” by default), so existing apps won’t break.

Notes

Vary: Accept-Encoding is still enforced.

We use response.get_etag() / response.set_etag() (Werkzeug) instead of string slicing, so weak/strong handling is correct and future-proof.

make_conditional() is gated to safe methods and runs only after the final body and headers are set.

Tests

Added unit tests showing:

  • Weak ETag and conditional GET returns 304 after this change.
  • With COMPRESS_EVALUATE_CONDITIONAL_REQUEST=True, conditional GETs are evaluated on the compressed representation (304 with empty body, no Content-Encoding on 304, ETag echoed).

@jlopex jlopex force-pushed the javi/rewrite_etags_manipulation branch from 4b08f0e to 243191c Compare October 5, 2025 17:01
@jlopex
Copy link
Contributor Author

jlopex commented Oct 5, 2025

@alexprengere here is a PR to try to help with conditional requests and compression with flask-compress. I did include some small tests to validate basic behaviour work as expected, I would appreciate any feedback on this.

I hope this little contribution can help a few guys that were raising issues at least in two approaches while not breaking the default behaviour of the package.

@jlopex jlopex force-pushed the javi/rewrite_etags_manipulation branch 4 times, most recently from ae6d185 to 7616d6f Compare October 6, 2025 08:39
@alexprengere
Copy link
Collaborator

Thanks a lot! I will take some time to review all this, I will also ask the original authors of the etag-related issues their opinion on this.

@jlopex
Copy link
Contributor Author

jlopex commented Oct 8, 2025

Thanks a lot! I will take some time to review all this, I will also ask the original authors of the etag-related issues their opinion on this.

I tried my best trying to make it retro-compatible and being the less intrusive possible but maybe there are possible improvements on top of it! Looking forward for the feedback!

README.md Outdated
| `COMPRESS_REGISTER` | Specifies if compression should be automatically registered. | `True` |
| `COMPRESS_ALGORITHM` | Supported compression algorithms. | `['zstd', 'br', 'gzip', 'deflate']` |
| `COMPRESS_STREAMS` | Compress content streams. | `True` |
| `COMPRESS_MUTATE_WEAK_ETAGS` | Compress mutates weak etags. | `True` |
Copy link
Collaborator

Choose a reason for hiding this comment

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

This can be removed 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch @alexprengere I did remove the reference at the README.md, thanks for your review! Looking forward to start testing this in real world!

@jlopex jlopex force-pushed the javi/rewrite_etags_manipulation branch from 0b834bc to c1f9ae5 Compare October 17, 2025 19:34
@jlopex jlopex force-pushed the javi/rewrite_etags_manipulation branch from c1f9ae5 to 51e56b8 Compare October 17, 2025 19:38
@alexprengere alexprengere merged commit cca52ae into colour-science:master Oct 18, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants