Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/honest-cobras-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

fix: `fetch` not working when URL is same host but different than `paths.base`
8 changes: 6 additions & 2 deletions packages/kit/src/runtime/server/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
request.headers.delete('origin');
}

if (url.origin !== event.url.origin) {
const decoded = decodeURIComponent(url.pathname);

if (
url.origin !== event.url.origin ||
(paths.base && decoded !== paths.base && !decoded.startsWith(`${paths.base}/`))
) {
// Allow cookie passthrough for "credentials: same-origin" and "credentials: include"
// if SvelteKit is serving my.domain.com:
// - domain.com WILL NOT receive cookies
Expand All @@ -77,7 +82,6 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
// handle fetch requests for static assets. e.g. prebaked data, etc.
// we need to support everything the browser's fetch supports
const prefix = paths.assets || paths.base;
const decoded = decodeURIComponent(url.pathname);
const filename = (
decoded.startsWith(prefix) ? decoded.slice(prefix.length) : decoded
).slice(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
fetch('/request-abort', { headers: { accept: 'application/json' } }).then(
async (r) => (result = await r.json())
);
}, 100);
}, 50);
}
onMount(test_abort);
Expand Down
3 changes: 3 additions & 0 deletions packages/kit/test/apps/options/source/pages/+server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function GET() {
return new Response('root');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export async function load({ fetch }) {
const response = await fetch('/not-base-path/');
return {
fetchUrl: response.url,
fetchResponse: await response.text()
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
/** @type {import('./$types').PageProps} */
const { data } = $props();
</script>

<p data-testid="fetch-url">{data.fetchUrl}</p>
<p data-testid="fetch-response">{data.fetchResponse}</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export async function load({ fetch }) {
// fetch to root with trailing slash
const response1 = await fetch('/', { redirect: 'manual' });
// fetch to root without trailing slash
const response2 = await fetch('', { redirect: 'manual' });
return {
fetches: [
{
url: response1.url,
response: await response1.text(),
redirect: response1.headers.get('location')
},
{
url: response2.url,
response: await response2.text(),
redirect: response2.headers.get('location')
}
]
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script>
/** @type {import('./$types').PageProps} */
const { data } = $props();
</script>

<h2>Fetch URLs</h2>

<dl>
{#each data.fetches as item, index}
<dt>fetch{index + 1}-url</dt>
<dd data-testid={`fetch${index + 1}-url`}>{item.url}</dd>
{/each}
</dl>

<h2>Fetch Responses</h2>
<dl>
{#each data.fetches as item, index}
<dt>fetch{index + 1}-response</dt>
<dd data-testid="fetch{index + 1}-response">{item.response}</dd>
{/each}
</dl>

<h2>Fetch Redirects</h2>
<dl>
{#each data.fetches as item, index}
<dt>fetch{index + 1}-redirect</dt>
<dd data-testid="fetch{index + 1}-redirect">{item.redirect}</dd>
{/each}
</dl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function GET() {
return new Response('relative');
}
28 changes: 28 additions & 0 deletions packages/kit/test/apps/options/test/paths-assets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,34 @@ test.describe('base path', () => {
expect(page.url()).toBe(`${baseURL}/path-base/resolve-route/resolved/`);
expect(await page.textContent('h2')).toBe('resolved');
});

test('server load fetch without base path does not invoke the server', async ({
page,
baseURL
}) => {
await page.goto('/path-base/fetch/link-outside-base/');
await expect(page.locator('[data-testid="fetch-url"]')).toHaveText(`${baseURL}/not-base-path/`);
await expect(page.locator('[data-testid="fetch-response"]')).toContainText(
'did you mean to visit'
);
});

test('server load fetch to root does not invoke the server', async ({ page, baseURL }) => {
await page.goto('/path-base/fetch/link-root/');
// fetch to root with trailing slash
await expect(page.locator('[data-testid="fetch1-url"]')).toHaveText(`${baseURL}/`);
if (process.env.DEV) {
await expect(page.locator('[data-testid="fetch1-redirect"]')).toHaveText('/path-base');
} else {
await expect(page.locator('[data-testid="fetch1-response"]')).toContainText(
'did you mean to visit'
);
}

// fetch to root without trailing slash should be relative
await expect(page.locator('[data-testid="fetch2-url"]')).toBeEmpty();
await expect(page.locator('[data-testid="fetch2-response"]')).toHaveText('relative');
});
});

test.describe('assets path', () => {
Expand Down
Loading