diff --git a/.changeset/angry-planes-swim.md b/.changeset/angry-planes-swim.md new file mode 100644 index 00000000000..680d329032c --- /dev/null +++ b/.changeset/angry-planes-swim.md @@ -0,0 +1,6 @@ +--- +'@whatwg-node/server': patch +--- + +If the environment is not able to send the response, do not terminate the server and handle internal +errors in a better way diff --git a/packages/server/src/createServerAdapter.ts b/packages/server/src/createServerAdapter.ts index 30b6d01632a..ff150cd54bb 100644 --- a/packages/server/src/createServerAdapter.ts +++ b/packages/server/src/createServerAdapter.ts @@ -172,14 +172,18 @@ function createServerAdapter< addWaitUntil(defaultServerContext, waitUntilPromises); return handleNodeRequest(nodeRequest, defaultServerContext as any, ...ctx) .then(response => { - if (response) { - return sendNodeResponse(response, serverResponse, nodeRequest); - } - return new Promise(resolve => { + try { + if (serverResponse.closed || serverResponse.destroyed) { + return; + } + if (response) { + return sendNodeResponse(response, serverResponse, nodeRequest); + } serverResponse.statusCode = 404; - serverResponse.once('end', resolve); serverResponse.end(); - }); + } catch (e: any) { + console.error(`Unexpected error: ${e.message || e}`); + } }) .finally(() => { if (waitUntilPromises.length > 0) { @@ -202,17 +206,27 @@ function createServerAdapter< res, fetchAPI, }); + let resAborted = false; + res.onAborted(() => { + resAborted = true; + }); return handleRequest(request, serverContext).then(response => { - if (!response) { - res.writeStatus('404 Not Found'); - res.end(); + if (resAborted) { return; } - - return sendResponseToUwsOpts({ - response, - res, - }); + try { + if (!response) { + res.writeStatus('404 Not Found'); + res.end(); + return; + } + return sendResponseToUwsOpts({ + response, + res, + }); + } catch (e: any) { + console.error(`Unexpected error: ${e.message || e}`); + } }); } diff --git a/packages/server/test/node.spec.ts b/packages/server/test/node.spec.ts index 6d3c59b8c22..21f1c3e9a48 100644 --- a/packages/server/test/node.spec.ts +++ b/packages/server/test/node.spec.ts @@ -9,6 +9,7 @@ import { Http2ServerResponse, } from 'http2'; import { AddressInfo } from 'net'; +import { HttpResponse } from 'uWebSockets.js'; import { fetch, ReadableStream, Response } from '@whatwg-node/fetch'; import { createServerAdapter } from '@whatwg-node/server'; import { runTestsForEachServerImpl } from './test-server.js'; @@ -99,6 +100,21 @@ describe('Node Specific Cases', () => { await sleep(100); expect(cancelFn).toHaveBeenCalledTimes(1); }); + + it('should not kill the server if response is ended on low level', async () => { + const serverAdapter = createServerAdapter<{ + res: HttpResponse | ServerResponse; + }>((_req, { res }) => { + res.end('This should reach the client.'); + return new Response('This should never reach the client.', { + status: 200, + }); + }); + testServer.addOnceHandler(serverAdapter); + const response = await fetch(testServer.url); + const resText = await response.text(); + expect(resText).toBe('This should reach the client.'); + }); }); });