Doing async reqwest

Hi

I'm trying for the first time to use the async version of reqwest and it's throwing an error I cannot decode.

My async function.

async fn get_page(uri: reqwest::Url) -> Result<String, reqwest::Error> {
    let client = reqwest::Client::new();
    let text = client
        .get(uri)
        .header(
            reqwest::header::USER_AGENT,
            "MemBot (+https://superrune.dk/membot/)",
        )
        .send()
        .await?
        .text()
        .await?;

    Ok(text)
}

And the funtion is the used like this

pub fn get_article(link: &str, id: &uuid::adapter::Hyphenated) -> Option<String> {
   ....
   
   if let Ok(body) = get_page(uri) {
       ....

       return Some(article);
   }

   None
}

Gives me this compile time errors

error[E0308]: mismatched types
    |
20  |     if let Ok(body) = get_page(uri) {
    |            ^^^^^^^^ expected opaque type, found enum `std::result::Result`
...
151 | async fn get_page(uri: reqwest::Url) -> Result<(), reqwest::Error> {
    |                                         -------------------------- the `Output` of this `async fn`'s expected opaque type
    |
    = note: expected opaque type `impl std::future::Future`
                      found enum `std::result::Result<_, _>`

error[E0277]: the size for values of type `str` cannot be known at compilation time
   |
20 |     if let Ok(body) = get_page(uri) {
   |               ^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `str`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: all local variables must have a statically known size
   = help: unsized locals are gated as an unstable feature

Can some one help me figure out this riddle, because I feel prettt incompetent right now.

1 Like

Since the get_page() is an async function, it doesn't return Result<String, reqwest::Error> directly but returns a future which will yields that result at some point. So your code should be:

if let Ok(body) = get_page(url).await {

The error expected opaque type impl std::future::Future usually means you need to .await something.

Alright. Does this mean that everything through the call stack, right up to the main function needs to have the async prefix?

If you're using #[tokio::main], yes. However you can also have main be synchronous and manually create a Runtime object somewhere, and then use spawn or block_on to start the asynchronous code from synchronous code. (This is what #[tokio::main] does for you behind the scenes)

But in general, yes. If you want to call an async function, everything up through the call stack until the spot where you give it to the executor should be async.

Thanks for all the answers. I've markede the first answer from @Hyeonu as the solution to my question.

Thanks @alice for answering my followup question.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.