diff --git a/.changeset/forty-lions-give.md b/.changeset/forty-lions-give.md new file mode 100644 index 000000000000..1c0228231662 --- /dev/null +++ b/.changeset/forty-lions-give.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +[breaking] resolve relative urls from the target page when using load's fetch diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index fc28a23103d1..3962f7d92f66 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -578,11 +578,44 @@ export function create_client({ target, session, base, trailing_slash }) { node.uses.stuff = true; return { ...stuff }; }, - fetch(resource, info) { - const requested = typeof resource === 'string' ? resource : resource.url; - add_dependency(requested); + async fetch(resource, init) { + let requested; + + if (typeof resource === 'string') { + requested = resource; + } else { + requested = resource.url; + + // we're not allowed to modify the received `Request` object, so in order + // to fixup relative urls we create a new equivalent `init` object instead + init = { + // the request body must be consumed in memory until browsers + // implement streaming request bodies and/or the body getter + body: + resource.method === 'GET' || resource.method === 'HEAD' + ? undefined + : await resource.blob(), + cache: resource.cache, + credentials: resource.credentials, + headers: resource.headers, + integrity: resource.integrity, + keepalive: resource.keepalive, + method: resource.method, + mode: resource.mode, + redirect: resource.redirect, + referrer: resource.referrer, + referrerPolicy: resource.referrerPolicy, + signal: resource.signal, + ...init + }; + } + + // we must fixup relative urls so they are resolved from the target page + const normalized = new URL(requested, url).href; + add_dependency(normalized); - return started ? fetch(resource, info) : initial_fetch(resource, info); + // prerendered pages may be served from any origin, so `initial_fetch` urls shouldn't be normalized + return started ? fetch(normalized, init) : initial_fetch(requested, init); }, status: status ?? null, error: error ?? null diff --git a/packages/kit/test/apps/basics/src/routes/load/fetch-relative.json.js b/packages/kit/test/apps/basics/src/routes/load/fetch-relative.json.js new file mode 100644 index 000000000000..6cabf09828a6 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/fetch-relative.json.js @@ -0,0 +1,16 @@ +export function get() { + return { + body: { + answer: 42 + } + }; +} + +/** @type {import('@sveltejs/kit').RequestHandler} */ +export async function post({ request }) { + return { + body: { + question: await request.text() + } + }; +} diff --git a/packages/kit/test/apps/basics/src/routes/load/fetch-relative.svelte b/packages/kit/test/apps/basics/src/routes/load/fetch-relative.svelte new file mode 100644 index 000000000000..4418226688cc --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/fetch-relative.svelte @@ -0,0 +1,19 @@ + + + + +