Skip to content

Commit

Permalink
[fix] Server-side fetch request should have headers (#696) (#3631)
Browse files Browse the repository at this point in the history
* pr 2861  rebase

* merge headers from request

* Revert "merge headers from request"

This reverts commit 6f5308e.

* Update packages/kit/src/runtime/server/page/load_node.js

* omit cookie and authorization headers by default

* all headers are single-valued, so use set rather than append

* omit if-none-match, replace referer header

* add test

* changeset

Co-authored-by: tom <anytable@gmail.com>
Co-authored-by: Rich Harris <hello@rich-harris.dev>
  • Loading branch information
3 people authored Feb 1, 2022
1 parent cf5d4aa commit d98cc57
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/twenty-numbers-destroy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Include page request headers in server-side fetches
17 changes: 13 additions & 4 deletions packages/kit/src/runtime/server/page/load_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ export async function load_node({

opts.headers = new Headers(opts.headers);

// merge headers from request
for (const [key, value] of event.request.headers) {
if (opts.headers.has(key)) continue;
if (key === 'cookie' || key === 'authorization' || key === 'if-none-match') continue;
opts.headers.set(key, value);
}

opts.headers.set('referer', event.url.href);

const resolved = resolve(event.url.pathname, requested.split('?')[0]);

/** @type {Response} */
Expand Down Expand Up @@ -209,10 +218,10 @@ export async function load_node({
if (!opts.body || typeof opts.body === 'string') {
// prettier-ignore
fetched.push({
url: requested,
body: /** @type {string} */ (opts.body),
json: `{"status":${response.status},"statusText":${s(response.statusText)},"headers":${s(headers)},"body":"${escape_json_string_in_html(body)}"}`
});
url: requested,
body: /** @type {string} */ (opts.body),
json: `{"status":${response.status},"statusText":${s(response.statusText)},"headers":${s(headers)},"body":"${escape_json_string_in_html(body)}"}`
});
}

if (dependency) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('@sveltejs/kit').RequestHandler} */
export function get({ request }) {
return {
body: Object.fromEntries(request.headers)
};
}
26 changes: 26 additions & 0 deletions packages/kit/test/apps/basics/src/routes/load/fetch-headers.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script context="module">
/** @type {import('@sveltejs/kit').Load} */
export async function load({ fetch }) {
const res = await fetch('/load/fetch-headers.json');
return {
props: {
headers: await res.json()
}
};
}
</script>

<script>
/** @type {Record<string, string>} */
export let headers;
const json = JSON.stringify({
'sec-fetch-dest': headers['sec-fetch-dest'],
'sec-fetch-mode': headers['sec-fetch-mode'],
'if-none-match': headers['if-none-match'],
referer: headers['referer']
});
</script>

<pre>{json}</pre>
1 change: 1 addition & 0 deletions packages/kit/test/apps/basics/src/routes/load/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

<a href="/load/fetch-request">fetch request</a>
<a href="/load/fetch-credentialed">fetch credentialed</a>
<a href="/load/fetch-headers">fetch headers</a>
<a href="/load/large-response">large response</a>
<a href="/load/raw-body">raw body</a>
<a href="/load/server-fetch-request">server fetch request</a>
19 changes: 19 additions & 0 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,25 @@ test.describe.parallel('Load', () => {
expect(await page.textContent('h1')).toBe('Hello SvelteKit!');
});

test('includes correct page request headers', async ({
baseURL,
page,
clicknav,
javaScriptEnabled
}) => {
await page.goto('/load');
await clicknav('[href="/load/fetch-headers"]');

const json = /** @type {string} */ (await page.textContent('pre'));
expect(JSON.parse(json)).toEqual({
referer: `${baseURL}/load/fetch-headers`,
// these headers aren't particularly useful, but they allow us to verify
// that page headers are being forwarded
'sec-fetch-dest': javaScriptEnabled ? 'empty' : 'document',
'sec-fetch-mode': javaScriptEnabled ? 'cors' : 'navigate'
});
});

test('exposes rawBody to endpoints', async ({ page, clicknav }) => {
await page.goto('/load');
await clicknav('[href="/load/raw-body"]');
Expand Down

0 comments on commit d98cc57

Please sign in to comment.