Skip to content

feat(cache)!: normalise the host in HTTP cache keys - #407

Merged
allen0099 merged 1 commit into
masterfrom
feat/265-host-normalization
Sep 29, 2026
Merged

allen0099 merged 1 commit into
masterfrom
feat/265-host-normalization

Conversation

@allen0099

Copy link
Copy Markdown
Owner

Third of the 0.4.0 cache-key changes, after #405 and #406.

What changes

The host component of an HTTP cache key is normalised, so every spelling of one origin shares an entry:

  • lower-cased (RFC 9110 §4.2.3);
  • an empty port or the scheme's default one dropped (:80 on http/ws, :443 on https/wss; RFC 3986 §6.2.3). The scheme is read from the ASGI scope, which is also what request.url uses; request.url.scheme itself comes back empty for some malformed hosts;
  • IPv6 literals keep their brackets ([fe80::1]:8000);
  • a trailing dot is not stripped, a missing Host still gives unknown, and a malformed host (unbracketed IPv6, :80, host:80:80) is kept as sent.

@cache, build_cache_key(), invalidate() and the monitoring routes all go through CacheKey.from_request, so they agree. clear_path() wildcards the host.

Docs

  • HTTP_CACHING.md and CACHE_FLOW.md (English and zh-TW) describe the rules, including that behind a TLS-terminating proxy the scheme is http unless the proxy's headers are applied.
  • MIGRATING_0_4.md states the rule precisely and notes that clear_pattern() patterns naming an upper-case host or a default port need rewriting.
  • changelog.d/265.changed.md.

Tests

tests/test_host_normalization.py:

  • 23 host/scheme cases;
  • an end-to-end check that EXAMPLE.com, example.com:80 and example.com hit one entry;
  • invalidate() finding the entry under another spelling.

Closes #265

Hostnames are case-insensitive, and an empty port or the scheme's default
one names the same origin as no port. The host component is now
lower-cased and such a port dropped (`:80` on http/ws, `:443` on
https/wss, read from the ASGI scope's scheme), so `Example.com`,
`example.com:80` and `example.com` share one entry. IPv6 literals keep
their brackets; malformed hosts are kept as sent.

BREAKING CHANGE: keys for hosts written with upper case or a default port
change, so those entries are cached afresh once, and `clear_pattern()`
patterns naming such a host no longer match.

Closes #265
@allen0099 allen0099 added this to the 0.4.0 milestone Sep 29, 2026
@allen0099 allen0099 added enhancement New feature or request http-cache The @cache decorator, cache keys and Cache-Control handling breaking-change Changes public behaviour or API; needs a minor/major release labels Sep 29, 2026
@allen0099
allen0099 merged commit 6c7103f into master Sep 29, 2026
14 checks passed
@allen0099
allen0099 deleted the feat/265-host-normalization branch September 29, 2026 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Changes public behaviour or API; needs a minor/major release enhancement New feature or request http-cache The @cache decorator, cache keys and Cache-Control handling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cache key: normalise the host (case, default port)

1 participant