From 29a2f0d1802a4fe286ae56715ac1a06315f8f858 Mon Sep 17 00:00:00 2001 From: Alex / KATT Date: Sun, 29 Dec 2024 13:07:04 +0100 Subject: [PATCH] fix(server): handle runtimes where `req.socket` isn't available (#6343) --- .../adapters/fastify/fastifyRequestHandler.ts | 4 +-- .../node-http/incomingMessageToRequest.ts | 28 +++++++++++-------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/server/src/adapters/fastify/fastifyRequestHandler.ts b/packages/server/src/adapters/fastify/fastifyRequestHandler.ts index 56144a6086f..e7e28904e12 100644 --- a/packages/server/src/adapters/fastify/fastifyRequestHandler.ts +++ b/packages/server/src/adapters/fastify/fastifyRequestHandler.ts @@ -19,8 +19,8 @@ import { // @trpc/server/node-http import { incomingMessageToRequest, - type IncomingMessageWithBody, type NodeHTTPCreateContextOption, + type UniversalIncomingMessage, } from '../node-http'; export type FastifyHandlerOptions< @@ -54,7 +54,7 @@ export async function fastifyRequestHandler< }); }; - const incomingMessage = opts.req.raw as IncomingMessageWithBody; + const incomingMessage: UniversalIncomingMessage = opts.req.raw; // monkey-path body to the IncomingMessage if ('body' in opts.req) { diff --git a/packages/server/src/adapters/node-http/incomingMessageToRequest.ts b/packages/server/src/adapters/node-http/incomingMessageToRequest.ts index 058bd3ccaae..91e6a1e9ec1 100644 --- a/packages/server/src/adapters/node-http/incomingMessageToRequest.ts +++ b/packages/server/src/adapters/node-http/incomingMessageToRequest.ts @@ -1,15 +1,21 @@ import type * as http from 'http'; import { TRPCError } from '../../@trpc/server'; -export interface IncomingMessageWithBody extends http.IncomingMessage { +export interface UniversalIncomingMessage + extends Omit { /** * Many adapters will add a `body` property to the incoming message and pre-parse the body */ body?: unknown; + /** + * Socket is not always available in all deployments, so we need to make it optional + * @see https://github.com/trpc/trpc/issues/6341 + */ + socket?: http.IncomingMessage['socket']; } function createBody( - req: http.IncomingMessage, + req: UniversalIncomingMessage, opts: { /** * Max body size in bytes. If the body is larger than this, the request will be aborted @@ -19,16 +25,16 @@ function createBody( ): RequestInit['body'] { // Some adapters will pre-parse the body and add it to the request object if ('body' in req) { + if (req.body === undefined) { + // If body property exists but is undefined, return undefined + return undefined; + } // If the body is already a string, return it directly if (typeof req.body === 'string') { return req.body; } // If body exists but isn't a string, stringify it as JSON - else if (req.body !== undefined) { - return JSON.stringify(req.body); - } - // If body property exists but is undefined, return undefined - return undefined; + return JSON.stringify(req.body); } let size = 0; let hasClosed = false; @@ -71,7 +77,7 @@ function createBody( }, }); } -export function createURL(req: http.IncomingMessage): URL { +export function createURL(req: UniversalIncomingMessage): URL { try { const protocol = req.socket && 'encrypted' in req.socket && req.socket.encrypted @@ -117,7 +123,7 @@ function createHeaders(incoming: http.IncomingHttpHeaders): Headers { * Convert an [`IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage) to a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) */ export function incomingMessageToRequest( - req: http.IncomingMessage, + req: UniversalIncomingMessage, res: http.ServerResponse, opts: { /** @@ -130,14 +136,14 @@ export function incomingMessageToRequest( const onAbort = () => { res.off('close', onAbort); - req.socket.off('end', onAbort); + req.socket?.off('end', onAbort); // abort the request ac.abort(); }; res.once('close', onAbort); - req.socket.once('end', onAbort); + req.socket?.once('end', onAbort); // Get host from either regular header or HTTP/2 pseudo-header const url = createURL(req);