diff --git a/packages/next/src/server/lib/incremental-cache/index.ts b/packages/next/src/server/lib/incremental-cache/index.ts index 85036a9382bd9..7441c00387f7d 100644 --- a/packages/next/src/server/lib/incremental-cache/index.ts +++ b/packages/next/src/server/lib/incremental-cache/index.ts @@ -383,7 +383,7 @@ export class IncrementalCache implements IncrementalCacheType { const headers = typeof (init.headers || {}).keys === 'function' ? Object.fromEntries(init.headers as Headers) - : Object.assign(init.headers || {}, {}) + : Object.assign({}, init.headers) if ('traceparent' in headers) delete headers['traceparent'] diff --git a/test/e2e/app-dir/app-static/app-static.test.ts b/test/e2e/app-dir/app-static/app-static.test.ts index a8864452aba38..2c8c19dad7e88 100644 --- a/test/e2e/app-dir/app-static/app-static.test.ts +++ b/test/e2e/app-dir/app-static/app-static.test.ts @@ -40,6 +40,22 @@ createNextDescribe( } }) + it('should still cache even though the `traceparent` header was different', async () => { + const res = await next.fetch('/strip-header-traceparent') + expect(res.status).toBe(200) + + const html = await res.text() + const $ = cheerio.load(html) + + const data1 = $('#data1').text() + const data2 = $('#data2').text() + expect(data1).toBeTruthy() + expect(data1).toBe(data2) + + const echoedHeaders = JSON.parse($('#echoedHeaders').text()) + expect(echoedHeaders.headers.traceparent).toEqual('C') + }) + it('should warn for too many cache tags', async () => { const res = await next.fetch('/too-many-cache-tags') expect(res.status).toBe(200) @@ -790,6 +806,10 @@ createNextDescribe( "static-to-dynamic-error-forced/[id]/page_client-reference-manifest.js", "static-to-dynamic-error/[id]/page.js", "static-to-dynamic-error/[id]/page_client-reference-manifest.js", + "strip-header-traceparent.html", + "strip-header-traceparent.rsc", + "strip-header-traceparent/page.js", + "strip-header-traceparent/page_client-reference-manifest.js", "too-many-cache-tags/page.js", "too-many-cache-tags/page_client-reference-manifest.js", "unstable-cache/dynamic-undefined/page.js", @@ -1512,6 +1532,22 @@ createNextDescribe( "initialRevalidateSeconds": false, "srcRoute": "/ssg-draft-mode/[[...route]]", }, + "/strip-header-traceparent": { + "dataRoute": "/strip-header-traceparent.rsc", + "experimentalBypassFor": [ + { + "key": "Next-Action", + "type": "header", + }, + { + "key": "content-type", + "type": "header", + "value": "multipart/form-data;.*", + }, + ], + "initialRevalidateSeconds": 50, + "srcRoute": "/strip-header-traceparent", + }, "/variable-config-revalidate/revalidate-3": { "dataRoute": "/variable-config-revalidate/revalidate-3.rsc", "experimentalBypassFor": [ diff --git a/test/e2e/app-dir/app-static/app/strip-header-traceparent/page.tsx b/test/e2e/app-dir/app-static/app/strip-header-traceparent/page.tsx new file mode 100644 index 0000000000000..7c67f7b08c67b --- /dev/null +++ b/test/e2e/app-dir/app-static/app/strip-header-traceparent/page.tsx @@ -0,0 +1,33 @@ +export default async function Page() { + const data1 = await fetch( + 'https://next-data-api-endpoint.vercel.app/api/random', + { + headers: { traceparent: 'A' }, + next: { revalidate: 50 }, + } + ).then((res) => res.text()) + + const data2 = await fetch( + 'https://next-data-api-endpoint.vercel.app/api/random', + { + headers: { traceparent: 'B' }, + next: { revalidate: 50 }, + } + ).then((res) => res.text()) + + const echoedHeaders = await fetch( + 'https://next-data-api-endpoint.vercel.app/api/echo-headers', + { + headers: { traceparent: 'C' }, + next: { revalidate: 50 }, + } + ).then((res) => res.text()) + + return ( + <> +

{data1}

+

{data2}

+

{echoedHeaders}

+ + ) +}