From 24887c7ebe404bc238756f41b9ab783d49e15017 Mon Sep 17 00:00:00 2001 From: orisrightpaw Date: Tue, 17 Jun 2025 23:51:18 -0400 Subject: [PATCH 1/3] feat: add signal property to request in vite, node environments --- .changeset/twelve-jokes-prove.md | 6 ++++++ packages/kit/src/exports/node/index.js | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 .changeset/twelve-jokes-prove.md diff --git a/.changeset/twelve-jokes-prove.md b/.changeset/twelve-jokes-prove.md new file mode 100644 index 000000000000..88fa8c65f40f --- /dev/null +++ b/.changeset/twelve-jokes-prove.md @@ -0,0 +1,6 @@ +--- +'@sveltejs/adapter-node': minor +'@sveltejs/kit': minor +--- + +feat: add signal property to request in vite, node environments diff --git a/packages/kit/src/exports/node/index.js b/packages/kit/src/exports/node/index.js index a69b7ae6d906..684ed103bdb3 100644 --- a/packages/kit/src/exports/node/index.js +++ b/packages/kit/src/exports/node/index.js @@ -120,11 +120,19 @@ export async function getRequest({ request, base, bodySizeLimit }) { delete headers[':scheme']; } + const controller = new AbortController(); + request.once('close', () => { + if (request.readableAborted) { + controller.abort(); + } + }); + return new Request(base + request.url, { // @ts-expect-error duplex: 'half', method: request.method, headers: Object.entries(headers), + signal: controller.signal, body: request.method === 'GET' || request.method === 'HEAD' ? undefined From 2654850d962066e2b89da751197deea8bd109e4b Mon Sep 17 00:00:00 2001 From: orisrightpaw Date: Wed, 18 Jun 2025 00:11:39 -0400 Subject: [PATCH 2/3] docs: describe signal property behavior in adapter-node --- .../25-build-and-deploy/40-adapter-node.md | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/documentation/docs/25-build-and-deploy/40-adapter-node.md b/documentation/docs/25-build-and-deploy/40-adapter-node.md index ce0a5bccf95f..c0050705f1c3 100644 --- a/documentation/docs/25-build-and-deploy/40-adapter-node.md +++ b/documentation/docs/25-build-and-deploy/40-adapter-node.md @@ -263,3 +263,49 @@ app.listen(3000, () => { console.log('listening on port 3000'); }); ``` + +## Aborted requests + +> [!NOTE] This feature is available in `vite dev` and `vite preview` servers. + +The adapter will fire an `abort` event when the incoming request is cancelled before completion. You can access the [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) via `event.request.signal`. + +A pretty typical example of using the `signal` property: + +```js +/// file: src/routes/api/object/[slug]/+server.js +/** @type {import('./$types').RequestHandler} */ +export async function GET({ request, params }) { + const stream = await s3.getObject("bucket", params.slug, { + signal: request.signal + }) + + return new Response(stream) +} +``` + +Another example, this time using [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events): + +```js +/// file: src/routes/api/sse/+server.js +/** @type {import('./$types').RequestHandler} */ +export async function GET({ request }) { + const stream = new ReadableStream({ + start(controller) { + const interval = setInterval(() => { + controller.enqueue("data: Hello, world!\n\n\n"); + }, 1000); + + request.signal.onabort = () => { + clearInterval(interval); + }; + }, + }); + + return new Response(stream, { + headers: { + "Content-Type": "text/event-stream", + }, + }); +} +``` \ No newline at end of file From 1396477c5975cdcf2209de2cb7d726242aa4757c Mon Sep 17 00:00:00 2001 From: orisrightpaw Date: Wed, 18 Jun 2025 00:17:15 -0400 Subject: [PATCH 3/3] docs: remove unnecessary async in example --- documentation/docs/25-build-and-deploy/40-adapter-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/25-build-and-deploy/40-adapter-node.md b/documentation/docs/25-build-and-deploy/40-adapter-node.md index c0050705f1c3..7c51c77ca377 100644 --- a/documentation/docs/25-build-and-deploy/40-adapter-node.md +++ b/documentation/docs/25-build-and-deploy/40-adapter-node.md @@ -289,7 +289,7 @@ Another example, this time using [Server-Sent Events](https://developer.mozilla. ```js /// file: src/routes/api/sse/+server.js /** @type {import('./$types').RequestHandler} */ -export async function GET({ request }) { +export function GET({ request }) { const stream = new ReadableStream({ start(controller) { const interval = setInterval(() => {