@@ -74,6 +74,7 @@ const uint32_t kOnHeadersComplete = 1;
74
74
const uint32_t kOnBody = 2 ;
75
75
const uint32_t kOnMessageComplete = 3 ;
76
76
const uint32_t kOnExecute = 4 ;
77
+ const uint32_t kOnTimeout = 5 ;
77
78
// Any more fields than this will be flushed into JS
78
79
const size_t kMaxHeaderFieldsCount = 32 ;
79
80
@@ -181,6 +182,7 @@ class Parser : public AsyncWrap, public StreamListener {
181
182
num_fields_ = num_values_ = 0 ;
182
183
url_.Reset ();
183
184
status_message_.Reset ();
185
+ header_parsing_start_time_ = uv_hrtime ();
184
186
return 0 ;
185
187
}
186
188
@@ -504,6 +506,7 @@ class Parser : public AsyncWrap, public StreamListener {
504
506
bool lenient = args[3 ]->IsTrue ();
505
507
506
508
uint64_t max_http_header_size = 0 ;
509
+ uint64_t headers_timeout = 0 ;
507
510
508
511
CHECK (args[0 ]->IsInt32 ());
509
512
CHECK (args[1 ]->IsObject ());
@@ -516,6 +519,11 @@ class Parser : public AsyncWrap, public StreamListener {
516
519
max_http_header_size = env->options ()->max_http_header_size ;
517
520
}
518
521
522
+ if (args.Length () > 4 ) {
523
+ CHECK (args[4 ]->IsInt32 ());
524
+ headers_timeout = args[4 ].As <Number>()->Value ();
525
+ }
526
+
519
527
llhttp_type_t type =
520
528
static_cast <llhttp_type_t >(args[0 ].As <Int32>()->Value ());
521
529
@@ -532,7 +540,7 @@ class Parser : public AsyncWrap, public StreamListener {
532
540
533
541
parser->set_provider_type (provider);
534
542
parser->AsyncReset (args[1 ].As <Object>());
535
- parser->Init (type, max_http_header_size, lenient);
543
+ parser->Init (type, max_http_header_size, lenient, headers_timeout );
536
544
}
537
545
538
546
template <bool should_pause>
@@ -636,6 +644,24 @@ class Parser : public AsyncWrap, public StreamListener {
636
644
if (ret.IsEmpty ())
637
645
return ;
638
646
647
+ // check header parsing time
648
+ if (header_parsing_start_time_ != 0 && headers_timeout_ != 0 ) {
649
+ uint64_t now = uv_hrtime ();
650
+ uint64_t parsing_time = (now - header_parsing_start_time_) / 1e6 ;
651
+
652
+ if (parsing_time > headers_timeout_) {
653
+ Local<Value> cb =
654
+ object ()->Get (env ()->context (), kOnTimeout ).ToLocalChecked ();
655
+
656
+ if (!cb->IsFunction ())
657
+ return ;
658
+
659
+ MakeCallback (cb.As <Function>(), 0 , nullptr );
660
+
661
+ return ;
662
+ }
663
+ }
664
+
639
665
Local<Value> cb =
640
666
object ()->Get (env ()->context (), kOnExecute ).ToLocalChecked ();
641
667
@@ -779,7 +805,8 @@ class Parser : public AsyncWrap, public StreamListener {
779
805
}
780
806
781
807
782
- void Init (llhttp_type_t type, uint64_t max_http_header_size, bool lenient) {
808
+ void Init (llhttp_type_t type, uint64_t max_http_header_size,
809
+ bool lenient, uint64_t headers_timeout) {
783
810
llhttp_init (&parser_, type, &settings);
784
811
llhttp_set_lenient (&parser_, lenient);
785
812
header_nread_ = 0 ;
@@ -790,6 +817,8 @@ class Parser : public AsyncWrap, public StreamListener {
790
817
have_flushed_ = false ;
791
818
got_exception_ = false ;
792
819
max_http_header_size_ = max_http_header_size;
820
+ header_parsing_start_time_ = 0 ;
821
+ headers_timeout_ = headers_timeout;
793
822
}
794
823
795
824
@@ -831,6 +860,8 @@ class Parser : public AsyncWrap, public StreamListener {
831
860
bool pending_pause_ = false ;
832
861
uint64_t header_nread_ = 0 ;
833
862
uint64_t max_http_header_size_;
863
+ uint64_t headers_timeout_;
864
+ uint64_t header_parsing_start_time_ = 0 ;
834
865
835
866
// These are helper functions for filling `http_parser_settings`, which turn
836
867
// a member function of Parser into a C-style HTTP parser callback.
@@ -890,6 +921,8 @@ void InitializeHttpParser(Local<Object> target,
890
921
Integer::NewFromUnsigned (env->isolate (), kOnMessageComplete ));
891
922
t->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " kOnExecute" ),
892
923
Integer::NewFromUnsigned (env->isolate (), kOnExecute ));
924
+ t->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " kOnTimeout" ),
925
+ Integer::NewFromUnsigned (env->isolate (), kOnTimeout ));
893
926
894
927
Local<Array> methods = Array::New (env->isolate ());
895
928
#define V (num, name, string ) \
0 commit comments