diff --git a/.changeset/large-ligers-decide.md b/.changeset/large-ligers-decide.md new file mode 100644 index 000000000..1beae0bf3 --- /dev/null +++ b/.changeset/large-ligers-decide.md @@ -0,0 +1,5 @@ +--- +"@opennextjs/aws": patch +--- + +fix: add vary header to cache interceptor diff --git a/packages/open-next/src/core/routing/cacheInterceptor.ts b/packages/open-next/src/core/routing/cacheInterceptor.ts index 0a33e3824..70dd083f8 100644 --- a/packages/open-next/src/core/routing/cacheInterceptor.ts +++ b/packages/open-next/src/core/routing/cacheInterceptor.ts @@ -13,6 +13,18 @@ import { generateMessageGroupId } from "./queue"; const CACHE_ONE_YEAR = 60 * 60 * 24 * 365; const CACHE_ONE_MONTH = 60 * 60 * 24 * 30; +/* + * We use this header to prevent Firefox (and possibly some CDNs) from incorrectly reusing the RSC responses during caching. + * This can especially happen when there's a redirect in the middleware as the `_rsc` query parameter is not visible there. + * So it will get dropped during the redirect, which results in the RSC response being cached instead of the actual HTML on the path `/`. + * This value can be found in the routes manifest, under `rsc.varyHeader`. + * They recompute it here in Next: + * https://github.com/vercel/next.js/blob/c5bf5bb4c8b01b1befbbfa7ad97a97476ee9d0d7/packages/next/src/server/base-server.ts#L2011 + * Also see this PR: https://github.com/vercel/next.js/pull/79426 + */ +const VARY_HEADER = + "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Next-Url"; + async function computeCacheControl( path: string, body: string, @@ -127,6 +139,7 @@ async function generateResult( ...cacheControl, "content-type": type, ...cachedValue.meta?.headers, + vary: VARY_HEADER, }, }; }