From df08d527c2083b852d8456b88b39114f30525236 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Thu, 14 May 2020 20:21:34 +0200 Subject: http: add requestTimeout This commits introduces a new http.Server option called requestTimeout with a default value in milliseconds of 0. If requestTimeout is set to a positive value, the server will start a new timer set to expire in requestTimeout milliseconds when a new connection is established. The timer is also set again if new requests after the first are received on the socket (this handles pipelining and keep-alive cases). The timer is cancelled when: 1. the request body is completely received by the server. 2. the response is completed. This handles the case where the application responds to the client without consuming the request body. 3. the connection is upgraded, like in the WebSocket case. If the timer expires, then the server responds with status code 408 and closes the connection. CVE-2020-8251 PR-URL: https://github.com/nodejs-private/node-private/pull/208 Reviewed-By: Franziska Hinkelmann Reviewed-By: James M Snell Reviewed-By: Robert Nagy Reviewed-By: Mary Marchini Co-Authored-By: Paolo Insogna Co-Authored-By: Robert Nagy --- doc/api/errors.md | 5 ++ doc/api/http.md | 17 ++++ doc/api/https.md | 10 +++ lib/_http_common.js | 8 ++ lib/_http_server.js | 85 ++++++++++++++++++- lib/https.js | 1 + lib/internal/errors.js | 1 + src/node_http_parser.cc | 28 +++++-- ...est-http-server-request-timeout-delayed-body.js | 62 ++++++++++++++ ...-http-server-request-timeout-delayed-headers.js | 48 +++++++++++ ...http-server-request-timeout-interrupted-body.js | 63 +++++++++++++++ ...p-server-request-timeout-interrupted-headers.js | 48 +++++++++++ .../test-http-server-request-timeout-keepalive.js | 94 ++++++++++++++++++++++ .../test-http-server-request-timeout-upgrade.js | 55 +++++++++++++ 14 files changed, 517 insertions(+), 8 deletions(-) create mode 100644 test/parallel/test-http-server-request-timeout-delayed-body.js create mode 100644 test/parallel/test-http-server-request-timeout-delayed-headers.js create mode 100644 test/parallel/test-http-server-request-timeout-interrupted-body.js create mode 100644 test/parallel/test-http-server-request-timeout-interrupted-headers.js create mode 100644 test/parallel/test-http-server-request-timeout-keepalive.js create mode 100644 test/parallel/test-http-server-request-timeout-upgrade.js diff --git a/doc/api/errors.md b/doc/api/errors.md index db56c571e9c..98ca5c17a8f 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -940,6 +940,11 @@ allowed size for a `Buffer`. An invalid symlink type was passed to the [`fs.symlink()`][] or [`fs.symlinkSync()`][] methods. + +### `ERR_HTTP_REQUEST_TIMEOUT` + +The client has not sent the entire request within the allowed time. + ### `ERR_HTTP_HEADERS_SENT` diff --git a/doc/api/http.md b/doc/api/http.md index e5871ef5a8c..8945ba3fda5 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -1259,6 +1259,23 @@ added: v0.7.0 Limits maximum incoming headers count. If set to 0, no limit will be applied. +### `server.requestTimeout` + + +* {number} **Default:** `0` + +Sets the timeout value in milliseconds for receiving the entire request from +the client. + +If the timeout expires, the server responds with status 408 without +forwarding the request to the request listener and then closes the connection. + +It must be set to a non-zero value (e.g. 120 seconds) to proctect against +potential Denial-of-Service attacks in case the server is deployed without a +reverse proxy in front. + ### `server.setTimeout([msecs][, callback])` + +* {number} **Default:** `0` + +See [`http.Server#requestTimeout`][]. + ### `server.setTimeout([msecs][, callback])`