diff --git a/src/content/changelog/workers/2025-05-22-handle-request-cancellation.mdx b/src/content/changelog/workers/2025-05-22-handle-request-cancellation.mdx new file mode 100644 index 00000000000000..89205f2b639ab6 --- /dev/null +++ b/src/content/changelog/workers/2025-05-22-handle-request-cancellation.mdx @@ -0,0 +1,18 @@ +--- +title: Handle incoming request cancellation in Workers with Request.signal +description: Workers can now add event listeners on Request.signal and perform tasks when the request is cancelled by the client +products: + - workers +date: 2025-05-22T01:00:00Z +--- + +import { Render } from "~/components"; + +In Cloudflare Workers, you can now attach an event listener to [`Request`](/workers/runtime-apis/request/) objects, using the [`signal` property](https://developer.mozilla.org/en-US/docs/Web/API/Request/signal). This allows you to perform tasks when the request to your Worker is canceled by the client. To use this feature, you must set the [`enable_request_signal`](/workers/configuration/compatibility-flags/#enable-requestsignal-for-incoming-requests) compatibility flag. + +You can use a listener to perform cleanup tasks or write to logs before your Worker's invocation ends. For example, if you run the Worker below, and then abort the request from the client, a log will be written: + + + + +For more information see the [`Request` documentation](/workers/runtime-apis/request). diff --git a/src/content/compatibility-flags/request-signal.md b/src/content/compatibility-flags/request-signal.md new file mode 100644 index 00000000000000..e60e43e66403e2 --- /dev/null +++ b/src/content/compatibility-flags/request-signal.md @@ -0,0 +1,8 @@ +--- +name: "Enable `Request.signal` for incoming requests" +sort_date: "2025-05-22" +enable_flag: "enable_request_signal" +disable_flag: "disable_request_signal" +--- + +When you use the `enable_request_signal` compatibility flag, you can attach an event listener to [`Request`](/workers/runtime-apis/request/) objects, using the [`signal` property](https://developer.mozilla.org/en-US/docs/Web/API/Request/signal). This allows you to perform tasks when the request to your Worker is canceled by the client. \ No newline at end of file diff --git a/src/content/docs/workers/runtime-apis/request.mdx b/src/content/docs/workers/runtime-apis/request.mdx index 93f4cb620f56af..0571113efb32b4 100644 --- a/src/content/docs/workers/runtime-apis/request.mdx +++ b/src/content/docs/workers/runtime-apis/request.mdx @@ -6,7 +6,7 @@ description: Interface that represents an HTTP request. --- -import { Type, MetaInfo } from "~/components"; +import { Type, MetaInfo, Render } from "~/components"; The [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request) interface represents an HTTP request and is part of the [Fetch API](/workers/runtime-apis/fetch/). @@ -88,6 +88,8 @@ An object containing properties that you want to apply to the request. * The redirect mode to use: `follow`, `error`, or `manual`. The default for a new `Request` object is `follow`. Note, however, that the incoming `Request` property of a `FetchEvent` will have redirect mode `manual`. +* `signal` AbortSignal optional + * If provided, the request can be canceled by triggering an abort on the corresponding `AbortController`. #### The `cf` property (`RequestInitCfProperties`) @@ -194,6 +196,11 @@ All properties of an incoming `Request` object (the request you receive from the * The redirect mode to use: `follow`, `error`, or `manual`. The `fetch` method will automatically follow redirects if the redirect mode is set to `follow`. If set to `manual`, the `3xx` redirect response will be returned to the caller as-is. The default for a new `Request` object is `follow`. Note, however, that the incoming `Request` property of a `FetchEvent` will have redirect mode `manual`. +* `signal` AbortSignal read-only + * The `AbortSignal` corresponding to this request. If you use the [`enable_request_signal`](/workers/configuration/compatibility-flags/#enable-requestsignal-for-incoming-requests) compatibility flag, you can attach an event listener to the signal. This allows you to perform cleanup tasks or write to logs before your Worker's invocation ends. + For example, if you run the Worker below, and then abort the request from the client, a log will be written: + + * `url` string read-only * Contains the URL of the request. diff --git a/src/content/partials/workers/request-signal-example.mdx b/src/content/partials/workers/request-signal-example.mdx new file mode 100644 index 00000000000000..e07caed0427765 --- /dev/null +++ b/src/content/partials/workers/request-signal-example.mdx @@ -0,0 +1,35 @@ +--- +{} + +--- + +import { TypeScriptExample } from "~/components"; + + +```ts +export default { + async fetch(request, env, ctx): Promise { + // This sets up an event listener that will be called if the client disconnects from your + // worker. + request.signal.addEventListener('abort', () => { + console.log('The request was aborted!'); + }); + + const { readable, writable } = new IdentityTransformStream(); + sendPing(writable); + return new Response(readable, { headers: { 'Content-Type': 'text/plain' } }); + }, +} satisfies ExportedHandler; + +async function sendPing(writable: WritableStream): Promise { + const writer = writable.getWriter(); + const enc = new TextEncoder(); + + for (;;) { + // Send 'ping' every second to keep the connection alive + await writer.write(enc.encode('ping\r\n')); + await scheduler.wait(1000); + } +} +``` +