Skip to content
Open
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
6 changes: 6 additions & 0 deletions .changeset/rare-schools-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@sveltejs/kit": minor
---

feat: allow adapters to override getRequest and setResponse

13 changes: 12 additions & 1 deletion documentation/docs/25-build-and-deploy/99-writing-adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type AdapterSpecificOptions = any;

// @filename: index.js
// ---cut---
import { getRequest, setResponse } from '@sveltejs/kit/node';

/** @param {AdapterSpecificOptions} options */
export default function (options) {
/** @type {import('@sveltejs/kit').Adapter} */
Expand Down Expand Up @@ -40,6 +42,15 @@ export default function (options) {
// Return `false if it can't, or throw a descriptive error.
}
},
getRequest(options) {
const request = getRequest(options);
// modify the Request object here if needed
return request;
},
setResponse(res, response) {
// handle WebSockets here, for example
setResponse(res, response);
},
vite: {
plugins: {
// add plugins here to integrate with Vite
Expand All @@ -53,7 +64,7 @@ export default function (options) {
}
```

Of these, `name` and `adapt` are required. `emulate`, `vite`, and `supports` are optional.
Of these, `name` and `adapt` are required. `emulate`, `vite`, `getRequest`, `setResponse`, and `supports` are optional.

Within the `adapt` method, there are a number of things that an adapter should do:

Expand Down
13 changes: 13 additions & 0 deletions packages/kit/src/exports/public.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { SvelteConfig } from '@sveltejs/vite-plugin-svelte';
import { Plugin } from 'vite';
import { RouteId as AppRouteId, LayoutParams as AppLayoutParams } from '$app/types';
import { ParamMatcher } from '@sveltejs/kit/params';
import { getRequest, setResponse } from '@sveltejs/kit/node';

export { PrerenderOption } from '../types/private.js';

Expand Down Expand Up @@ -58,6 +59,18 @@ export interface Adapter {
*/
instrumentation?: () => boolean;
};
/**
* This function overrides the default behavior to convert an `http.IncomingMessage` to a `Request` object.
* To call the original setRequest function, import it from `@sveltejs/kit/node`.
* @since 3.0.0
*/
getRequest?: typeof getRequest;
/**
* This function overrides the default behavior to write a `Response` object to an `http.ServerResponse`.
* To call the original setResponse function, import it from `@sveltejs/kit/node`.
* @since 3.0.0
*/
setResponse?: typeof setResponse;
/**
* Creates an `Emulator`, which allows the adapter to influence the environment
* during dev, build and prerendering.
Expand Down
6 changes: 3 additions & 3 deletions packages/kit/src/exports/vite/dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ export async function dev(
read: (file) => createReadableStream(from_fs(file))
});

const request = getRequest({
const request = (svelte_config.kit.adapter?.getRequest ?? getRequest)({
base,
request: req
});
Expand Down Expand Up @@ -646,11 +646,11 @@ export async function dev(
// @ts-expect-error
serve_static_middleware.handle(req, res, () => {
log_response(rendered.status, request);
setResponse(res, rendered);
(svelte_config.kit.adapter?.setResponse ?? setResponse)(res, rendered);
});
} else {
log_response(rendered.status, request);
setResponse(res, rendered);
(svelte_config.kit.adapter?.setResponse ?? setResponse)(res, rendered);
}
} catch (e) {
const error = coalesce_to_error(e);
Expand Down
4 changes: 2 additions & 2 deletions packages/kit/src/exports/vite/preview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,12 @@ export async function preview(vite, vite_config, svelte_config) {
vite.middlewares.use(async (req, res) => {
const host = req.headers[':authority'] || req.headers.host;

const request = getRequest({
const request = (svelte_config.kit.adapter?.getRequest ?? getRequest)({
base: `${protocol}://${host}`,
request: req
});

setResponse(
(svelte_config.kit.adapter?.setResponse ?? setResponse)(
res,
await server.respond(request, {
getClientAddress: () => {
Expand Down
13 changes: 13 additions & 0 deletions packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ declare module '@sveltejs/kit' {
import type { SvelteConfig } from '@sveltejs/vite-plugin-svelte';
import type { Plugin } from 'vite';
import type { RouteId as AppRouteId, LayoutParams as AppLayoutParams } from '$app/types';
import type { getRequest, setResponse } from '@sveltejs/kit/node';
import type { StandardSchemaV1 } from '@standard-schema/spec';
// @ts-ignore this is an optional peer dependency so could be missing. Written like this so dts-buddy preserves the ts-ignore
type Span = import('@opentelemetry/api').Span;
Expand Down Expand Up @@ -38,6 +39,18 @@ declare module '@sveltejs/kit' {
*/
instrumentation?: () => boolean;
};
/**
* This function overrides the default behavior to convert an `http.IncomingMessage` to a `Request` object.
* To call the original setRequest function, import it from `@sveltejs/kit/node`.
* @since 3.0.0
*/
getRequest?: typeof getRequest;
/**
* This function overrides the default behavior to write a `Response` object to an `http.ServerResponse`.
* To call the original setResponse function, import it from `@sveltejs/kit/node`.
* @since 3.0.0
*/
setResponse?: typeof setResponse;
/**
* Creates an `Emulator`, which allows the adapter to influence the environment
* during dev, build and prerendering.
Expand Down
Loading