diff --git a/doc/api/http.md b/doc/api/http.md index 9479ffdf814db4..039b83616f3a0c 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. diff --git a/lib/_http_server.js b/lib/_http_server.js index 900060d61137dc..86340e78877a04 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 && 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) 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(); + })); +}));