Repository navigation
http: respect Keep-Alive timeout hint when agent has no explicit timeout - #66737
Open
DivyanshuX9 wants to merge 3 commits into
Open
DivyanshuX9 wants to merge 3 commits into
DivyanshuX9 wants to merge 3 commits into
Conversation
When http.Agent is created with keepAlive: true but no explicit timeout
option, the server's Keep-Alive: timeout=N hint was being ignored.
In keepSocketAlive(), agentTimeout is initialized as:
let agentTimeout = this.options.timeout || 0;
When no timeout is configured, this evaluates to 0. The condition that
applies the server hint:
} else if (serverHintTimeout < agentTimeout) {
is never true when agentTimeout is 0, because serverHintTimeout is
always a positive value after buffer subtraction. As a result,
socket.setTimeout(0) is called, which disables the idle timer entirely.
The socket remains in freeSockets after the server closes it, and the
next request that reuses it receives ECONNRESET.
Fix by also applying the server hint when agentTimeout is 0, meaning
no client-side timeout is configured.
Fixes: nodejs#66734
Signed-off-by: Divyanshu Sharma <divyanshu88999@gmail.com>
Collaborator
|
Review requested:
|
Add test-http-agent-keep-alive-server-hint.js covering four cases for Agent.prototype.keepSocketAlive() server hint handling: - agent with no explicit timeout respects server Keep-Alive hint - agent timeout longer than server hint: server hint wins - agent timeout shorter than server hint: agent timeout wins - no Keep-Alive header: socket.timeout stays 0 (no timer) Refs: nodejs#66734 Signed-off-by: Divyanshu Sharma <divyanshu88999@gmail.com>
Node's http.Server automatically sends Keep-Alive: timeout=65 on every
keep-alive response unless keepAliveTimeout is set to 0. Case 4 assumed
no hint would be sent with a plain createServer(), which was incorrect.
Use { keepAliveTimeout: 0 } to suppress the automatic header and
correctly test the no-hint code path.
Refs: nodejs#66734
Signed-off-by: Divyanshu Sharma <divyanshu88999@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When an http.Agent is created with keepAlive: true but no explicit timeout option, the server's Keep-Alive: timeout=N response header is silently ignored. The socket is returned to the pool with socket.setTimeout(0), which disables the idle timer entirely. The server eventually closes the connection, but the socket remains in freeSockets. The next request that reuses it receives ECONNRESET.
Root cause
In keepSocketAlive(), agentTimeout is derived from the agent's timeout option:
When no timeout is configured, agentTimeout is 0. The branch that applies the server hint:
can never be true when agentTimeout === 0 (since serverHintTimeout is always positive after buffer subtraction). As a result, socket.setTimeout(0) is called, disabling the idle timer.
Fix
Also apply the server hint when agentTimeout === 0 (i.e., no client-side timeout is configured). The server's hint is the only available signal, so it should be respected rather than discarded.
Test
Add a test that:
Creates a server that sends Keep-Alive: timeout=1 in the response.
Creates an agent with { keepAlive: true } (no timeout).
Makes a request, waits past the server's hint, and verifies the socket is destroyed (not left in freeSockets).
Fixes: #66734