@@ -279,32 +279,27 @@ impl HttpClient {
279279 }
280280 }
281281
282- if !status. is_ok ( ) {
283- // TODO: Handle 3xx redirection responses.
284- return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: NotFound , "not found" ) ) ;
285- }
286-
287282 // Read message body
288283 let read_limit = MAX_HTTP_MESSAGE_BODY_SIZE - reader. buffer ( ) . len ( ) ;
289284 reader. get_mut ( ) . set_limit ( read_limit as u64 ) ;
290- match message_length {
291- HttpMessageLength :: Empty => { Ok ( Vec :: new ( ) ) } ,
285+ let contents = match message_length {
286+ HttpMessageLength :: Empty => { Vec :: new ( ) } ,
292287 HttpMessageLength :: ContentLength ( length) => {
293288 if length == 0 || length > MAX_HTTP_MESSAGE_BODY_SIZE {
294- Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: InvalidData , "out of range" ) )
289+ return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: InvalidData , "out of range" ) )
295290 } else {
296291 let mut content = vec ! [ 0 ; length] ;
297292 #[ cfg( feature = "tokio" ) ]
298293 reader. read_exact ( & mut content[ ..] ) . await ?;
299294 #[ cfg( not( feature = "tokio" ) ) ]
300295 reader. read_exact ( & mut content[ ..] ) ?;
301- Ok ( content)
296+ content
302297 }
303298 } ,
304299 HttpMessageLength :: TransferEncoding ( coding) => {
305300 if !coding. eq_ignore_ascii_case ( "chunked" ) {
306- Err ( std:: io:: Error :: new (
307- std:: io:: ErrorKind :: InvalidInput , "unsupported transfer coding" ) )
301+ return Err ( std:: io:: Error :: new (
302+ std:: io:: ErrorKind :: InvalidInput , "unsupported transfer coding" ) )
308303 } else {
309304 let mut content = Vec :: new ( ) ;
310305 #[ cfg( feature = "tokio" ) ]
@@ -339,17 +334,30 @@ impl HttpClient {
339334 reader. read_exact ( & mut content[ chunk_offset..] ) . await ?;
340335 content. resize ( chunk_offset + chunk_size, 0 ) ;
341336 }
342- Ok ( content)
337+ content
343338 }
344339 #[ cfg( not( feature = "tokio" ) ) ]
345340 {
346341 let mut decoder = chunked_transfer:: Decoder :: new ( reader) ;
347342 decoder. read_to_end ( & mut content) ?;
348- Ok ( content)
343+ content
349344 }
350345 }
351346 } ,
347+ } ;
348+
349+ if !status. is_ok ( ) {
350+ // TODO: Handle 3xx redirection responses.
351+ let error_details = match contents. is_ascii ( ) {
352+ true => String :: from_utf8_lossy ( & contents) . to_string ( ) ,
353+ false => "binary" . to_string ( )
354+ } ;
355+ let error_msg = format ! ( "Errored with status: {} and contents: {}" ,
356+ status. code, error_details) ;
357+ return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , error_msg) ) ;
352358 }
359+
360+ Ok ( contents)
353361 }
354362}
355363
@@ -720,6 +728,23 @@ pub(crate) mod client_tests {
720728 }
721729 }
722730
731+ #[ tokio:: test]
732+ async fn read_error ( ) {
733+ let response = String :: from (
734+ "HTTP/1.1 500 Internal Server Error\r \n \
735+ Content-Length: 10\r \n \r \n test error\r \n ") ;
736+ let server = HttpServer :: responding_with ( response) ;
737+
738+ let mut client = HttpClient :: connect ( & server. endpoint ( ) ) . unwrap ( ) ;
739+ match client. get :: < JsonResponse > ( "/foo" , "foo.com" ) . await {
740+ Err ( e) => {
741+ assert_eq ! ( e. get_ref( ) . unwrap( ) . to_string( ) , "Errored with status: 500 and contents: test error" ) ;
742+ assert_eq ! ( e. kind( ) , std:: io:: ErrorKind :: Other ) ;
743+ } ,
744+ Ok ( _) => panic ! ( "Expected error" ) ,
745+ }
746+ }
747+
723748 #[ tokio:: test]
724749 async fn read_empty_message_body ( ) {
725750 let server = HttpServer :: responding_with_ok :: < String > ( MessageBody :: Empty ) ;
0 commit comments