Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`?` couldn't convert the error to `std::io::Error`

Tags:

rust

reqwest

I am attempting to do a post using the reqwest library and following patters that I have found in various places online:

let res = http_client.post(&url)
                          .header("Content-Type", "application/x-www-form-urlencoded")
                          .form(&form_data)
                          .send()
                          .await?;
println!("authenticate response: {}", res.status)

The code block above causes a compile error:

`?` couldn't convert the error to `std::io::Error` the trait ` 
      `std::convert::From<reqwest::error::Error>` is not implemented for `std::io::Error`

I do not understand why I am getting this error. I have made my code as close to the examples as I can. It will compile if I remove the ? and the res.status. But I need to get the status res.status value. More importantly, I need to understand what I am missing or doing wrong.

like image 709
Jim Reineri Avatar asked Jun 09 '20 01:06

Jim Reineri


1 Answers

Your error is caused by the return type of the function from where you call this block, the compiler wants to return a error of the type std::io::Error.

From the error description, I draw the conclusion your main function looks something like this:

fn main() -> Result<(), std::io::Error> {
    // ...
}

The problem is that reqwest does not return an io::Error. This is a snippet I wrote a few months ago:

use exitfailure::ExitFailure;

fn main() -> Result<(), ExitFailure> {
    let res = http_client
        .post(&url)
        .header("Content-Type", "application/x-www-form-urlencoded")
        .form(&form_data)
        .send()
        .await?;

    println!("authenticate response: {}", res.status);
    Ok(())
}

I used exitfailure to convert the returned error type to a human-readable return type for main. I think it will solve your issue too.

Update: It was pointed out in the comments, exifailure have deprecated dependencies and this could be achieved without an external crate. There is a recommended way of returning an encapsulated dynamic error: Box<dyn std::error::Error>

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = http_client
        .post(&url)
        .header("Content-Type", "application/x-www-form-urlencoded")
        .form(&form_data)
        .send()
        .await?;

    println!("authenticate response: {}", res.status);
    Ok(())

}

From what I could see the behavior in returning agreageted errors from main is identical.

like image 87
Simson Avatar answered Sep 18 '22 20:09

Simson