@@ -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 ,
@@ -61,6 +62,7 @@ const {
61
62
codes
62
63
} = require ( 'internal/errors' ) ;
63
64
const {
65
+ ERR_HTTP_REQUEST_TIMEOUT ,
64
66
ERR_HTTP_HEADERS_SENT ,
65
67
ERR_HTTP_INVALID_STATUS_CODE ,
66
68
ERR_HTTP_SOCKET_ENCODING ,
@@ -77,6 +79,7 @@ const {
77
79
DTRACE_HTTP_SERVER_RESPONSE
78
80
} = require ( 'internal/dtrace' ) ;
79
81
const { observerCounts, constants } = internalBinding ( 'performance' ) ;
82
+ const { setTimeout, clearTimeout } = require ( 'timers' ) ;
80
83
const { NODE_PERFORMANCE_ENTRY_TYPE_HTTP } = constants ;
81
84
82
85
const kServerResponse = Symbol ( 'ServerResponse' ) ;
@@ -148,6 +151,7 @@ const STATUS_CODES = {
148
151
511 : 'Network Authentication Required' // RFC 6585 6
149
152
} ;
150
153
154
+ const kOnMessageBegin = HTTPParser . kOnMessageBegin | 0 ;
151
155
const kOnExecute = HTTPParser . kOnExecute | 0 ;
152
156
const kOnTimeout = HTTPParser . kOnTimeout | 0 ;
153
157
@@ -369,6 +373,7 @@ function Server(options, requestListener) {
369
373
this . keepAliveTimeout = 5000 ;
370
374
this . maxHeadersCount = null ;
371
375
this . headersTimeout = 60 * 1000 ; // 60 seconds
376
+ this . requestTimeout = 0 ; // 120 seconds
372
377
}
373
378
ObjectSetPrototypeOf ( Server . prototype , net . Server . prototype ) ;
374
379
ObjectSetPrototypeOf ( Server , net . Server ) ;
@@ -491,6 +496,16 @@ function connectionListenerInternal(server, socket) {
491
496
parser [ kOnTimeout ] =
492
497
onParserTimeout . bind ( undefined , server , socket ) ;
493
498
499
+ // When receiving new requests on the same socket (pipelining or keep alive)
500
+ // make sure the requestTimeout is active.
501
+ parser [ kOnMessageBegin ] =
502
+ setRequestTimeout . bind ( undefined , server , socket ) ;
503
+
504
+ // This protects from DOS attack where an attacker establish the connection
505
+ // without sending any data on applications where server.timeout is left to
506
+ // the default value of zero.
507
+ setRequestTimeout ( server , socket ) ;
508
+
494
509
socket . _paused = false ;
495
510
}
496
511
@@ -586,6 +601,11 @@ function socketOnData(server, socket, parser, state, d) {
586
601
onParserExecuteCommon ( server , socket , parser , state , ret , d ) ;
587
602
}
588
603
604
+ function onRequestTimeout ( socket ) {
605
+ socket [ kRequestTimeout ] = undefined ;
606
+ socketOnError . call ( socket , new ERR_HTTP_REQUEST_TIMEOUT ( ) ) ;
607
+ }
608
+
589
609
function onParserExecute ( server , socket , parser , state , ret ) {
590
610
// When underlying `net.Socket` instance is consumed - no
591
611
// `data` events are emitted, and thus `socket.setTimeout` fires the
@@ -608,6 +628,10 @@ const badRequestResponse = Buffer.from(
608
628
`HTTP/1.1 400 ${ STATUS_CODES [ 400 ] } ${ CRLF } ` +
609
629
`Connection: close${ CRLF } ${ CRLF } ` , 'ascii'
610
630
) ;
631
+ const requestTimeoutResponse = Buffer . from (
632
+ `HTTP/1.1 408 ${ STATUS_CODES [ 408 ] } ${ CRLF } ` +
633
+ `Connection: close${ CRLF } ${ CRLF } ` , 'ascii'
634
+ ) ;
611
635
const requestHeaderFieldsTooLargeResponse = Buffer . from (
612
636
`HTTP/1.1 431 ${ STATUS_CODES [ 431 ] } ${ CRLF } ` +
613
637
`Connection: close${ CRLF } ${ CRLF } ` , 'ascii'
@@ -619,8 +643,20 @@ function socketOnError(e) {
619
643
620
644
if ( ! this . server . emit ( 'clientError' , e , this ) ) {
621
645
if ( this . writable && this . bytesWritten === 0 ) {
622
- const response = e . code === 'HPE_HEADER_OVERFLOW' ?
623
- requestHeaderFieldsTooLargeResponse : badRequestResponse ;
646
+ let response ;
647
+
648
+ switch ( e . code ) {
649
+ case 'HPE_HEADER_OVERFLOW' :
650
+ response = requestHeaderFieldsTooLargeResponse ;
651
+ break ;
652
+ case 'ERR_HTTP_REQUEST_TIMEOUT' :
653
+ response = requestTimeoutResponse ;
654
+ break ;
655
+ default :
656
+ response = badRequestResponse ;
657
+ break ;
658
+ }
659
+
624
660
this . write ( response ) ;
625
661
}
626
662
this . destroy ( e ) ;
@@ -660,11 +696,20 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
660
696
const bodyHead = d . slice ( ret , d . length ) ;
661
697
662
698
socket . readableFlowing = null ;
699
+
700
+ // Clear the requestTimeout after upgrading the connection.
701
+ clearRequestTimeout ( req ) ;
702
+
663
703
server . emit ( eventName , req , socket , bodyHead ) ;
664
704
} else {
665
705
// Got CONNECT method, but have no handler.
666
706
socket . destroy ( ) ;
667
707
}
708
+ } else {
709
+ // When receiving new requests on the same socket (pipelining or keep alive)
710
+ // make sure the requestTimeout is active.
711
+ parser [ kOnMessageBegin ] =
712
+ setRequestTimeout . bind ( undefined , server , socket ) ;
668
713
}
669
714
670
715
if ( socket . _paused && socket . parser ) {
@@ -692,6 +737,32 @@ function clearIncoming(req) {
692
737
}
693
738
}
694
739
740
+ function setRequestTimeout ( server , socket ) {
741
+ // Set the request timeout handler.
742
+ if (
743
+ ! socket [ kRequestTimeout ] &&
744
+ server . requestTimeout && server . requestTimeout > 0
745
+ ) {
746
+ debug ( 'requestTimeout timer set' ) ;
747
+ socket [ kRequestTimeout ] =
748
+ setTimeout ( onRequestTimeout , server . requestTimeout , socket ) . unref ( ) ;
749
+ }
750
+ }
751
+
752
+ function clearRequestTimeout ( req ) {
753
+ if ( ! req ) {
754
+ req = this ;
755
+ }
756
+
757
+ if ( ! req [ kRequestTimeout ] ) {
758
+ return ;
759
+ }
760
+
761
+ debug ( 'requestTimeout timer cleared' ) ;
762
+ clearTimeout ( req [ kRequestTimeout ] ) ;
763
+ req [ kRequestTimeout ] = undefined ;
764
+ }
765
+
695
766
function resOnFinish ( req , res , socket , state , server ) {
696
767
// Usually the first incoming element should be our request. it may
697
768
// be that in the case abortIncoming() was called that the incoming
@@ -706,6 +777,14 @@ function resOnFinish(req, res, socket, state, server) {
706
777
if ( ! req . _consuming && ! req . _readableState . resumeScheduled )
707
778
req . _dump ( ) ;
708
779
780
+ // Make sure the requestTimeout is cleared before finishing.
781
+ // This might occur if the application has sent a response
782
+ // without consuming the request body, which would have alredy
783
+ // cleared the timer.
784
+ // clearRequestTimeout can be executed even if the timer is not active,
785
+ // so this is safe.
786
+ clearRequestTimeout ( req ) ;
787
+
709
788
res . detachSocket ( socket ) ;
710
789
clearIncoming ( req ) ;
711
790
process . nextTick ( emitCloseNT , res ) ;
@@ -802,6 +881,8 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
802
881
res . end ( ) ;
803
882
}
804
883
} else {
884
+ req . on ( 'end' , clearRequestTimeout ) ;
885
+
805
886
server . emit ( 'request' , req , res ) ;
806
887
}
807
888
return 0 ; // No special treatment.
0 commit comments