diff --git a/.changeset/clear-spies-wear.md b/.changeset/clear-spies-wear.md new file mode 100644 index 000000000000..fb6449618f8e --- /dev/null +++ b/.changeset/clear-spies-wear.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +allow multiple server-timing headers diff --git a/packages/kit/src/runtime/server/respond.js b/packages/kit/src/runtime/server/respond.js index 9067418bc450..7a7e2f8d641c 100644 --- a/packages/kit/src/runtime/server/respond.js +++ b/packages/kit/src/runtime/server/respond.js @@ -183,7 +183,11 @@ export async function internal_respond(request, options, manifest, state) { 'Use `event.cookies.set(name, value, options)` instead of `event.setHeaders` to set cookies' ); } else if (lower in headers) { - throw new Error(`"${key}" header is already set`); + if (lower === 'server-timing') { + headers[lower] += ', ' + value; + } else { + throw new Error(`"${key}" header is already set`); + } } else { headers[lower] = value; diff --git a/packages/kit/test/apps/basics/src/routes/headers/server-timing/+layout.server.js b/packages/kit/test/apps/basics/src/routes/headers/server-timing/+layout.server.js new file mode 100644 index 000000000000..e321b9002d48 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/headers/server-timing/+layout.server.js @@ -0,0 +1,6 @@ +/** @type {import('./$types').LayoutServerLoad} */ +export function load({ setHeaders }) { + setHeaders({ + 'server-timing': 'db;dur=53' + }); +} diff --git a/packages/kit/test/apps/basics/src/routes/headers/server-timing/+layout.svelte b/packages/kit/test/apps/basics/src/routes/headers/server-timing/+layout.svelte new file mode 100644 index 000000000000..4fa864ce7aa9 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/headers/server-timing/+layout.svelte @@ -0,0 +1 @@ + diff --git a/packages/kit/test/apps/basics/src/routes/headers/server-timing/sub/+page.server.js b/packages/kit/test/apps/basics/src/routes/headers/server-timing/sub/+page.server.js new file mode 100644 index 000000000000..8bdc52d30137 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/headers/server-timing/sub/+page.server.js @@ -0,0 +1,6 @@ +/** @type {import('./$types').PageServerLoad} */ +export function load({ setHeaders }) { + setHeaders({ + 'server-timing': 'external-api;dur=250' + }); +} diff --git a/packages/kit/test/apps/basics/src/routes/headers/server-timing/sub/+page.svelte b/packages/kit/test/apps/basics/src/routes/headers/server-timing/sub/+page.svelte new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/kit/test/apps/basics/test/server.test.js b/packages/kit/test/apps/basics/test/server.test.js index 61a8c9256320..033f8d161946 100644 --- a/packages/kit/test/apps/basics/test/server.test.js +++ b/packages/kit/test/apps/basics/test/server.test.js @@ -785,6 +785,12 @@ test.describe('setHeaders', () => { expect(cookies).toMatch('cookie1=value1'); expect(cookies).toMatch('cookie2=value2'); }); + test('allows multiple server-timing headers with different values', async ({ page }) => { + const response = await page.goto('/headers/server-timing/sub'); + const serverTiming = response ? (await response.allHeaders())['server-timing'] : ''; + + expect(serverTiming).toMatch('db;dur=53, external-api;dur=250'); + }); }); test.describe('cookies', () => {