Skip to content

[6.x] Run custom API middleware before the response cache - #15385

Open
duncanmcclean wants to merge 5 commits into
6.xfrom
api-middleware-order
Open

[6.x] Run custom API middleware before the response cache#15385
duncanmcclean wants to merge 5 commits into
6.xfrom
api-middleware-order

Conversation

@duncanmcclean

@duncanmcclean duncanmcclean commented Sep 7, 2026

Copy link
Copy Markdown
Member

This pull request fixes an issue where custom middleware configured via statamic.api.middleware (or statamic.graphql.middleware) couldn't be used to authenticate requests, because a cached response would be returned before the custom middleware ran. Once an authenticated request had populated the cache, unauthenticated requests to the same endpoint received the cached response.

This was happening because the configured middleware group was nested inside the Cache middleware in the REST API route group, and the GraphQL schema appended custom middleware after CacheResponse.

This PR fixes it by running the configured middleware after HandleAuthentication but before the cache middleware in both the REST API and GraphQL. The $middlewarePriority workaround from the issue continues to work.

Behaviour changes

  • Custom middleware now runs on cache hits too. The default api group includes ThrottleRequests, so cached responses now count towards the rate limit.
  • Middleware which modifies the response now runs fresh on every request, rather than having its changes baked into the cached copy.
  • GraphQL middleware which counts or logs requests will now see every request, not just uncached ones. This applies to middleware added via GraphQL::addMiddleware() as well as statamic.graphql.middleware.
  • Since Cache is now the innermost middleware, cache hits also run SubstituteBindings from the api group, so route bindings (collections, taxonomies, asset containers, globals, forms, sites) are resolved against the Stache before the cached response is returned.

I don't think any of these are unreasonable, since the config file describes statamic.api.middleware as a place to "configure a middleware-based authentication layer", which wasn't possible before. But feel free to close if you consider this breaking.


Fixes #10010

the `statamic.api.middleware` group and graphql schema middleware now run before `HandleAuthentication` and the cache middleware, so cached responses can no longer bypass custom authentication.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015MAdoF7RTBQ4mUTaki7k2e
@duncanmcclean

Copy link
Copy Markdown
Member Author

Test failures are unrelated. Fixed in #15387

@jasonvarga jasonvarga left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice catch on the underlying bug — a cached response being served before a middleware-based auth layer runs is a genuine hole, and the direction here is right. Two things to sort before this goes in.

Separately, worth calling out in the release notes: because Cache is now the innermost middleware, cache hits also run SubstituteBindings, so every cached REST request now resolves its route bindings (Collection::findByHandle, taxonomies, asset containers, globals, forms, sites — see RouteServiceProvider) against the Stache before the cached response is returned. That isn't in the behaviour-change list in the description, and it does eat into the point of the response cache.

Comment thread routes/routes.php Outdated
Comment thread src/GraphQL/DefaultSchema.php Outdated
Comment thread tests/Feature/GraphQL/CustomMiddlewareTest.php Outdated
duncanmcclean and others added 3 commits September 8, 2026 08:42
only the custom middleware needs to run before `Cache`. moving `HandleAuthentication` inside the configured group meant `HandleToken` ran before the `auth_token` check.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01624MAUMx1KeFxpnqwivkiA
only `CacheResponse` needs to move behind the custom middleware.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01624MAUMx1KeFxpnqwivkiA
…areTest`

the config test was pointed at the `GraphQL::addMiddleware()` environment, leaving `addCustomMiddlewareThroughConfig` unused.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01624MAUMx1KeFxpnqwivkiA
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.

statamic.api.middleware does not allow performing custom authentication

2 participants