If the server responds with a redirect (e.g. 307), and the redirected
location does not contain the cache busting search param set in the
original request, the response is likely invalid — when following the
redirect, the browser will have forwarded the request headers, but
without a corresponding cache busting search param. (See
https://github.com/vercel/next.js/pull/79563 for more context.)
Ideally, we would be able to intercept the redirect response and perform
it manually, instead of letting the browser automatically follow it, but
this is not allowed by the fetch API.
So instead, we must "replay" the redirect by fetching the new location
again, but this time we'll append the cache busting search param to
prevent a mismatch.
We can optimize Next.js's built-in middleware APIs by returning a custom
status code, to prevent the browser from automatically following it.
This will land in future PRs. Third-party proxies can choose to
implement this same protocol for cases where they need to redirect
Next.js requests but are not using Next.js APIs.
However, we'll still need this fallback behavior for third-party proxies
that don't implement our optimized redirect protocol.
This does not affect Server Action-based redirects; those are encoded
differently, as part of the Flight body.
As of now, this is gated behind the experimental
`validateRSCRequestHeaders` flag. We will test it before turning it on
by default.
Not all CDNs respect the Vary header when caching. We must assume that
only the URL is used to vary the responses. The Next client computes a
hash of the header values and sends it as a search param.
Before responding to a request, we must verify that the hash matches the
expected value. Neglecting to do this properly can lead to cache
poisoning attacks on certain CDNs.
In this initial PR, the verification I've added only runs during per-
segment prefetch requests, since those are the only ones that both vary
on a custom header and are also cacheable. But for safety, we should run
this verification for all requests, once we confirm the behavior is
correct. Will need to update our test suite, since there are a handful
of unit tests that send fetch requests with custom headers but without a
corresponding cache-busting search param.
It would be even better if we stopped using custom request headers, and
instead fully encoded everything into the search param. At least for
cacheable requests.