Skip to content

feat(cache)!: sort query parameters in HTTP cache keys by default - #409

Merged
allen0099 merged 1 commit into
masterfrom
feat/72-sort-query-default
Sep 30, 2026
Merged

allen0099 merged 1 commit into
masterfrom
feat/72-sort-query-default

Conversation

@allen0099

Copy link
Copy Markdown
Owner

Closes #72. Last of the 0.4.0 cache key changes (#405–#408).

What changes

  • sort_query now defaults to sorting in @cache, invalidate(), build_cache_key() and CacheKey.from_request(), so ?b=2&a=1 and ?a=1&b=2 share one entry.
  • sort_query=False is the opt-out, for handlers whose response depends on the query order as sent. Pass the same value to invalidate().
  • @cache and invalidate() take sort_query: bool | None = None; None means "not passed".
  • Any explicit sort_query together with a custom key_builder raises CacheXError, False included.
    • build_cache_key() inside the builder sorts by default, so key_builder=b, sort_query=False would silently not do what it says.
    • 0.3.9 accepted False there, where it had no effect, and did not warn. The error is raised when the decorator is applied, not at request time. MIGRATING_0_4.md covers this.

Docs

  • HTTP_CACHING, CACHE_FLOW and MIGRATING_0_4 are updated in English and zh-TW.
  • The HTTP_CACHING example now shows when to use sort_query=False.
  • Changelog fragment: changelog.d/72.changed.md.

Tests

  • Existing tests are updated to the sorted default; the MagicMock-based default_key_builder tests now use a real Request.
  • New cases:
    • default and explicit True both merge reordered queries;
    • False keeps reordered queries apart;
    • both bools are rejected with a key_builder, in @cache and in invalidate();
    • invalidate() and sort_query=False round-trip;
    • a custom builder without the flag.
  • Checked that the tests catch each of these mutations:
    • reverting either default;
    • letting False through with a key_builder;
    • routing False to the default builder.

sort_query now defaults to sorting in @cache, invalidate(),
build_cache_key() and CacheKey.from_request(), so ?b=2&a=1 and ?a=1&b=2
share one entry. The sort is stable: repeated values of one name keep
the order sent. sort_query=False keeps the query as sent.

@cache and invalidate() take sort_query=None to mean "not passed". Any
explicit value together with a custom key_builder raises CacheXError,
False included: build_cache_key() in the builder sorts by default, so
the flag would silently not do what it says.

BREAKING CHANGE: query parameters are sorted in HTTP cache keys by
default. A handler that depends on the query order as sent must set
@cache(sort_query=False) and pass the same to invalidate().
sort_query passed with a custom key_builder is rejected, False included.

Closes #72
@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 60162f3 into master Sep 30, 2026
18 checks passed
@allen0099
allen0099 deleted the feat/72-sort-query-default branch September 30, 2026 01:07
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 keys do not normalize query parameter order

1 participant