From e8a2f2f475027e19369fad12e9ff43d7f2062f51 Mon Sep 17 00:00:00 2001 From: pachirel Date: Mon, 16 Oct 2023 16:56:09 +0900 Subject: [PATCH] fix: 'aborted' detection on Node v15.5.0+ This fixes a major memory leak I encountered usign this on Node v16. Doing a binary search of node versions, the problem appears to originate in v15.5.0 as a result of nodejs/node#33035, however later changes have quietly completely removed the 'aborted' event that `http-proxy` relies on, and later added a deprecation note about it (which seems to actually be incorrect). Despite what the notes about [DEP0156](https://nodejs.org/dist/latest-v16.x/docs/api/deprecations.html#DEP0156) say, the only way I could get this module working reliably again was to replace `req.on('aborted')` with instead checking `res.on('close')` and looking at `res.writeableFinished`. The original commit is [here](https://github.com/http-party/node-http-proxy/pull/1559/commits/058182ae832a1a8e018570123db24348009e8598) by Jimbly. --- lib/http-proxy/passes/web-incoming.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/http-proxy/passes/web-incoming.js b/lib/http-proxy/passes/web-incoming.js index 7ae735514..64da74135 100644 --- a/lib/http-proxy/passes/web-incoming.js +++ b/lib/http-proxy/passes/web-incoming.js @@ -18,6 +18,11 @@ var nativeAgents = { http: httpNative, https: httpsNative }; * flexible. */ +// 'aborted' event stopped working reliably on v15.5.0 and was later removed entirely +var supportsAbortedEvent = (function () { + var ver = process.versions.node.split('.').map(Number); + return ver[0] <= 14 || ver[0] === 15 && ver[1] <= 4; +}()); module.exports = { @@ -143,9 +148,18 @@ module.exports = { } // Ensure we abort proxy if request is aborted - req.on('aborted', function () { - proxyReq.abort(); - }); + if (supportsAbortedEvent) { + req.on('aborted', function () { + proxyReq.abort(); + }); + } else { + res.on('close', function () { + var aborted = !res.writableFinished; + if (aborted) { + proxyReq.abort(); + } + }); + } // handle errors in proxy and incoming request, just like for forward proxy var proxyError = createErrorHandler(proxyReq, options.target);