diff --git a/apps/svelte.dev/content/docs/kit/20-core-concepts/20-load.md b/apps/svelte.dev/content/docs/kit/20-core-concepts/20-load.md index b53304c60b..a93eae45f3 100644 --- a/apps/svelte.dev/content/docs/kit/20-core-concepts/20-load.md +++ b/apps/svelte.dev/content/docs/kit/20-core-concepts/20-load.md @@ -714,6 +714,74 @@ To prevent data waterfalls and preserve layout `load` caches: Putting an auth guard in `+layout.server.js` requires all child pages to call `await parent()` before protected code. Unless every child page depends on returned data from `await parent()`, the other options will be more performant. +## Using `getRequestEvent` + +When running server `load` functions, the `event` object passed to the function as an argument can also be retrieved with [`getRequestEvent`]($app-server#getRequestEvent). This allows shared logic (such as authentication guards) to access information about the current request without it needing to be passed around. + +For example, you might have a function that requires users to be logged in, and redirects them to `/login` if not: + +```js +/// file: src/lib/server/auth.js +// @filename: ambient.d.ts +interface User { + name: string; +} + +declare namespace App { + interface Locals { + user?: User; + } +} + +// @filename: index.ts +// ---cut--- +import { redirect } from '@sveltejs/kit'; +import { getRequestEvent } from '$app/server'; + +export function requireLogin() { + const { locals, url } = getRequestEvent(); + + // assume `locals.user` is populated in `handle` + if (!locals.user) { + const redirectTo = url.pathname + url.search; + const params = new URLSearchParams({ redirectTo }); + + redirect(307, `/login?${params}`); + } + + return locals.user; +} +``` + +Now, you can call `requireLogin` in any `load` function (or [form action](form-actions), for example) to guarantee that the user is logged in: + +```js +/// file: +page.server.js +// @filename: ambient.d.ts + +declare module '$lib/server/auth' { + interface User { + name: string; + } + + export function requireLogin(): User; +} + +// @filename: index.ts +// ---cut--- +import { requireLogin } from '$lib/server/auth'; + +export function load() { + const user = requireLogin(); + + // `user` is guaranteed to be a user object here, because otherwise + // `requireLogin` would throw a redirect and we wouldn't get here + return { + message: `hello ${user.name}!` + }; +} +``` + ## Further reading - [Tutorial: Loading data](/tutorial/kit/page-data) diff --git a/apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md b/apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md index ff1d26f383..5fb3b8b4b0 100644 --- a/apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md +++ b/apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md @@ -7,9 +7,34 @@ title: $app/server ```js // @noErrors -import { read } from '$app/server'; +import { getRequestEvent, read } from '$app/server'; +``` + +## getRequestEvent + +
+ +Available since 2.20.0 + ++ +Returns the current `RequestEvent`. Can be used inside `handle`, `load` and actions (and functions called by them). + +In environments without [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage), this must be called synchronously (i.e. not after an `await`). + +