How to fetch response body in Decode failed error in reqwest?

2.3k views Asked by At

Currently I can only get the error message which is error decoding response body: expected value at line 1 column 1.

Apparently the reason of error is httpbin.org was returning HTML. I'm wondering how can I return that HTML to the client.

use actix_web::{get, App, Error, HttpResponse, HttpServer};
use reqwest;
use std::collections::HashMap;

#[get("/")]
async fn index() -> Result<HttpResponse, Error> {
    let res = reqwest::get("https://httpbin.org/404")
        .await
        .expect("Get request failed");

    match res.json::<HashMap<String, String>>().await {
        Ok(resp) => Ok(HttpResponse::Ok().json(resp)),
        Err(e) => {
            println!("{:?}", e);
            Err(Error::from(HttpResponse::BadRequest().body(e.to_string())))
        }
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(index))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}
1

There are 1 answers

0
Masklinn On

actix_web's Response::json is defined as:

pub async fn json<T: DeserializeOwned>(self) -> Result<T>

As it takes self by value, it consumes the response and thus makes it inaccessible.

Therefore in order to keep access to the response body you need to deserialise it yourself, to ensure the response body is still accessible and not consumed.

That's pretty easy since Response::json is a very short helper:

pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> {
    let full = self.bytes().await?;

    serde_json::from_slice(&full).map_err(crate::error::decode)
}

Since serde doesn't consume the response body, all you have to do is keep the result of Response::bytes around, then you'll be able to further use it.

Though to me if the endpoint you're calling might return not-json to a request expecting json:

  • you should investigate why? (TBF I fail to see why it would return json when you specifically query the site's 404?)
  • you should be able to check the content-type of the response