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
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.