11use std:: collections:: HashMap ;
22use std:: fmt;
33
4- use crate :: async_runtime:: { NativeAsyncPending , spawn_tokio_native} ;
4+ use crate :: async_runtime:: { NativeAsyncPending , run_pending , spawn_tokio_native} ;
55use crate :: channel:: { ChannelError , RssStream , stream_from_iterator} ;
66use std:: io:: { BufRead , Read } ;
77use std:: str:: Utf8Error ;
@@ -19,6 +19,7 @@ pub struct Request {
1919pub struct Response {
2020 status : i64 ,
2121 body : String ,
22+ body_bytes : Vec < u8 > ,
2223}
2324
2425#[ derive( Debug , Clone , PartialEq , Eq ) ]
@@ -440,6 +441,7 @@ pub fn response_ok(body: &str) -> Result<Response, HttpError> {
440441 Ok ( Response {
441442 status : 200 ,
442443 body : body. to_string ( ) ,
444+ body_bytes : body. as_bytes ( ) . to_vec ( ) ,
443445 } )
444446}
445447
@@ -452,9 +454,7 @@ pub fn response_body(response: &Response) -> String {
452454}
453455
454456pub fn http_get ( url : & str ) -> Result < Response , HttpError > {
455- Err ( HttpError {
456- message : format ! ( "HTTP client runtime is not configured for GET {url}" ) ,
457- } )
457+ run_pending ( http_get_async ( url) )
458458}
459459
460460pub fn http_get_async ( url : & str ) -> NativeAsyncPending < Result < Response , HttpError > > {
@@ -674,9 +674,11 @@ async fn http_request_async(
674674 let body = response. bytes ( ) . await . map_err ( |error| HttpError {
675675 message : format ! ( "failed to read HTTP response body from {url}: {error}" ) ,
676676 } ) ?;
677+ let body_bytes = body. to_vec ( ) ;
677678 Ok ( Response {
678679 status,
679- body : String :: from_utf8_lossy ( & body) . to_string ( ) ,
680+ body : String :: from_utf8_lossy ( & body_bytes) . to_string ( ) ,
681+ body_bytes,
680682 } )
681683}
682684
@@ -746,7 +748,7 @@ pub fn http_response_text(response: &Response) -> String {
746748}
747749
748750pub fn http_response_bytes ( response : & Response ) -> Vec < u8 > {
749- response. body . as_bytes ( ) . to_vec ( )
751+ response. body_bytes . clone ( )
750752}
751753
752754pub fn http_response_lines ( response : & Response ) -> Vec < String > {
@@ -1823,6 +1825,32 @@ mod tests {
18231825 handle. join ( ) . expect ( "server thread should finish" ) ;
18241826 }
18251827
1828+ #[ test]
1829+ fn http_get_sync_uses_reqwest_tokio_io_and_preserves_bytes ( ) {
1830+ use std:: io:: { Read , Write } ;
1831+ use std:: net:: TcpListener ;
1832+
1833+ let listener = TcpListener :: bind ( "127.0.0.1:0" ) . expect ( "test listener should bind" ) ;
1834+ let addr = listener. local_addr ( ) . expect ( "listener addr should exist" ) ;
1835+ let handle = std:: thread:: spawn ( move || {
1836+ let ( mut stream, _) = listener. accept ( ) . expect ( "client should connect" ) ;
1837+ let mut request = [ 0_u8 ; 1024 ] ;
1838+ let read = stream. read ( & mut request) . expect ( "request should read" ) ;
1839+ let request = String :: from_utf8_lossy ( & request[ ..read] ) ;
1840+ assert ! ( request. starts_with( "GET /bytes HTTP/1.1" ) ) ;
1841+ stream
1842+ . write_all ( b"HTTP/1.1 200 OK\r \n Content-Length: 3\r \n Connection: close\r \n \r \n \x00 \xff A" )
1843+ . expect ( "response should write" ) ;
1844+ } ) ;
1845+
1846+ let response = http_get ( & format ! ( "http://{addr}/bytes" ) )
1847+ . expect ( "sync HTTP GET should succeed" ) ;
1848+
1849+ assert_eq ! ( response. status, 200 ) ;
1850+ assert_eq ! ( http_response_bytes( & response) , vec![ 0 , 255 , 65 ] ) ;
1851+ handle. join ( ) . expect ( "server thread should finish" ) ;
1852+ }
1853+
18261854 #[ test]
18271855 fn http_post_json_async_sends_body_through_reqwest_tokio_io ( ) {
18281856 use std:: io:: { Read , Write } ;
0 commit comments