@@ -5,7 +5,8 @@ use std::str::FromStr;
55use async_dup:: { Arc , Mutex } ;
66use async_std:: io:: { BufReader , Read , Write } ;
77use async_std:: { prelude:: * , task} ;
8- use http_types:: headers:: { CONTENT_LENGTH , EXPECT , TRANSFER_ENCODING } ;
8+ use http_types:: content:: ContentLength ;
9+ use http_types:: headers:: { EXPECT , TRANSFER_ENCODING } ;
910use http_types:: { ensure, ensure_eq, format_err} ;
1011use http_types:: { Body , Method , Request , Url } ;
1112
@@ -82,11 +83,16 @@ where
8283 req. append_header ( header. name , std:: str:: from_utf8 ( header. value ) ?) ;
8384 }
8485
85- let content_length = req . header ( CONTENT_LENGTH ) ;
86+ let content_length = ContentLength :: from_headers ( & req ) ? ;
8687 let transfer_encoding = req. header ( TRANSFER_ENCODING ) ;
8788
88- http_types:: ensure!(
89+ // Return a 400 status if both Content-Length and Transfer-Encoding headers
90+ // are set to prevent request smuggling attacks.
91+ //
92+ // https://tools.ietf.org/html/rfc7230#section-3.3.3
93+ http_types:: ensure_status!(
8994 content_length. is_none( ) || transfer_encoding. is_none( ) ,
95+ 400 ,
9096 "Unexpected Content-Length header"
9197 ) ;
9298
@@ -123,11 +129,11 @@ where
123129 req. set_body ( Body :: from_reader ( reader, None ) ) ;
124130 return Ok ( Some ( ( req, BodyReader :: Chunked ( reader_clone) ) ) ) ;
125131 } else if let Some ( len) = content_length {
126- let len = len. last ( ) . as_str ( ) . parse :: < usize > ( ) ? ;
127- let reader = Arc :: new ( Mutex :: new ( reader. take ( len as u64 ) ) ) ;
132+ let len = len. len ( ) ;
133+ let reader = Arc :: new ( Mutex :: new ( reader. take ( len) ) ) ;
128134 req. set_body ( Body :: from_reader (
129135 BufReader :: new ( ReadNotifier :: new ( reader. clone ( ) , body_read_sender) ) ,
130- Some ( len) ,
136+ Some ( len as usize ) ,
131137 ) ) ;
132138 Ok ( Some ( ( req, BodyReader :: Fixed ( reader) ) ) )
133139 } else {
0 commit comments