Skip to content

feat(cache)!: store a query over 200 bytes as its SHA-256 digest - #408

Merged
allen0099 merged 1 commit into
masterfrom
feat/269-hash-long-query
Sep 29, 2026
Merged

allen0099 merged 1 commit into
masterfrom
feat/269-hash-long-query

Conversation

@allen0099

Copy link
Copy Markdown
Owner

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

What changes

  • A query component longer than 200 bytes, as encoded in the key, is stored as sha256: plus the full 64-digit hex digest (_QUERY_HASH_THRESHOLD, not configurable), so a client cannot make the query part of a key arbitrarily long.
  • The digest is taken after sorting, so sort_query=True still merges reordered long queries.
  • A query as sent never looks like a digest: str(QueryParams) / urlencode write : as %3A.
  • The path stays readable. clear_path() finds such entries with include_params=True, and the monitoring routes show the digest as query_params (no new field).
  • Long paths are left alone.

@cache, build_cache_key() and invalidate() all go through CacheKey.from_request, so they agree.

Docs

  • HTTP_CACHING.md and CACHE_FLOW.md (English and zh-TW) describe the rule. They note that Memcached still hashes a whole key over 250 bytes, which a query just under the threshold with a long host or path can reach.
  • MIGRATING_0_4.md states the exact threshold.
  • changelog.d/269.changed.md.

Tests

tests/test_query_hash.py covers:

  • the 200/201-byte boundary, and that the digest is taken over the encoded query;
  • hashing after sorting, and that a query cannot pose as a digest;
  • extra components after the digest;
  • end-to-end hits and monitoring output;
  • clear_path with and without include_params;
  • invalidate(), including a reordered long query with sort_query=True.

Closes #269

The query component of an HTTP cache key was the full query string, so
a client could make keys arbitrarily long. A query longer than 200 bytes
as encoded in the key is now stored as `sha256:` and its full hex
digest, taken after sorting so `sort_query` still merges reordered long
queries. The path stays readable, so `clear_path()` still finds the
entry, and the monitoring routes show the digest as `query_params`. A
query as sent never starts with `sha256:`, since `:` is encoded as `%3A`.

BREAKING CHANGE: keys for requests with a query over 200 bytes change,
so those entries are cached afresh once.

Closes #269
@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 e5d57e3 into master Sep 29, 2026
15 checks passed
@allen0099
allen0099 deleted the feat/269-hash-long-query branch September 29, 2026 17:06
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: hash long query strings to bound key length

1 participant