How to read the response body as a string in Rust Hyper?
Asked Answered
Y

3

7

This question has several answers (here, here, and here), but none of them worked for me :(

What I've tried so far:


    use hyper as http;
    use futures::TryStreamExt;

    fn test_heartbeat() {
        let mut runtime = tokio::runtime::Runtime::new().expect("Could not get default runtime");

        runtime.spawn(httpserve());

        let addr = "http://localhost:3030".parse().unwrap();
        let expected = json::to_string(&HeartBeat::default()).unwrap();

        let client = http::Client::new();
        let actual = runtime.block_on(client.get(addr));

        assert!(actual.is_ok());

        if let Ok(response) = actual {
            let (_, body) = response.into_parts();
            
            // what shall be done here? 
        }
    }

I am not sure, what to do here?

Yangyangtze answered 7/8, 2020 at 12:24 Comment(3)
Have you tried to_bytes? It returns a Bytes object which you can deref into a &[u8], which you can then interpret as utf-8.Myeshamyhre
I would also suggest reqwest if you'd prefer ease of use over fine-grained control of hyper.Myeshamyhre
yep, that's it.Yangyangtze
Y
3

According to justinas the answer is:

// ...
let bytes = runtime.block_on(hyper::body::to_bytes(body)).unwrap();
let result = String::from_utf8(bytes.into_iter().collect()).expect("");
Yangyangtze answered 7/8, 2020 at 12:55 Comment(2)
even though it surely can be solved in a better way.Yangyangtze
Note that if you are already inside async code, you should replace the runtime.block_on part with an .await like seen in the other answer.Gratitude
T
9

This worked for me (using hyper 0.2.1):

async fn body_to_string(req: Request<Body>) -> String {
    let body_bytes = hyper::body::to_bytes(req.into_body()).await?;
    String::from_utf8(body_bytes.to_vec()).unwrap()
}
Trousers answered 6/9, 2020 at 2:13 Comment(1)
hyper::body::to_bytes() removed in 1.0, req.collect().await?.to_bytes(); works. (to_bytes() is now unfallible)Monnet
Y
3

According to justinas the answer is:

// ...
let bytes = runtime.block_on(hyper::body::to_bytes(body)).unwrap();
let result = String::from_utf8(bytes.into_iter().collect()).expect("");
Yangyangtze answered 7/8, 2020 at 12:55 Comment(2)
even though it surely can be solved in a better way.Yangyangtze
Note that if you are already inside async code, you should replace the runtime.block_on part with an .await like seen in the other answer.Gratitude
P
0

As of hyper 1, you can simply do

let contents: String = response.into_body().try_into().expect("oh no");
Piwowar answered 27/5 at 8:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.