Skip to content

Commit 8516da1

Browse files
ofrobotsBethGriggs
authored andcommitted
http, http2: flag for overriding server timeout
Make it possible to override the default http server timeout. Ideally there should be no server timeout - as done on the master branch. This is a non-breaking way to enable platform providers to override the value. Backport-PR-URL: #27939 PR-URL: #27704 Refs: #27558 Refs: #27556 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Myles Borins <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
1 parent 08a32fb commit 8516da1

File tree

10 files changed

+90
-5
lines changed

10 files changed

+90
-5
lines changed

doc/api/cli.md

+12
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ added: v6.0.0
119119
Force FIPS-compliant crypto on startup. (Cannot be disabled from script code.)
120120
(Same requirements as `--enable-fips`.)
121121

122+
### `--http-server-default-timeout=milliseconds`
123+
<!-- YAML
124+
added: REPLACEME
125+
-->
126+
127+
Overrides the default value of `http`, `https` and `http2` server socket
128+
timeout. Setting the value to 0 disables server socket timeout. Unless
129+
provided, http server sockets timeout after 120s (2 minutes). Programmatic
130+
setting of the timeout takes precedence over the value set through this
131+
flag.
132+
122133
### `--icu-data-dir=file`
123134
<!-- YAML
124135
added: v0.11.15
@@ -590,6 +601,7 @@ Node.js options that are allowed are:
590601
- `--experimental-vm-modules`
591602
- `--experimental-worker`
592603
- `--force-fips`
604+
- `--http-server-default-timeout`
593605
- `--icu-data-dir`
594606
- `--inspect`
595607
- `--inspect-brk`

doc/api/http.md

+7
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,9 @@ By default, the Server's timeout value is 2 minutes, and sockets are
10041004
destroyed automatically if they time out. However, if a callback is assigned
10051005
to the Server's `'timeout'` event, timeouts must be handled explicitly.
10061006

1007+
To change the default timeout use the [`--http-server-default-timeout`][]
1008+
flag.
1009+
10071010
### server.timeout
10081011
<!-- YAML
10091012
added: v0.9.12
@@ -1019,6 +1022,9 @@ A value of `0` will disable the timeout behavior on incoming connections.
10191022
The socket timeout logic is set up on connection, so changing this
10201023
value only affects new connections to the server, not any existing connections.
10211024

1025+
To change the default timeout use the [`--http-server-default-timeout`][]
1026+
flag.
1027+
10221028
### server.keepAliveTimeout
10231029
<!-- YAML
10241030
added: v8.0.0
@@ -2113,6 +2119,7 @@ will be emitted in the following order:
21132119
Note that setting the `timeout` option or using the `setTimeout()` function will
21142120
not abort the request or do anything besides add a `'timeout'` event.
21152121

2122+
[`--http-server-default-timeout`]: cli.html#cli_http_server_default_timeout_milliseconds
21162123
[`--max-http-header-size`]: cli.html#cli_max_http_header_size_size
21172124
[`'checkContinue'`]: #http_event_checkcontinue
21182125
[`'request'`]: #http_event_request

doc/api/http2.md

+7
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,9 @@ The `'timeout'` event is emitted when there is no activity on the Server for
17231723
a given number of milliseconds set using `http2server.setTimeout()`.
17241724
**Default:** 2 minutes.
17251725

1726+
To change the default timeout use the [`--http-server-default-timeout`][]
1727+
flag.
1728+
17261729
#### server.close([callback])
17271730
<!-- YAML
17281731
added: v8.4.0
@@ -1753,6 +1756,9 @@ The given callback is registered as a listener on the `'timeout'` event.
17531756
In case of no callback function were assigned, a new `ERR_INVALID_CALLBACK`
17541757
error will be thrown.
17551758

1759+
To change the default timeout use the [`--http-server-default-timeout`][]
1760+
flag.
1761+
17561762
### Class: Http2SecureServer
17571763
<!-- YAML
17581764
added: v8.4.0
@@ -3411,6 +3417,7 @@ following additional properties:
34113417
* `type` {string} Either `'server'` or `'client'` to identify the type of
34123418
`Http2Session`.
34133419

3420+
[`--http-server-default-timeout`]: cli.html#cli_http_server_default_timeout_milliseconds
34143421
[ALPN Protocol ID]: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
34153422
[ALPN negotiation]: #http2_alpn_negotiation
34163423
[Compatibility API]: #http2_compatibility_api

doc/node.1

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ Chooses an HTTP parser library. Available values are
109109
or
110110
.Sy legacy .
111111
.
112+
.It Fl -http-server-default-timeout Ns = Ns Ar milliseconds
113+
Overrides the default value for server socket timeout.
114+
.
112115
.It Fl -icu-data-dir Ns = Ns Ar file
113116
Specify ICU data load path.
114117
Overrides

lib/_http_server.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@ const {
5050
ERR_INVALID_CHAR
5151
} = require('internal/errors').codes;
5252
const Buffer = require('buffer').Buffer;
53+
const { getOptionValue } = require('internal/options');
5354

5455
const kServerResponse = Symbol('ServerResponse');
56+
const kDefaultHttpServerTimeout =
57+
getOptionValue('--http-server-default-timeout');
5558

5659
const STATUS_CODES = {
5760
100: 'Continue',
@@ -300,7 +303,7 @@ function Server(options, requestListener) {
300303

301304
this.on('connection', connectionListener);
302305

303-
this.timeout = 2 * 60 * 1000;
306+
this.timeout = kDefaultHttpServerTimeout;
304307
this.keepAliveTimeout = 5000;
305308
this.maxHeadersCount = null;
306309
this.headersTimeout = 40 * 1000; // 40 seconds

lib/https.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ const { urlToOptions, searchParamsSymbol } = require('internal/url');
3939
const { ERR_INVALID_DOMAIN_NAME } = require('internal/errors').codes;
4040
const { IncomingMessage, ServerResponse } = require('http');
4141
const { kIncomingMessage } = require('_http_common');
42+
const { getOptionValue } = require('internal/options');
43+
44+
const kDefaultHttpServerTimeout =
45+
getOptionValue('--http-server-default-timeout');
4246

4347
function Server(opts, requestListener) {
4448
if (!(this instanceof Server)) return new Server(opts, requestListener);
@@ -72,7 +76,7 @@ function Server(opts, requestListener) {
7276
conn.destroy(err);
7377
});
7478

75-
this.timeout = 2 * 60 * 1000;
79+
this.timeout = kDefaultHttpServerTimeout;
7680
this.keepAliveTimeout = 5000;
7781
this.maxHeadersCount = null;
7882
this.headersTimeout = 40 * 1000; // 40 seconds

lib/internal/http2/core.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ const { UV_EOF } = process.binding('uv');
126126
const { StreamPipe } = internalBinding('stream_pipe');
127127
const { _connectionListener: httpConnectionListener } = http;
128128
const debug = util.debuglog('http2');
129+
const { getOptionValue } = require('internal/options');
129130

130131
const kMaxFrameSize = (2 ** 24) - 1;
131132
const kMaxInt = (2 ** 32) - 1;
@@ -162,7 +163,8 @@ const kState = Symbol('state');
162163
const kType = Symbol('type');
163164
const kWriteGeneric = Symbol('write-generic');
164165

165-
const kDefaultSocketTimeout = 2 * 60 * 1000;
166+
const kDefaultHttpServerTimeout =
167+
getOptionValue('--http-server-default-timeout');
166168

167169
const {
168170
paddingBuffer,
@@ -2726,7 +2728,7 @@ class Http2SecureServer extends TLSServer {
27262728
options = initializeTLSOptions(options);
27272729
super(options, connectionListener);
27282730
this[kOptions] = options;
2729-
this.timeout = kDefaultSocketTimeout;
2731+
this.timeout = kDefaultHttpServerTimeout;
27302732
this.on('newListener', setupCompat);
27312733
if (typeof requestListener === 'function')
27322734
this.on('request', requestListener);
@@ -2748,7 +2750,7 @@ class Http2Server extends NETServer {
27482750
constructor(options, requestListener) {
27492751
super(connectionListener);
27502752
this[kOptions] = initializeOptions(options);
2751-
this.timeout = kDefaultSocketTimeout;
2753+
this.timeout = kDefaultHttpServerTimeout;
27522754
this.on('newListener', setupCompat);
27532755
if (typeof requestListener === 'function')
27542756
this.on('request', requestListener);

src/node_options.cc

+5
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
102102
&EnvironmentOptions::experimental_worker,
103103
kAllowedInEnvironment);
104104
AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals);
105+
AddOption("--http-server-default-timeout",
106+
"Default http server socket timeout in ms "
107+
"(default: 120000)",
108+
&EnvironmentOptions::http_server_default_timeout,
109+
kAllowedInEnvironment);
105110
AddOption("--loader",
106111
"(with --experimental-modules) use the specified file as a "
107112
"custom loader",

src/node_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class EnvironmentOptions : public Options {
7272
bool experimental_vm_modules = false;
7373
bool experimental_worker = false;
7474
bool expose_internals = false;
75+
uint64_t http_server_default_timeout = 120000;
7576
bool no_deprecation = false;
7677
bool no_force_async_hooks_checks = false;
7778
bool no_warnings = false;
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict';
2+
const common = require('../common');
3+
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
const fixtures = require('../common/fixtures');
8+
const http = require('http');
9+
const https = require('https');
10+
const http2 = require('http2');
11+
const assert = require('assert');
12+
const { spawnSync } = require('child_process');
13+
14+
// Make sure the defaults are correct.
15+
const servers = [
16+
http.createServer(),
17+
https.createServer({
18+
key: fixtures.readKey('agent1-key.pem'),
19+
cert: fixtures.readKey('agent1-cert.pem')
20+
}),
21+
http2.createServer()
22+
];
23+
24+
for (const server of servers) {
25+
assert.strictEqual(server.timeout, 120000);
26+
server.close();
27+
}
28+
29+
// Ensure that command line flag overrides the default timeout.
30+
const child1 = spawnSync(process.execPath, ['--http-server-default-timeout=10',
31+
'-p', 'http.createServer().timeout'
32+
]);
33+
assert.strictEqual(+child1.stdout.toString().trim(), 10);
34+
35+
// Ensure that the flag is whitelisted for NODE_OPTIONS.
36+
const env = Object.assign({}, process.env, {
37+
NODE_OPTIONS: '--http-server-default-timeout=10'
38+
});
39+
const child2 = spawnSync(process.execPath,
40+
[ '-p', 'http.createServer().timeout'], { env });
41+
assert.strictEqual(+child2.stdout.toString().trim(), 10);

0 commit comments

Comments
 (0)