diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts index 70605da0c3525..2d6470d948bc1 100644 --- a/packages/next/src/server/next-server.ts +++ b/packages/next/src/server/next-server.ts @@ -110,6 +110,7 @@ import { filterReqHeaders } from './lib/server-ipc/utils' import { createRequestResponseMocks } from './lib/mock-request' import chalk from 'next/dist/compiled/chalk' import { NEXT_RSC_UNION_QUERY } from '../client/components/app-router-headers' +import { signalFromNodeRequest } from './web/spec-extension/adapters/next-request' export * from './base-server' @@ -2342,6 +2343,9 @@ export default class NextNodeServer extends BaseServer { url: url, page: page, body: getRequestMeta(params.request, '__NEXT_CLONABLE_BODY'), + signal: signalFromNodeRequest( + (params.request as NodeNextRequest).originalRequest + ), }, useCache: true, onWarning: params.onWarning, @@ -2851,6 +2855,9 @@ export default class NextNodeServer extends BaseServer { ...(params.params && { params: params.params }), }, body: getRequestMeta(params.req, '__NEXT_CLONABLE_BODY'), + signal: signalFromNodeRequest( + (params.req as NodeNextRequest).originalRequest + ), }, useCache: true, onWarning: params.onWarning, diff --git a/packages/next/src/server/web/adapter.ts b/packages/next/src/server/web/adapter.ts index 60c2abfcd5e52..5a8c953ad71a3 100644 --- a/packages/next/src/server/web/adapter.ts +++ b/packages/next/src/server/web/adapter.ts @@ -132,6 +132,7 @@ export async function adapter( ip: params.request.ip, method: params.request.method, nextConfig: params.request.nextConfig, + signal: params.request.signal, }, }) diff --git a/packages/next/src/server/web/spec-extension/adapters/next-request.ts b/packages/next/src/server/web/spec-extension/adapters/next-request.ts index 2248629df1e20..3efe37370b341 100644 --- a/packages/next/src/server/web/spec-extension/adapters/next-request.ts +++ b/packages/next/src/server/web/spec-extension/adapters/next-request.ts @@ -1,11 +1,22 @@ import type { BaseNextRequest } from '../../../base-http' import type { NodeNextRequest } from '../../../base-http/node' import type { WebNextRequest } from '../../../base-http/web' +import type { IncomingMessage } from 'node:http' import { getRequestMeta } from '../../../request-meta' import { fromNodeOutgoingHttpHeaders } from '../../utils' import { NextRequest } from '../request' +export function signalFromNodeRequest(request: IncomingMessage) { + const { errored } = request + if (errored) return AbortSignal.abort(errored) + const controller = new AbortController() + request.on('error', (e) => { + controller.abort(e) + }) + return controller.signal +} + export class NextRequestAdapter { public static fromBaseNextRequest(request: BaseNextRequest): NextRequest { // TODO: look at refining this check @@ -46,6 +57,7 @@ export class NextRequestAdapter { headers: fromNodeOutgoingHttpHeaders(request.headers), // @ts-expect-error - see https://github.com/whatwg/fetch/pull/1457 duplex: 'half', + signal: signalFromNodeRequest(request.originalRequest), // geo // ip // nextConfig @@ -65,6 +77,7 @@ export class NextRequestAdapter { headers: fromNodeOutgoingHttpHeaders(request.headers), // @ts-expect-error - see https://github.com/whatwg/fetch/pull/1457 duplex: 'half', + signal: request.request.signal, // geo // ip // nextConfig diff --git a/packages/next/src/server/web/spec-extension/request.ts b/packages/next/src/server/web/spec-extension/request.ts index 84cdba908e0c5..de893ce522d75 100644 --- a/packages/next/src/server/web/spec-extension/request.ts +++ b/packages/next/src/server/web/spec-extension/request.ts @@ -16,7 +16,7 @@ export class NextRequest extends Request { nextUrl: NextURL } - constructor(input: URL | RequestInfo, init: RequestInit = {}) { + constructor(input: URL | RequestInfo, init: RequestInit) { const url = typeof input !== 'string' && 'url' in input ? input.url : String(input) validateURL(url) @@ -111,4 +111,5 @@ export interface RequestInit extends globalThis.RequestInit { i18n?: I18NConfig | null trailingSlash?: boolean } + signal?: AbortSignal } diff --git a/packages/next/src/server/web/types.ts b/packages/next/src/server/web/types.ts index 6d4cb7f6f89a3..4ca61bb6c644c 100644 --- a/packages/next/src/server/web/types.ts +++ b/packages/next/src/server/web/types.ts @@ -27,6 +27,7 @@ export interface RequestData { } url: string body?: ReadableStream + signal: AbortSignal } export type NodejsRequestData = Omit & {