Skip to content

cache: only store GET responses and bypass non-cacheable methods - #4375

Open
Ramya-9353 wants to merge 1 commit into
zalando:masterfrom
Ramya-9353:cache-method-aware-store
Open

Ramya-9353 wants to merge 1 commit into
zalando:masterfrom
Ramya-9353:cache-method-aware-store

Conversation

@Ramya-9353

Copy link
Copy Markdown
Contributor

Repro: on a route with cache("5m", "15s", "30s"), send OPTIONS /index.html against a cold key and then GET /index.html: the GET is served as a HIT with Content-Length: 0, the backend's Allow header and no body. Likewise a HEAD /page while the GET entry is inside its stale-while-revalidate window makes the background revalidation store a body-less 200 carrying the original Content-Length, after which every GET for that URL fails with unexpected EOF until the TTL expires. Both were reproduced through proxytest against an httptest backend on master.

Cause: the cache key omits the request method and none of the store paths (Response(), coalesce(), doRevalidate()) check which method fetched the response, so body-less OPTIONS and HEAD representations are persisted under the GET key and OPTIONS requests are answered from the cached GET entry, which also breaks CORS preflights on cached routes.

Fix: bypass the cache in Request() for methods that are neither GET/HEAD nor unsafe, forward HEAD misses instead of coalescing them, and let storeDecision() persist only responses fetched with GET, which also covers revalidation (RFC 9111 §3, §4). Regression tests cover the cold HEAD, the OPTIONS/TRACE/PROPFIND bypass and the store gate; the filter docs now state the method behaviour. The guards do not overlap with the open cache PRs #4369 to #4372, none of which touch method handling.

The cache key does not include the request method and the store paths
did not check which method produced the response. A cold OPTIONS request
stored the backend's body-less reply under the GET key, and a HEAD request
during the stale-while-revalidate window made the background revalidation
store a body-less 200 with the original Content-Length, so later GETs for
the same URL were served an empty body until the TTL expired. OPTIONS
requests were also answered from the cached GET representation.

Per RFC 9111 §3 and §4 only GET and HEAD are cacheable. Bypass the cache
for methods that are neither cacheable nor unsafe, forward HEAD misses
instead of coalescing them, and persist only responses fetched with GET.

Signed-off-by: Ramya Eliger <ramya@digiscrypt.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant