diff --git a/.changeset/curvy-experts-try.md b/.changeset/curvy-experts-try.md new file mode 100644 index 000000000000..5b43be733273 --- /dev/null +++ b/.changeset/curvy-experts-try.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +Make shadow endpoint `event.url` consistent between server and client navigation diff --git a/packages/kit/src/runtime/client/renderer.js b/packages/kit/src/runtime/client/renderer.js index c85fa5e23dd8..f31d2bc7ef6b 100644 --- a/packages/kit/src/runtime/client/renderer.js +++ b/packages/kit/src/runtime/client/renderer.js @@ -754,7 +754,7 @@ export class Renderer { if (has_shadow && i === a.length - 1) { const res = await fetch( - `${url.pathname}${url.pathname.endsWith('/') ? '' : '/'}__data.json`, + `${url.pathname}${url.pathname.endsWith('/') ? '' : '/'}__data.json${url.search}`, { headers: { 'x-sveltekit-noredirect': 'true' diff --git a/packages/kit/src/runtime/server/index.js b/packages/kit/src/runtime/server/index.js index 9e52cde695d3..1bca2a3635d0 100644 --- a/packages/kit/src/runtime/server/index.js +++ b/packages/kit/src/runtime/server/index.js @@ -124,7 +124,17 @@ export async function respond(request, options, state = {}) { } const is_data_request = decoded.endsWith(DATA_SUFFIX); - if (is_data_request) decoded = decoded.slice(0, -DATA_SUFFIX.length) || '/'; + + if (is_data_request) { + decoded = decoded.slice(0, -DATA_SUFFIX.length) || '/'; + + const normalized = normalize_path( + url.pathname.slice(0, -DATA_SUFFIX.length), + options.trailing_slash + ); + + event.url = new URL(event.url.origin + normalized + event.url.search); + } for (const route of options.manifest._.routes) { const match = route.pattern.exec(decoded); diff --git a/packages/kit/test/apps/basics/src/routes/shadowed/same-render-entry.svelte b/packages/kit/test/apps/basics/src/routes/shadowed/same-render-entry.svelte new file mode 100644 index 000000000000..58469e584e78 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/shadowed/same-render-entry.svelte @@ -0,0 +1 @@ +Click here to navigate \ No newline at end of file diff --git a/packages/kit/test/apps/basics/src/routes/shadowed/same-render.js b/packages/kit/test/apps/basics/src/routes/shadowed/same-render.js new file mode 100644 index 000000000000..1a50efddcc1f --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/shadowed/same-render.js @@ -0,0 +1,4 @@ +/** @type {import('@sveltejs/kit').RequestHandler} */ +export function get({ url }) { + return { body: { url: url.toString() } }; +} diff --git a/packages/kit/test/apps/basics/src/routes/shadowed/same-render.svelte b/packages/kit/test/apps/basics/src/routes/shadowed/same-render.svelte new file mode 100644 index 000000000000..d3cc398cd527 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/shadowed/same-render.svelte @@ -0,0 +1,5 @@ + +

URL: {url}

\ No newline at end of file diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index f2a740b4aedf..dac816d3123e 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -432,6 +432,12 @@ test.describe.parallel('Shadowed pages', () => { expect(await response.json()).toEqual({ answer: 42 }); }); + test('Endpoint receives consistent URL', async ({ baseURL, page, clicknav }) => { + await page.goto('/shadowed/same-render-entry'); + await clicknav('[href="/shadowed/same-render?param1=value1"]'); + expect(await page.textContent('h1')).toBe(`URL: ${baseURL}/shadowed/same-render?param1=value1`); + }); + test('responds to HEAD requests from endpoint', async ({ request }) => { const url = '/shadowed/simple';