Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python Flask ETag responses: preserve cache validators across conditional reads

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

An ETag is a response validator that lets a client ask whether a selected representation has changed.

Download Python source kit

Operation contract

The owned Flask endpoint returns a fixed receipt summary, marks it private with a short cache lifetime, sets an ETag for those exact representation bytes and applies the request’s conditional headers. A normal local test-client GET returns the payload and validator. A second GET sends the same If-None-Match and receives 304 with no body. A mismatched validator receives 200 and the representation. All three requests remain inside the local test client.

Failure and ownership boundary

A validator is not permission to read a resource. A real endpoint must perform authentication and tenant/resource checks before deciding which representation is selected, even when it might return 304. This fixture has no identity service or persistent record changes. A production validator must change when the represented bytes change and must account for representation variants. Django REST Framework list visibility: filter the principal’s rows before paging, Flask error responses: preserve status without exposing internal exception text and Flask JSON API: reject unknown fields, booleans and oversized bodies remain necessary.

Tested environment

Dependency check: this program was executed on CPython 3.14.6 with Flask==3.1.3. Install these versions in a separate virtual environment. The download includes the recorded environment snapshot; no third-party package is part of the website runtime.

Working program

python
from flask import Flask, Response, request

application = Flask(__name__)

@application.get("/receipts/41")
def receipt_summary():
    response = Response(b"receipt=41;amount=125\n", mimetype="text/plain")
    response.cache_control.private = True
    response.cache_control.max_age = 30
    response.add_etag()
    return response.make_conditional(request)

with application.test_client() as client:
    initial = client.get("/receipts/41")
    validator = initial.headers["ETag"]
    unchanged = client.get("/receipts/41", headers={"If-None-Match": validator})
    changed = client.get("/receipts/41", headers={"If-None-Match": '"different"'})
    print("statuses:", initial.status_code, unchanged.status_code, changed.status_code)
    print("304 body:", unchanged.data)
    print("validator retained:", unchanged.headers["ETag"] == validator)
    print("cache policy:", initial.headers["Cache-Control"])

Output

Output
statuses: 200 304 200
304 body: b''
validator retained: True
cache policy: private, max-age=30

Costs and limits

Computing the validator reads the representation bytes. Avoid reconstructing an expensive report merely to discover it is unchanged when a correctly maintained version can identify the same representation. This tiny response does not measure proxy behavior, compression variants, bandwidth savings or production cache hit rate.

Common Mistakes

  • Run access checks before returning an unchanged-resource status.
  • Do not reuse a validator when the selected representation bytes change.

Connected lessons

Flask JSON API: reject unknown fields, booleans and oversized bodies, Django REST Framework list visibility: filter the principal’s rows before paging, Flask error responses: preserve status without exposing internal exception text.

Trace the next boundary

Python Flask If-Match: reject a stale in-memory revision before mutation.

python
flask-conditional-response
Storage details