Skip to content

[6.x] Add request-scoped HTTP cache control - #20545

Open
timkelty wants to merge 1 commit into
6.xfrom
cache-control-foundations
Open

timkelty wants to merge 1 commit into
6.xfrom
cache-control-foundations

Conversation

@timkelty

@timkelty timkelty commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Description

Give cache integrations a common source of cache directives, dependency tags, and explanations, rather than making each integration infer intent from response headers.

Core API

  • The CacheControl service and facade collect request-scoped browser/shared directives using Symfony's cache-control vocabulary, with optional reasons and caller attribution.
  • The ApplyCacheControl middleware applies those directives on Craft site requests, preserves restrictions, and caps supplied freshness by dependency expiry. Core supplies no default lifetime.
  • The CacheControlApplied event gives synchronous consumers the actual response, a detached Symfony Response policy snapshot, raw tags, and reasons at the middleware checkpoint. Outer middleware and later listeners can still change the response.

Existing API changes

  • Replaces ResponseHeaders::setCache() and noCache(); add() remains.
  • Migrated calls stop generating redundant Expires and Pragma headers.

Collect cache directives, dependency tags, and reasons for synchronous cache integration consumers at the Craft middleware checkpoint. Preserve privacy and storage restrictions while migrating legacy cache header callers.

Amp-Thread-ID: https://ampcode.com/threads/T-43f45309-465e-4cd2-a911-0978bfe4f41d
Co-authored-by: Amp <amp@ampcode.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-10T04:31:08.402893Z b439591 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown

📚 Storybook previews

@craftcms/ui — open Storybook

No changed components detected in this Storybook.

resources/js — open Storybook

No changed components detected in this Storybook.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are reported for the request-scoped HTTP cache policy API.

No open issues 🎉

What changed in this PR

Adds a request-scoped HTTP cache policy API so Craft cache integrations can consume shared directives, dependency tags, and explanations instead of inferring intent from headers.

Changes:

  • Introduces CacheControl, middleware that applies policy and caps freshness by dependency expiry, and a checkpoint event with a detached policy snapshot.
  • Migrates template expiry, CSRF, and pending-transform handling from ResponseHeaders, preserving storage restrictions without supplying a default lifetime.
  • Adds coverage for middleware ordering, privacy, request isolation, dependency expiry, and integration behavior.
File Description
tests/​Unit/​View/​BladeDirectives/​ResponseDirectiveTest.php Tests migrated Blade expiry and last-duration-wins behavior.
tests/​Unit/​Twig/​Tags/​ExpiresTagTest.php Tests migrated Twig expiry and directive precedence.
tests/​Unit/​Support/​HtmlTest.php Checks CSRF protection through the new middleware.
tests/​Feature/​Image/​ImageTransformerTest.php Tests storage prohibition for pending transforms.
tests/​Feature/​Http/​Middleware/​SetHeadersTest.php Updates JSON-response coverage to use the new API.
tests/​Feature/​Http/​Middleware/​ApplyCacheControlTest.php Covers policy application, privacy, expiry, isolation, and event consumers.
tests/​.pest/​snapshots/​Unit/​Twig/​Nodes/​ExpiresNodeTest/​it_compiles_with_static_duration.snap Updates static expiry compilation output.
tests/​.pest/​snapshots/​Unit/​Twig/​Nodes/​ExpiresNodeTest/​it_compiles_with_dynamic_expiration.snap Updates dynamic expiry compilation output.
src/​Twig/​Nodes/​ExpiresNode.php Compiles expiry tags to CacheControl::setDuration().
src/​Support/​Html.php Records CSRF-related storage restrictions.
src/​Support/​Facades/​ResponseHeaders.php Removes obsolete cache-method annotations.
src/​Support/​Facades/​CacheControl.php Exposes the request-scoped cache policy facade.
src/​Route/​RouteServiceProvider.php Registers middleware and its execution priority.
src/​Image/​ImageTransformer.php Records pending-transform storage restrictions.
src/​Http/​ResponseHeaders.php Removes cache state and methods; retains arbitrary headers.
src/​Http/​Middleware/​SetHeaders.php Removes application of accumulated cache settings.
src/​Http/​Middleware/​ApplyCacheControl.php Applies policy, collects dependencies, and dispatches the checkpoint event.
src/​Http/​Events/​CacheControlApplied.php Defines the integration event and snapshot contract.
src/​Http/​CacheControl.php Collects directives, reasons, and caller attribution.
src/​Blade/​Directives/​ResponseDirective.php Migrates Blade expiry to the new service.
composer.lock Updates the manifest content hash.
composer.json Registers the CacheControl facade alias.
CHANGELOG.md Documents the new API and removed methods.
CHANGELOG-WIP.md Documents HTTP policy and template-expiry changes.

Review effort: Balanced

This branch has not been deployed

No deployments
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.

2 participants