From ba0d89544bb502b86a2c62a01f7e64fef081e375 Mon Sep 17 00:00:00 2001 From: Arrigo Zanette Date: Mon, 22 Apr 2024 15:40:12 +0200 Subject: [PATCH] net: reduce likelihood of race conditions on keep-alive timeout calculation between http1.1 servers and clients reduced likelihood of race conditions on keep-alive timeout calculation between http1.1 servers and clients and honor server keep-alive timeout when agentTimeout is not set Fixes: /~https://github.com/nodejs/node/issues/47130 Fixes: /~https://github.com/nodejs/node/issues/52649 --- lib/_http_agent.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/_http_agent.js b/lib/_http_agent.js index a4829526f6e1382..629601885cab74d 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -488,6 +488,7 @@ Agent.prototype.keepSocketAlive = function keepSocketAlive(socket) { socket.unref(); let agentTimeout = this.options.timeout || 0; + let canKeepSocketAlive = true; if (socket._httpMessage?.res) { const keepAliveHint = socket._httpMessage.res.headers['keep-alive']; @@ -496,9 +497,14 @@ Agent.prototype.keepSocketAlive = function keepSocketAlive(socket) { const hint = RegExpPrototypeExec(/^timeout=(\d+)/, keepAliveHint)?.[1]; if (hint) { - const serverHintTimeout = NumberParseInt(hint) * 1000; - - if (serverHintTimeout < agentTimeout) { + // Let the timer expires before the announced timeout to reduce + // the likelihood of ECONNRESET errors + let serverHintTimeout = (NumberParseInt(hint) * 1000) - 1000; + serverHintTimeout = serverHintTimeout > 0 ? serverHintTimeout : 0; + if (serverHintTimeout === 0) { + // Cannot safely reuse the socket because the server timeout is too short + canKeepSocketAlive = false; + } else if (!agentTimeout || serverHintTimeout < agentTimeout) { agentTimeout = serverHintTimeout; } } @@ -509,7 +515,7 @@ Agent.prototype.keepSocketAlive = function keepSocketAlive(socket) { socket.setTimeout(agentTimeout); } - return true; + return canKeepSocketAlive; }; Agent.prototype.reuseSocket = function reuseSocket(socket, req) {