Skip to content

Commit 10815c4

Browse files
ronagaddaleax
authored andcommitted
http: provide keep-alive timeout response header
In http 1.1 persistent connection protocol there is a timing race where the client sends the request and then the server kills the connection (due to inactivity) before receiving the client's request. By providing a keep-alive header it is possible to provide the client a hint of when idle timeout would occur and avoid the race. Fixes: #34560 PR-URL: #34561 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Zeyu Yang <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]> Reviewed-By: Pranshu Srivastava <[email protected]>
1 parent c0a961e commit 10815c4

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

lib/_http_outgoing.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const {
2828
ObjectKeys,
2929
ObjectPrototypeHasOwnProperty,
3030
ObjectSetPrototypeOf,
31+
MathFloor,
3132
Symbol,
3233
} = primordials;
3334

@@ -117,6 +118,8 @@ function OutgoingMessage() {
117118
this._header = null;
118119
this[kOutHeaders] = null;
119120

121+
this._keepAliveTimeout = 0;
122+
120123
this._onPendingData = noopPendingOutput;
121124
}
122125
ObjectSetPrototypeOf(OutgoingMessage.prototype, Stream.prototype);
@@ -402,6 +405,10 @@ function _storeHeader(firstLine, headers) {
402405
(state.contLen || this.useChunkedEncodingByDefault || this.agent);
403406
if (shouldSendKeepAlive) {
404407
header += 'Connection: keep-alive\r\n';
408+
if (this._keepAliveTimeout) {
409+
const timeoutSeconds = MathFloor(this._keepAliveTimeout) / 1000;
410+
header += `Keep-Alive: timeout=${timeoutSeconds}\r\n`;
411+
}
405412
} else {
406413
this._last = true;
407414
header += 'Connection: close\r\n';

lib/_http_server.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
740740
}
741741

742742
const res = new server[kServerResponse](req);
743+
res._keepAliveTimeout = server.keepAliveTimeout;
743744
res._onPendingData = updateOutgoingData.bind(undefined, socket, state);
744745

745746
res.shouldKeepAlive = keepAlive;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const http = require('http');
5+
const assert = require('assert');
6+
7+
const server = http.createServer(common.mustCall((req, res) => {
8+
const body = 'hello world\n';
9+
10+
res.writeHead(200, { 'Content-Length': body.length });
11+
res.write(body);
12+
res.end();
13+
}));
14+
server.keepAliveTimeout = 12000;
15+
16+
const agent = new http.Agent({ maxSockets: 1, keepAlive: true });
17+
18+
server.listen(0, common.mustCall(function() {
19+
http.get({
20+
path: '/', port: this.address().port, agent: agent
21+
}, common.mustCall((response) => {
22+
response.resume();
23+
assert.strictEqual(
24+
response.headers['keep-alive'], 'timeout=12');
25+
server.close();
26+
agent.destroy();
27+
}));
28+
}));

0 commit comments

Comments
 (0)