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: https://github.com/nodejs/node/issues/34560 PR-URL: https://github.com/nodejs/node/pull/34561 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Zeyu Yang <himself65@outlook.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Pranshu Srivastava <rexagod@gmail.com>
This commit is contained in:
parent
770a02d3c8
commit
849d9e7b90
@ -28,6 +28,7 @@ const {
|
||||
ObjectKeys,
|
||||
ObjectPrototypeHasOwnProperty,
|
||||
ObjectSetPrototypeOf,
|
||||
MathFloor,
|
||||
Symbol,
|
||||
} = primordials;
|
||||
|
||||
@ -123,6 +124,8 @@ function OutgoingMessage() {
|
||||
this._header = null;
|
||||
this[kOutHeaders] = null;
|
||||
|
||||
this._keepAliveTimeout = 0;
|
||||
|
||||
this._onPendingData = noopPendingOutput;
|
||||
}
|
||||
ObjectSetPrototypeOf(OutgoingMessage.prototype, Stream.prototype);
|
||||
@ -424,6 +427,10 @@ function _storeHeader(firstLine, headers) {
|
||||
(state.contLen || this.useChunkedEncodingByDefault || this.agent);
|
||||
if (shouldSendKeepAlive) {
|
||||
header += 'Connection: keep-alive\r\n';
|
||||
if (this._keepAliveTimeout) {
|
||||
const timeoutSeconds = MathFloor(this._keepAliveTimeout) / 1000;
|
||||
header += `Keep-Alive: timeout=${timeoutSeconds}\r\n`;
|
||||
}
|
||||
} else {
|
||||
this._last = true;
|
||||
header += 'Connection: close\r\n';
|
||||
|
@ -766,6 +766,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
|
||||
}
|
||||
|
||||
const res = new server[kServerResponse](req);
|
||||
res._keepAliveTimeout = server.keepAliveTimeout;
|
||||
res._onPendingData = updateOutgoingData.bind(undefined, socket, state);
|
||||
|
||||
res.shouldKeepAlive = keepAlive;
|
||||
|
28
test/parallel/test-http-keep-alive-timeout.js
Normal file
28
test/parallel/test-http-keep-alive-timeout.js
Normal file
@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const http = require('http');
|
||||
const assert = require('assert');
|
||||
|
||||
const server = http.createServer(common.mustCall((req, res) => {
|
||||
const body = 'hello world\n';
|
||||
|
||||
res.writeHead(200, { 'Content-Length': body.length });
|
||||
res.write(body);
|
||||
res.end();
|
||||
}));
|
||||
server.keepAliveTimeout = 12000;
|
||||
|
||||
const agent = new http.Agent({ maxSockets: 1, keepAlive: true });
|
||||
|
||||
server.listen(0, common.mustCall(function() {
|
||||
http.get({
|
||||
path: '/', port: this.address().port, agent: agent
|
||||
}, common.mustCall((response) => {
|
||||
response.resume();
|
||||
assert.strictEqual(
|
||||
response.headers['keep-alive'], 'timeout=12');
|
||||
server.close();
|
||||
agent.destroy();
|
||||
}));
|
||||
}));
|
Loading…
x
Reference in New Issue
Block a user