Actix-web: lifetime error

I'm trying to create a middleware that takes the COOKIE from the request and returns the user id.

use std::{future::{ready, Ready}};
use actix_web::{
    dev::{Service, ServiceRequest, ServiceResponse, Transform, forward_ready},
    Error, HttpMessage, http::header::{self, HeaderValue}
};
use futures_util::{future::LocalBoxFuture, FutureExt};
use crate::mycrate

pub struct SignedUserTransform;

impl<S, B> Transform<S, ServiceRequest> for SignedUserTransform
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = SignedUser<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ready(Ok(SignedUser { service }))
    }
}
pub struct SignedUser<S> {
    service: S,
}
impl<S, B> Service<ServiceRequest> for SignedUser<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
    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 {
        let re = req.into_parts();
            Box::pin(async move {
                let session_v = SignedUserCheck::is_exits_session(&re.0).await;
                let rebuild = ServiceRequest::from_parts(re.0, re.1);
                let res = self.service.call(rebuild).await?;
                match session_v {
                    Ok(user_id) => {
                        let user_info = input::SignedUserInfo {id : user_id};
                        req.extensions_mut().insert(user_info);
                        Ok(res)
                    },
                    Err(_) => {
                        req.headers_mut().append(header::LOCATION, HeaderValue::from_static("/"));
                        Ok(res)
                    },
                }
            }).boxed_local()
    }

error

`self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
...is used and required to live as long as `'static` here

I tried trial and error, but nothing worked.

The definition of service's future uses 'static, which means that temporary references are forbidden and can't be made to work.

&self is a temporary reference, and therefore it's banned in the async move { block you're returning. You must copy any data you need out of self and not use it inside the async block, so that the returned future is completely independent of self and can work even after self is destroyed.

I used this document as a reference. With your help, I understand some of the things I don't understand.

impl<S, B> Transform<S, ServiceRequest> for SignedUserTransform
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = SignedUser<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ready(Ok(SignedUser { service: Rc::new(service) }))
    }
}

pub struct SignedUser<S> {
    service: Rc<S>,
}
impl<S, B> Service<ServiceRequest> for SignedUser<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
    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, mut req: ServiceRequest) -> Self::Future {
        let srv = self.service.clone();
            Box::pin(async move {
                let session_v = SignedUserCheck::is_exits_session(&req).await;
                match session_v {
                    Ok(user_id) => {
                        let user_info = input::SignedUserInfo {id : user_id};
                        req.extensions_mut().insert(user_info);
                        Ok(srv.call(req).await?)
                    },
                    Err(_) => {
                        req.headers_mut().append(header::LOCATION, HeaderValue::from_static("/"));
                        Ok(srv.call(req).await?)
...

By using "Rc" quietly, the error disappeared.
Thank you!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.