From 87e26dc978d951e4ec3d8f8c10a6f51df7b06692 Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Wed, 29 Apr 2020 09:25:09 +0200 Subject: [PATCH 1/4] http: disable headersTimeout check when set to zero --- lib/_http_server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/_http_server.js b/lib/_http_server.js index d43c1bfb63d67b..f20e70940ef12b 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -572,7 +572,7 @@ function onParserExecute(server, socket, parser, state, ret) { // If we have not parsed the headers, destroy the socket // after server.headersTimeout to protect from DoS attacks. // start === 0 means that we have parsed headers. - if (start !== 0 && nowDate() - start > server.headersTimeout) { + if (start !== 0 && server.headersTimeout && nowDate() - start > server.headersTimeout) { const serverTimeout = server.emit('timeout', socket); if (!serverTimeout) From 563692bbb725d7b00c56f50f9618ee72f9d79ba2 Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Wed, 29 Apr 2020 09:27:26 +0200 Subject: [PATCH 2/4] doc: updated headersTimeout documentation --- doc/api/http.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/api/http.md b/doc/api/http.md index be4642177a73c0..5a76022c0b9fd1 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -1122,6 +1122,8 @@ event is emitted on the server object, and (by default) the socket is destroyed. See [`server.timeout`][] for more information on how timeout behavior can be customized. +A value of `0` will disable the HTTP headers timeout check. + ### `server.listen()` Starts the HTTP server listening for connections. From 2eb7c2e1a2aa185cf1f68a6b5c7891baf577c354 Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Fri, 8 May 2020 12:18:33 +0200 Subject: [PATCH 3/4] lint: fix failures --- lib/_http_server.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/_http_server.js b/lib/_http_server.js index f20e70940ef12b..7b80e6ddb12d3c 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -571,8 +571,12 @@ function onParserExecute(server, socket, parser, state, ret) { // If we have not parsed the headers, destroy the socket // after server.headersTimeout to protect from DoS attacks. - // start === 0 means that we have parsed headers. - if (start !== 0 && server.headersTimeout && nowDate() - start > server.headersTimeout) { + // start === 0 means that we have parsed headers, while + // server.headersTimeout === 0 means user disabled this check. + if ( + start !== 0 && server.headersTimeout && + nowDate() - start > server.headersTimeout + ) { const serverTimeout = server.emit('timeout', socket); if (!serverTimeout) From 31cfa4d0bc2084b5f15092d5079667a2e8f69d18 Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Mon, 11 May 2020 09:39:09 +0200 Subject: [PATCH 4/4] test: add test for disabled headersTimeout --- ...st-http-server-disabled-headers-timeout.js | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 test/parallel/test-http-server-disabled-headers-timeout.js diff --git a/test/parallel/test-http-server-disabled-headers-timeout.js b/test/parallel/test-http-server-disabled-headers-timeout.js new file mode 100644 index 00000000000000..905e589cbe71eb --- /dev/null +++ b/test/parallel/test-http-server-disabled-headers-timeout.js @@ -0,0 +1,49 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { createServer } = require('http'); +const { connect } = require('net'); + +// This test verifies that it is possible to disable +// headersTimeout by setting it to zero. + +const server = createServer(common.mustCall((req, res) => { + res.writeHead(200); + res.end('OK'); +})); + +server.headersTimeout = 0; + +server.once('timeout', common.mustNotCall((socket) => { + socket.destroy(); +})); + +server.listen(0, common.mustCall(() => { + const client = connect(server.address().port); + let response = ''; + + client.resume(); + client.write('GET / HTTP/1.1\r\nConnection: close\r\n'); + + // All the timeouts below must be greater than a second, otherwise + // headersTimeout won't be triggered anyway as the current date is cached + // for a second in HTTP internals. + setTimeout(() => { + client.write('X-Crash: Ab: 456\r\n'); + }, common.platformTimeout(1100)).unref(); + + setTimeout(() => { + client.write('\r\n'); + }, common.platformTimeout(1200)).unref(); + + client.on('data', (chunk) => { + response += chunk.toString('utf-8'); + }); + + client.on('end', common.mustCall(() => { + assert.strictEqual(response.split('\r\n').shift(), 'HTTP/1.1 200 OK'); + client.end(); + server.close(); + })); +}));