Search code examples
rustreqwest

Reqwest: read body text and return reqwest::Error


I want to use reqwest to make a request, then print the response's body and return a reqwest::Error if the status code was >= 400. This is how I would like to do this:

pub async fn print_body() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://www.rust-lang.org").await?;
    println!("received text: {:?}", response.text().await?);
    response.error_for_status()?;
    Ok(())

The trouble is that both response.text() and response.error_for_status() consume the response. Debug printing the response itself or the error from response.error_for_status() does not print the response body.

I've tried saving the status code, then generating a reqwest::Error if the status code is >= 400, but reqwest::Error is not meant to be constructed by library users since its inner field and constructor are private. Ideally a reqwest::Error is returned since other functions depend on this API, and I would like to understand if it's possible to achieve this without changing the public interface.

Rust playground link


Solution

  • You might have glossed over the error_for_status_ref() method, which does not consume the response. You just need to swap the order of the calls:

    pub async fn print_body() -> Result<(), reqwest::Error> {
        let response = reqwest::get("https://www.rust-lang.org").await?;
        response.error_for_status_ref()?;
        println!("received text: {:?}", response.text().await?);
        Ok(())
    }
    

    To print the text regardless, just store the result of error_for_status_ref() and map the reference in the Ok case to be () to match the return type of your function:

    pub async fn print_body() -> Result<(), reqwest::Error> {
        let response = reqwest::get("https://www.rust-lang.org").await?;
        let result = response.error_for_status_ref().map(|_| ());
        println!("received text: {:?}", response.text().await?);
        result
    }