@@ -88,22 +88,32 @@ where
8888 "Unexpected Content-Length header"
8989 ) ;
9090
91- let ( sender, receiver) = sync:: channel ( 1 ) ;
91+ // Establish a channel to wait for the body to be read. This
92+ // allows us to avoid sending 100-continue in situations that
93+ // respond without reading the body, saving clients from uploading
94+ // their body.
95+ let ( body_read_sender, body_read_receiver) = sync:: channel ( 1 ) ;
9296
93- if let Some ( CONTINUE_HEADER_VALUE ) = req. header ( EXPECT ) . map ( |h| h. as_str ( ) ) {
97+ if Some ( CONTINUE_HEADER_VALUE ) = = req. header ( EXPECT ) . map ( |h| h. as_str ( ) ) {
9498 task:: spawn ( async move {
95- if let Ok ( ( ) ) = receiver. recv ( ) . await {
99+ // If the client expects a 100-continue header, spawn a
100+ // task to wait for the first read attempt on the body.
101+ if let Ok ( ( ) ) = body_read_receiver. recv ( ) . await {
96102 io. write_all ( CONTINUE_RESPONSE ) . await . ok ( ) ;
97103 } ;
104+ // Since the sender is moved into the Body, this task will
105+ // finish when the client disconnects, whether or not
106+ // 100-continue was sent.
98107 } ) ;
99108 }
100109
101110 // Check for Transfer-Encoding
102111 if let Some ( encoding) = transfer_encoding {
103112 if encoding. last ( ) . as_str ( ) == "chunked" {
104113 let trailer_sender = req. send_trailers ( ) ;
105- let reader = BufReader :: new ( ChunkedDecoder :: new ( reader, trailer_sender) ) ;
106- let reader = ReadNotifier :: new ( reader, sender) ;
114+ let reader = ChunkedDecoder :: new ( reader, trailer_sender) ;
115+ let reader = BufReader :: new ( reader) ;
116+ let reader = ReadNotifier :: new ( reader, body_read_sender) ;
107117 req. set_body ( Body :: from_reader ( reader, None ) ) ;
108118 return Ok ( Some ( req) ) ;
109119 }
@@ -113,7 +123,7 @@ where
113123 // Check for Content-Length.
114124 if let Some ( len) = content_length {
115125 let len = len. last ( ) . as_str ( ) . parse :: < usize > ( ) ?;
116- let reader = ReadNotifier :: new ( reader. take ( len as u64 ) , sender ) ;
126+ let reader = ReadNotifier :: new ( reader. take ( len as u64 ) , body_read_sender ) ;
117127 req. set_body ( Body :: from_reader ( reader, Some ( len) ) ) ;
118128 }
119129
0 commit comments