rustlifetimeactix-webrust-futures

Using async functions within a Actix middleware


I'm making a Rust API with actix and sqlx, and currently working on a JWT middleware, it's mostly done, but I'd like to retrieve the authorized user into my endpoints. That's what the code below is attempting, but I'm running into a lifetime issue.

fn call(&self, req: ServiceRequest) -> Self::Future {
    if ApiEnv::skip_auth() {
        return Box::pin(self.service.call(req));
    }

    // Box::pin(self.service.call(req))
    Box::pin(async move {
        let u = {
            let db: &Data<Database> = req.app_data().unwrap();
            let pool = db.pool.clone();
            let headers = req.headers().clone();
            let mut extensions = req.extensions_mut();

            match authorize(pool, headers).await {
                Ok(u) => {
                    extensions.insert(u);
                    Ok(())
                }
                Err(e) => Err(e),
            }
        };

        match u {
            Ok(_) => self.service.call(req).await,
            Err(e) => Err(e),
        }
    })
}

I'm getting the following error:

error: lifetime may not live long enough
   --> src/middleware/jwt.rs
    |
    |     fn call(&self, req: ServiceRequest) -> Self::Future {
    |             - let's call the lifetime of this reference `'1`
...
    | /     Box::pin(async move {
    | |       let u = {
    | |         let db: &Data<Database> = req.app_data().unwrap();
    | |         let pool = db.pool.clone();
...   |
    | |       }
    | |     })
    | |______^ returning this value requires that `'1` must outlive `'static`

I know why this is: I'm using self.service.call inside of a Box::pin, but how do i fix it?

If I move self.service.call(req) outside of the Box::Pin, the req value is moved before i call let mut extensions = req.extensions_mut(); and extensions.insert(u), so as far as i know, i can't do that either.

How can I call an async function in actix-web middleware? is a very similar issue, but all the links either lead to deleted repo's, or one that calls self.service.clone(), despite Service not implementing Clone


Solution

  • After a few days I figured what was going on, the repo that had self.service.clone() wrapped Service in a Rc<> therefore being able to clone it. I missed it completely.