Is this for Service? Or any other trait where Future is a non-generic associated type...
There's no way for non-generic associated types like Handler to involve lifetimes that don't come from trait parameters or the implementing type,[1] such as the reference lifetime on &self. But your future is capturing &self in the else branch.
corollary: if there are no non-'static lifetimes in the trait parameters or implementing type, a non-generic associated type satisfies a 'static bound âŠī¸
Yes it is indeed for Service. My else branch is really close to what is on the doc though:
impl<S, B> Service<ServiceRequest> for SayHiMiddleware<S>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
B: 'static,
{
type Response = ServiceResponse<B>;
type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
forward_ready!(service);
fn call(&self, req: ServiceRequest) -> Self::Future {
println!("Hi from start. You requested: {}", req.path());
let fut = self.service.call(req);
Box::pin(async move {
let res = fut.await?;
println!("Hi from response");
Ok(res)
})
}
}
So I have the impression something I do is not permitted by the lib bit it isnt clear what it is.
Also I did remove the generic type B 'static on the service cause I thought it brought issues. With this 'static generic type B the compiler outputs this following:
error[E0308]: mismatched types
--> src/middleware.rs:62:27
|
34 | impl<S, B> Service<ServiceRequest> for AuthenticationMiddleware<S>
| - found this type parameter
...
62 | return Ok(res)
| -- ^^^ expected `ServiceResponse`, found `ServiceResponse<B>`
| |
| arguments to this enum variant are incorrect
|
= note: expected struct `ServiceResponse<BoxBody>`
found struct `ServiceResponse<B>`
So in a nutshell, is it the Http response I build which has not the lifetime of req being the issue ? How do people usually add some filtering logic using actix middlewares ?
Note that the example creates the future (which is 'static) that represents the call to the underlying service not inside of the returned future (i.e. it is created outside of the returned async move { ... } block), but before that. This avoids capturing the non-static reference &self, which would make the future we return from SayHiMiddleware::call not 'static itself, violating the trait bounds of Service.
I personally use the actix_web_httpauth crate to build my authentication middleware.
It's not the library, but closure semantics. As @quinedot mentioned you are capturing self in the future, and that's what the error you posted is about.
If this is not clear for you, let me rephrase it:
The move keyword in Rust is what allows a closure to capture the variables from its context:
async move {
...
}
And you are capturing self in the else branch by using it:
else {
let fut = self.service.call(req); // Here you used self
let res = fut.await.unwrap();
return Ok(res)
}
And you constrained the returned future to have a 'static lifetime:
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;