Skip to content

feat(proxy-cache): honor Vary header for memory strategy#13376

Draft
shreemaan-abhishek wants to merge 2 commits into
apache:masterfrom
shreemaan-abhishek:feat/proxy-cache-vary
Draft

feat(proxy-cache): honor Vary header for memory strategy#13376
shreemaan-abhishek wants to merge 2 commits into
apache:masterfrom
shreemaan-abhishek:feat/proxy-cache-vary

Conversation

@shreemaan-abhishek
Copy link
Copy Markdown
Contributor

Description

The memory cache strategy previously ignored the upstream Vary response header, so requests that differed only in a Vary'd header (e.g. Accept-Encoding) collided on the same cache entry. The disk strategy already inherits Vary handling from NGINX's native proxy_cache; this PR brings the memory strategy in line.

What changes:

  • Parse the upstream Vary header into a canonical sorted list of lowercased header names.
  • Store an index entry at <base_key>::__vary describing the Vary headers and known variants for that base key.
  • Store each variant at <base_key>::<md5(request values)>.
  • On lookup, read the index, compute the request's signature, and resolve to the matching variant. With no index present, fall back to the base key (no Vary recorded).
  • Vary: * is treated as not reusable per RFC 9111 §4.1 and is not cached.
  • PURGE walks every variant under a base key.
  • CACHE_VERSION is bumped from 1 to 2 so any pre-Vary entries get purged on read via the existing version-mismatch path.

The disk handler is intentionally unchanged.

Which issue(s) this PR fixes:

Fixes #

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

Notes

  • Integration tests under t/plugin/proxy-cache/memory.t were added (TEST 41–44) but I have not run the suite locally on this branch.
  • The disk cache strategy is unaffected; NGINX's native proxy_cache already handles Vary.

Implement RFC 9111 §4.1 secondary cache key handling for the in-memory
cache. Cache entries are now partitioned by the request's values for
each header listed in the upstream Vary response, so a response cached
under one set of Vary header values is not returned to a request with
different values. Responses carrying `Vary: *` are treated as not
reusable and are not cached.

Storage layout:
- `<base_key>::__vary` holds the variant index `{vary, variants, version}`.
- `<base_key>::<md5(values)>` holds each variant body+headers.

PURGE walks every variant under a base key. CACHE_VERSION is bumped to
2 so any in-flight v1 entries are purged on read via the existing
version-mismatch path. The disk strategy is unchanged: NGINX's native
`proxy_cache` already honors Vary.
- Bound the per-base-key `variants` list to MAX_VARIANTS (64) with FIFO
  eviction. Without this, a Vary on a high-cardinality header would grow
  the index until it exceeds the shdict slot capacity and writes start
  failing with "no memory".
- Make the `Vary: *` test deterministic: call `ngx.update_time()` in the
  fixture and sleep briefly between requests so the body comparison
  cannot tie on a single nginx time tick.
- Trim two over-detailed comments in the handler.
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.

1 participant