Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex R <alexei.rudenko@gmail.com>2019-10-31 01:33:33 +0300
committerMichaƫl Zasso <targos@protonmail.com>2020-04-11 11:01:16 +0300
commit8597df48f79408b0a72049197982c67e424552c0 (patch)
tree4e1af04636bddca37f6942047ae775e533bbe363 /src/node_http_parser.cc
parent4acd7f4390f4c73c14532fef1cb3e56911604935 (diff)
http: fix incorrect headersTimeout measurement
For keep-alive connections, the headersTimeout may fire during subsequent request because the measurement was reset after a request and not before a request. PR-URL: https://github.com/nodejs/node/pull/32329 Fixes: https://github.com/nodejs/node/issues/27363 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src/node_http_parser.cc')
-rw-r--r--src/node_http_parser.cc37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc
index 75d7e89a91c..2c75e6a532f 100644
--- a/src/node_http_parser.cc
+++ b/src/node_http_parser.cc
@@ -74,6 +74,7 @@ const uint32_t kOnHeadersComplete = 1;
const uint32_t kOnBody = 2;
const uint32_t kOnMessageComplete = 3;
const uint32_t kOnExecute = 4;
+const uint32_t kOnTimeout = 5;
// Any more fields than this will be flushed into JS
const size_t kMaxHeaderFieldsCount = 32;
@@ -181,6 +182,7 @@ class Parser : public AsyncWrap, public StreamListener {
num_fields_ = num_values_ = 0;
url_.Reset();
status_message_.Reset();
+ header_parsing_start_time_ = uv_hrtime();
return 0;
}
@@ -504,6 +506,7 @@ class Parser : public AsyncWrap, public StreamListener {
bool lenient = args[3]->IsTrue();
uint64_t max_http_header_size = 0;
+ uint64_t headers_timeout = 0;
CHECK(args[0]->IsInt32());
CHECK(args[1]->IsObject());
@@ -516,6 +519,11 @@ class Parser : public AsyncWrap, public StreamListener {
max_http_header_size = env->options()->max_http_header_size;
}
+ if (args.Length() > 4) {
+ CHECK(args[4]->IsInt32());
+ headers_timeout = args[4].As<Number>()->Value();
+ }
+
llhttp_type_t type =
static_cast<llhttp_type_t>(args[0].As<Int32>()->Value());
@@ -532,7 +540,7 @@ class Parser : public AsyncWrap, public StreamListener {
parser->set_provider_type(provider);
parser->AsyncReset(args[1].As<Object>());
- parser->Init(type, max_http_header_size, lenient);
+ parser->Init(type, max_http_header_size, lenient, headers_timeout);
}
template <bool should_pause>
@@ -636,6 +644,24 @@ class Parser : public AsyncWrap, public StreamListener {
if (ret.IsEmpty())
return;
+ // check header parsing time
+ if (header_parsing_start_time_ != 0 && headers_timeout_ != 0) {
+ uint64_t now = uv_hrtime();
+ uint64_t parsing_time = (now - header_parsing_start_time_) / 1e6;
+
+ if (parsing_time > headers_timeout_) {
+ Local<Value> cb =
+ object()->Get(env()->context(), kOnTimeout).ToLocalChecked();
+
+ if (!cb->IsFunction())
+ return;
+
+ MakeCallback(cb.As<Function>(), 0, nullptr);
+
+ return;
+ }
+ }
+
Local<Value> cb =
object()->Get(env()->context(), kOnExecute).ToLocalChecked();
@@ -779,7 +805,8 @@ class Parser : public AsyncWrap, public StreamListener {
}
- void Init(llhttp_type_t type, uint64_t max_http_header_size, bool lenient) {
+ void Init(llhttp_type_t type, uint64_t max_http_header_size,
+ bool lenient, uint64_t headers_timeout) {
llhttp_init(&parser_, type, &settings);
llhttp_set_lenient(&parser_, lenient);
header_nread_ = 0;
@@ -790,6 +817,8 @@ class Parser : public AsyncWrap, public StreamListener {
have_flushed_ = false;
got_exception_ = false;
max_http_header_size_ = max_http_header_size;
+ header_parsing_start_time_ = 0;
+ headers_timeout_ = headers_timeout;
}
@@ -831,6 +860,8 @@ class Parser : public AsyncWrap, public StreamListener {
bool pending_pause_ = false;
uint64_t header_nread_ = 0;
uint64_t max_http_header_size_;
+ uint64_t headers_timeout_;
+ uint64_t header_parsing_start_time_ = 0;
// These are helper functions for filling `http_parser_settings`, which turn
// a member function of Parser into a C-style HTTP parser callback.
@@ -890,6 +921,8 @@ void InitializeHttpParser(Local<Object> target,
Integer::NewFromUnsigned(env->isolate(), kOnMessageComplete));
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnExecute"),
Integer::NewFromUnsigned(env->isolate(), kOnExecute));
+ t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnTimeout"),
+ Integer::NewFromUnsigned(env->isolate(), kOnTimeout));
Local<Array> methods = Array::New(env->isolate());
#define V(num, name, string) \