@@ -88,22 +88,32 @@ where
88
88
"Unexpected Content-Length header"
89
89
) ;
90
90
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 ) ;
92
96
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 ( ) ) {
94
98
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 {
96
102
io. write_all ( CONTINUE_RESPONSE ) . await . ok ( ) ;
97
103
} ;
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.
98
107
} ) ;
99
108
}
100
109
101
110
// Check for Transfer-Encoding
102
111
if let Some ( encoding) = transfer_encoding {
103
112
if encoding. last ( ) . as_str ( ) == "chunked" {
104
113
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) ;
107
117
req. set_body ( Body :: from_reader ( reader, None ) ) ;
108
118
return Ok ( Some ( req) ) ;
109
119
}
@@ -113,7 +123,7 @@ where
113
123
// Check for Content-Length.
114
124
if let Some ( len) = content_length {
115
125
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 ) ;
117
127
req. set_body ( Body :: from_reader ( reader, Some ( len) ) ) ;
118
128
}
119
129
0 commit comments