@@ -3,10 +3,15 @@ use std::fmt;
33use std:: io:: { self , IoSlice } ;
44use std:: marker:: Unpin ;
55use std:: mem:: MaybeUninit ;
6+ use std:: future:: Future ;
7+ #[ cfg( all( feature = "server" , feature = "runtime" ) ) ]
8+ use std:: time:: Duration ;
69
10+ #[ cfg( all( feature = "server" , feature = "runtime" ) ) ]
11+ use tokio:: time:: Instant ;
712use bytes:: { Buf , BufMut , Bytes , BytesMut } ;
813use tokio:: io:: { AsyncRead , AsyncWrite , ReadBuf } ;
9- use tracing:: { debug, trace} ;
14+ use tracing:: { debug, warn , trace} ;
1015
1116use super :: { Http1Transaction , ParseContext , ParsedMessage } ;
1217use crate :: common:: buf:: BufList ;
@@ -181,6 +186,12 @@ where
181186 cached_headers : parse_ctx. cached_headers ,
182187 req_method : parse_ctx. req_method ,
183188 h1_parser_config : parse_ctx. h1_parser_config . clone ( ) ,
189+ #[ cfg( all( feature = "server" , feature = "runtime" ) ) ]
190+ h1_header_read_timeout : parse_ctx. h1_header_read_timeout ,
191+ #[ cfg( all( feature = "server" , feature = "runtime" ) ) ]
192+ h1_header_read_timeout_fut : parse_ctx. h1_header_read_timeout_fut ,
193+ #[ cfg( all( feature = "server" , feature = "runtime" ) ) ]
194+ h1_header_read_timeout_running : parse_ctx. h1_header_read_timeout_running ,
184195 preserve_header_case : parse_ctx. preserve_header_case ,
185196 h09_responses : parse_ctx. h09_responses ,
186197 #[ cfg( feature = "ffi" ) ]
@@ -191,6 +202,16 @@ where
191202 ) ? {
192203 Some ( msg) => {
193204 debug ! ( "parsed {} headers" , msg. head. headers. len( ) ) ;
205+
206+ #[ cfg( all( feature = "server" , feature = "runtime" ) ) ]
207+ {
208+ * parse_ctx. h1_header_read_timeout_running = false ;
209+
210+ if let Some ( h1_header_read_timeout_fut) = parse_ctx. h1_header_read_timeout_fut {
211+ // Reset the timer in order to avoid woken up when the timeout finishes
212+ h1_header_read_timeout_fut. as_mut ( ) . reset ( Instant :: now ( ) + Duration :: from_secs ( 30 * 24 * 60 * 60 ) ) ;
213+ }
214+ }
194215 return Poll :: Ready ( Ok ( msg) ) ;
195216 }
196217 None => {
@@ -199,6 +220,18 @@ where
199220 debug ! ( "max_buf_size ({}) reached, closing" , max) ;
200221 return Poll :: Ready ( Err ( crate :: Error :: new_too_large ( ) ) ) ;
201222 }
223+
224+ #[ cfg( all( feature = "server" , feature = "runtime" ) ) ]
225+ if * parse_ctx. h1_header_read_timeout_running {
226+ if let Some ( h1_header_read_timeout_fut) = parse_ctx. h1_header_read_timeout_fut {
227+ if Pin :: new ( h1_header_read_timeout_fut) . poll ( cx) . is_ready ( ) {
228+ * parse_ctx. h1_header_read_timeout_running = false ;
229+
230+ warn ! ( "read header from client timeout" ) ;
231+ return Poll :: Ready ( Err ( crate :: Error :: new_header_timeout ( ) ) )
232+ }
233+ }
234+ }
202235 }
203236 }
204237 if ready ! ( self . poll_read_from_io( cx) ) . map_err ( crate :: Error :: new_io) ? == 0 {
@@ -693,6 +726,9 @@ mod tests {
693726 cached_headers : & mut None ,
694727 req_method : & mut None ,
695728 h1_parser_config : Default :: default ( ) ,
729+ h1_header_read_timeout : None ,
730+ h1_header_read_timeout_fut : & mut None ,
731+ h1_header_read_timeout_running : & mut false ,
696732 preserve_header_case : false ,
697733 h09_responses : false ,
698734 #[ cfg( feature = "ffi" ) ]
0 commit comments