@@ -62,6 +62,8 @@ pub struct HttpSession {
62
62
keepalive_timeout : KeepaliveStatus ,
63
63
read_timeout : Option < Duration > ,
64
64
write_timeout : Option < Duration > ,
65
+ /// How long to wait to make downstream session reusable, if body needs to be drained.
66
+ total_drain_timeout : Option < Duration > ,
65
67
/// A copy of the response that is already written to the client
66
68
response_written : Option < Box < ResponseHeader > > ,
67
69
/// The parsed request header
@@ -106,6 +108,7 @@ impl HttpSession {
106
108
request_header : None ,
107
109
read_timeout : None ,
108
110
write_timeout : None ,
111
+ total_drain_timeout : None ,
109
112
body_bytes_sent : 0 ,
110
113
body_bytes_read : 0 ,
111
114
retry_buffer : None ,
@@ -399,6 +402,30 @@ impl HttpSession {
399
402
}
400
403
}
401
404
405
+ async fn do_drain_request_body ( & mut self ) -> Result < ( ) > {
406
+ loop {
407
+ match self . read_body_bytes ( ) . await {
408
+ Ok ( Some ( _) ) => { /* continue to drain */ }
409
+ Ok ( None ) => return Ok ( ( ) ) , // done
410
+ Err ( e) => return Err ( e) ,
411
+ }
412
+ }
413
+ }
414
+
415
+ /// Drain the request body. `Ok(())` when there is no (more) body to read.
416
+ pub async fn drain_request_body ( & mut self ) -> Result < ( ) > {
417
+ if self . is_body_done ( ) {
418
+ return Ok ( ( ) ) ;
419
+ }
420
+ match self . total_drain_timeout {
421
+ Some ( t) => match timeout ( t, self . do_drain_request_body ( ) ) . await {
422
+ Ok ( res) => res,
423
+ Err ( _) => Error :: e_explain ( ReadTimedout , format ! ( "draining body, timeout: {t:?}" ) ) ,
424
+ } ,
425
+ None => self . do_drain_request_body ( ) . await ,
426
+ }
427
+ }
428
+
402
429
/// Whether there is no (more) body need to be read.
403
430
pub fn is_body_done ( & mut self ) -> bool {
404
431
self . init_body_reader ( ) ;
@@ -862,6 +889,18 @@ impl HttpSession {
862
889
self . write_timeout = Some ( timeout) ;
863
890
}
864
891
892
+ /// Sets the total drain timeout. For HTTP/1.1, reusing a session requires
893
+ /// ensuring that the request body is consumed. This `timeout` will be used
894
+ /// to determine how long to wait for the entirety of the downstream request
895
+ /// body to finish after the upstream response is completed to return the
896
+ /// session to the reuse pool. If the timeout is exceeded, we will give up
897
+ /// on trying to reuse the session.
898
+ ///
899
+ /// Note that the downstream read timeout still applies between body byte reads.
900
+ pub fn set_total_drain_timeout ( & mut self , timeout : Duration ) {
901
+ self . total_drain_timeout = Some ( timeout) ;
902
+ }
903
+
865
904
/// Sets the minimum downstream send rate in bytes per second. This
866
905
/// is used to calculate a write timeout in seconds based on the size
867
906
/// of the buffer being written. If a `min_send_rate` is configured it
@@ -911,19 +950,25 @@ impl HttpSession {
911
950
}
912
951
913
952
/// Consume `self`, if the connection can be reused, the underlying stream will be returned
914
- /// to be fed to the next [`Self::new()`]. The next session can just call [`Self::read_request()`].
953
+ /// to be fed to the next [`Self::new()`]. This drains any remaining request body if it hasn't
954
+ /// yet been read and the stream is reusable.
955
+ ///
956
+ /// The next session can just call [`Self::read_request()`].
957
+ ///
915
958
/// If the connection cannot be reused, the underlying stream will be closed and `None` will be
916
- /// returned.
917
- pub async fn reuse ( mut self ) -> Option < Stream > {
918
- // TODO: this function is unnecessarily slow for keepalive case
919
- // because that case does not need async
959
+ /// returned. If there was an error while draining any remaining request body that error will
960
+ /// be returned.
961
+ pub async fn reuse ( mut self ) -> Result < Option < Stream > > {
920
962
match self . keepalive_timeout {
921
963
KeepaliveStatus :: Off => {
922
964
debug ! ( "HTTP shutdown connection" ) ;
923
965
self . shutdown ( ) . await ;
924
- None
966
+ Ok ( None )
967
+ }
968
+ _ => {
969
+ self . drain_request_body ( ) . await ?;
970
+ Ok ( Some ( self . underlying_stream ) )
925
971
}
926
- _ => Some ( self . underlying_stream ) ,
927
972
}
928
973
}
929
974
0 commit comments