Skip to content

@cache: normaliser for vary= headers to bound the number of entries #310

Description

@allen0099

Problem

@cache(vary=[...]) (#268, PR #309) keys the cache on each listed request header's raw value, lower-cased name and trimmed value only. Header values come from the client, so every distinct value becomes its own entry: Accept-Language: en-US,en;q=0.9 and Accept-Language: en are two entries even when the route only supports en and zh-TW. Reducing a header to the values the route actually serves currently needs a custom key_builder that calls build_cache_key (#264) and leaves out vary= for that header. The docs show this in "Varying on request headers".

Proposal

Let vary also accept a mapping from header name to a normaliser:

def locale(value: str) -> str:
    return "zh-TW" if value.lower().startswith("zh") else "en"

@cache(ttl=60, vary={"Accept-Language": locale})
  • The normaliser receives the trimmed value (empty when missing) and returns the string that goes into the key. It could also return an int, as build_cache_key accepts.
  • The list form keeps working and keeps its keys. A header mapped to None behaves like the list form.
  • The Vary response header is unchanged: a downstream cache still sees the raw header.
  • invalidate(vary=...) must apply the same normaliser so it deletes the right entry.
  • An allow-list ({"Accept": ["application/json", "text/html"]}, with anything else mapping to a default) could be sugar on top. Decide whether it is worth a second form.

Additive. Routes without a mapping keep their keys.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthttp-cacheThe @cache decorator, cache keys and Cache-Control handling

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions