@@ -40,6 +40,7 @@ const {
40
40
continueExpression,
41
41
chunkExpression,
42
42
kIncomingMessage,
43
+ kRequestTimeout,
43
44
HTTPParser,
44
45
isLenient,
45
46
_checkInvalidHeaderChar : checkInvalidHeaderChar ,
@@ -57,6 +58,7 @@ const {
57
58
} = require ( 'internal/async_hooks' ) ;
58
59
const { IncomingMessage } = require ( '_http_incoming' ) ;
59
60
const {
61
+ ERR_HTTP_REQUEST_TIMEOUT ,
60
62
ERR_HTTP_HEADERS_SENT ,
61
63
ERR_HTTP_INVALID_STATUS_CODE ,
62
64
ERR_INVALID_ARG_TYPE ,
@@ -72,6 +74,7 @@ const {
72
74
DTRACE_HTTP_SERVER_RESPONSE
73
75
} = require ( 'internal/dtrace' ) ;
74
76
const { observerCounts, constants } = internalBinding ( 'performance' ) ;
77
+ const { setTimeout, clearTimeout } = require ( 'timers' ) ;
75
78
const { NODE_PERFORMANCE_ENTRY_TYPE_HTTP } = constants ;
76
79
77
80
const kServerResponse = Symbol ( 'ServerResponse' ) ;
@@ -143,6 +146,7 @@ const STATUS_CODES = {
143
146
511 : 'Network Authentication Required' // RFC 6585 6
144
147
} ;
145
148
149
+ const kOnMessageBegin = HTTPParser . kOnMessageBegin | 0 ;
146
150
const kOnExecute = HTTPParser . kOnExecute | 0 ;
147
151
const kOnTimeout = HTTPParser . kOnTimeout | 0 ;
148
152
@@ -360,6 +364,7 @@ function Server(options, requestListener) {
360
364
this . keepAliveTimeout = 5000 ;
361
365
this . maxHeadersCount = null ;
362
366
this . headersTimeout = 60 * 1000 ; // 60 seconds
367
+ this . requestTimeout = 0 ; // 120 seconds
363
368
}
364
369
ObjectSetPrototypeOf ( Server . prototype , net . Server . prototype ) ;
365
370
ObjectSetPrototypeOf ( Server , net . Server ) ;
@@ -481,6 +486,16 @@ function connectionListenerInternal(server, socket) {
481
486
parser [ kOnTimeout ] =
482
487
onParserTimeout . bind ( undefined , server , socket ) ;
483
488
489
+ // When receiving new requests on the same socket (pipelining or keep alive)
490
+ // make sure the requestTimeout is active.
491
+ parser [ kOnMessageBegin ] =
492
+ setRequestTimeout . bind ( undefined , server , socket ) ;
493
+
494
+ // This protects from DOS attack where an attacker establish the connection
495
+ // without sending any data on applications where server.timeout is left to
496
+ // the default value of zero.
497
+ setRequestTimeout ( server , socket ) ;
498
+
484
499
socket . _paused = false ;
485
500
}
486
501
@@ -567,6 +582,11 @@ function socketOnData(server, socket, parser, state, d) {
567
582
onParserExecuteCommon ( server , socket , parser , state , ret , d ) ;
568
583
}
569
584
585
+ function onRequestTimeout ( socket ) {
586
+ socket [ kRequestTimeout ] = undefined ;
587
+ socketOnError . call ( socket , new ERR_HTTP_REQUEST_TIMEOUT ( ) ) ;
588
+ }
589
+
570
590
function onParserExecute ( server , socket , parser , state , ret ) {
571
591
// When underlying `net.Socket` instance is consumed - no
572
592
// `data` events are emitted, and thus `socket.setTimeout` fires the
@@ -589,6 +609,10 @@ const badRequestResponse = Buffer.from(
589
609
`HTTP/1.1 400 ${ STATUS_CODES [ 400 ] } ${ CRLF } ` +
590
610
`Connection: close${ CRLF } ${ CRLF } ` , 'ascii'
591
611
) ;
612
+ const requestTimeoutResponse = Buffer . from (
613
+ `HTTP/1.1 408 ${ STATUS_CODES [ 408 ] } ${ CRLF } ` +
614
+ `Connection: close${ CRLF } ${ CRLF } ` , 'ascii'
615
+ ) ;
592
616
const requestHeaderFieldsTooLargeResponse = Buffer . from (
593
617
`HTTP/1.1 431 ${ STATUS_CODES [ 431 ] } ${ CRLF } ` +
594
618
`Connection: close${ CRLF } ${ CRLF } ` , 'ascii'
@@ -600,8 +624,20 @@ function socketOnError(e) {
600
624
601
625
if ( ! this . server . emit ( 'clientError' , e , this ) ) {
602
626
if ( this . writable && this . bytesWritten === 0 ) {
603
- const response = e . code === 'HPE_HEADER_OVERFLOW' ?
604
- requestHeaderFieldsTooLargeResponse : badRequestResponse ;
627
+ let response ;
628
+
629
+ switch ( e . code ) {
630
+ case 'HPE_HEADER_OVERFLOW' :
631
+ response = requestHeaderFieldsTooLargeResponse ;
632
+ break ;
633
+ case 'ERR_HTTP_REQUEST_TIMEOUT' :
634
+ response = requestTimeoutResponse ;
635
+ break ;
636
+ default :
637
+ response = badRequestResponse ;
638
+ break ;
639
+ }
640
+
605
641
this . write ( response ) ;
606
642
}
607
643
this . destroy ( e ) ;
@@ -641,11 +677,20 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
641
677
const bodyHead = d . slice ( ret , d . length ) ;
642
678
643
679
socket . readableFlowing = null ;
680
+
681
+ // Clear the requestTimeout after upgrading the connection.
682
+ clearRequestTimeout ( req ) ;
683
+
644
684
server . emit ( eventName , req , socket , bodyHead ) ;
645
685
} else {
646
686
// Got CONNECT method, but have no handler.
647
687
socket . destroy ( ) ;
648
688
}
689
+ } else {
690
+ // When receiving new requests on the same socket (pipelining or keep alive)
691
+ // make sure the requestTimeout is active.
692
+ parser [ kOnMessageBegin ] =
693
+ setRequestTimeout . bind ( undefined , server , socket ) ;
649
694
}
650
695
651
696
if ( socket . _paused && socket . parser ) {
@@ -671,6 +716,32 @@ function clearIncoming(req) {
671
716
}
672
717
}
673
718
719
+ function setRequestTimeout ( server , socket ) {
720
+ // Set the request timeout handler.
721
+ if (
722
+ ! socket [ kRequestTimeout ] &&
723
+ server . requestTimeout && server . requestTimeout > 0
724
+ ) {
725
+ debug ( 'requestTimeout timer set' ) ;
726
+ socket [ kRequestTimeout ] =
727
+ setTimeout ( onRequestTimeout , server . requestTimeout , socket ) . unref ( ) ;
728
+ }
729
+ }
730
+
731
+ function clearRequestTimeout ( req ) {
732
+ if ( ! req ) {
733
+ req = this ;
734
+ }
735
+
736
+ if ( ! req [ kRequestTimeout ] ) {
737
+ return ;
738
+ }
739
+
740
+ debug ( 'requestTimeout timer cleared' ) ;
741
+ clearTimeout ( req [ kRequestTimeout ] ) ;
742
+ req [ kRequestTimeout ] = undefined ;
743
+ }
744
+
674
745
function resOnFinish ( req , res , socket , state , server ) {
675
746
// Usually the first incoming element should be our request. it may
676
747
// be that in the case abortIncoming() was called that the incoming
@@ -685,6 +756,14 @@ function resOnFinish(req, res, socket, state, server) {
685
756
if ( ! req . _consuming && ! req . _readableState . resumeScheduled )
686
757
req . _dump ( ) ;
687
758
759
+ // Make sure the requestTimeout is cleared before finishing.
760
+ // This might occur if the application has sent a response
761
+ // without consuming the request body, which would have alredy
762
+ // cleared the timer.
763
+ // clearRequestTimeout can be executed even if the timer is not active,
764
+ // so this is safe.
765
+ clearRequestTimeout ( req ) ;
766
+
688
767
res . detachSocket ( socket ) ;
689
768
clearIncoming ( req ) ;
690
769
process . nextTick ( emitCloseNT , res ) ;
@@ -779,6 +858,8 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
779
858
res . end ( ) ;
780
859
}
781
860
} else {
861
+ req . on ( 'end' , clearRequestTimeout ) ;
862
+
782
863
server . emit ( 'request' , req , res ) ;
783
864
}
784
865
return 0 ; // No special treatment.
0 commit comments