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/thick-steaks-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Passthrough server-side fetch cookies for most same-origin scenarios
2 changes: 2 additions & 0 deletions documentation/docs/03-loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ So if the example above was `src/routes/blog/[slug].svelte` and the URL was `htt

> When `fetch` runs on the server, the resulting response will be serialized and inlined into the rendered HTML. This allows the subsequent client-side `load` to access identical data immediately without an additional network request.

> Cookies will only be passed through if the target host is the same as the SvelteKit application or a more specific subdomain of it.

#### session

`session` can be used to pass data from the server related to the current request, e.g. the current user. By default it is `undefined`. See [`getSession`](#hooks-getsession) to learn how to use it.
Expand Down
32 changes: 28 additions & 4 deletions packages/kit/src/runtime/server/page/load_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { resolve } from './resolve.js';

const s = JSON.stringify;

const hasScheme = (/** @type {string} */ url) => /^[a-zA-Z]+:/.test(url);

/**
*
* @param {{
Expand Down Expand Up @@ -97,10 +99,32 @@ export async function load_node({

let response;

if (/^[a-zA-Z]+:/.test(url)) {
// external fetch
const request = new Request(url, /** @type {RequestInit} */ (opts));
response = await options.hooks.serverFetch.call(null, request);
if (hasScheme(url)) {
// possibly external fetch
if (typeof request.host !== 'undefined') {
const { hostname: fetchHostname } = new URL(url);
const [serverHostname] = request.host.split(':');

// allow cookie passthrough for "same-origin"
// if SvelteKit is serving my.domain.com:
// - domain.com WILL NOT receive cookies
// - my.domain.com WILL receive cookies
// - api.domain.dom WILL NOT receive cookies
// - sub.my.domain.com WILL receive cookies
// ports do not affect the resolution
// leading dot prevents mydomain.com matching domain.com
if (`.${fetchHostname}`.endsWith(`.${serverHostname}`) && opts.credentials !== 'omit') {
uses_credentials = true;

opts.headers = {
...opts.headers,
cookie: request.headers.cookie
};
}
}

const externalRequest = new Request(url, /** @type {RequestInit} */ (opts));
response = await options.hooks.serverFetch.call(null, externalRequest);
} else {
const [path, search] = url.split('?');

Expand Down