Rust 将变量移出其环境的扭曲过滤器

Rust 将变量移出其环境的扭曲过滤器,rust,rust-warp,Rust,Rust Warp,我正在尝试实现一个过滤器,它位于我的所有路由中,提取一个头并将一个可能的令牌与存储在我的系统上的令牌相匹配 我想实现类似的东西,但我得到了错误 应为实现Fn特性的闭包,但此闭包 仅实现FnOnce闭包是FnOnce,因为它移动 将变量tmp移出其环境 我有点明白编译器的意思,但不知道如何解决它。 我想让tmp=store.clone这样做会更好 我有过滤器: pub fn haystack_auth_header(store: Store) -> impl Filter<Extrac

我正在尝试实现一个过滤器,它位于我的所有路由中,提取一个头并将一个可能的令牌与存储在我的系统上的令牌相匹配

我想实现类似的东西,但我得到了错误

应为实现Fn特性的闭包,但此闭包 仅实现FnOnce闭包是FnOnce,因为它移动 将变量tmp移出其环境

我有点明白编译器的意思,但不知道如何解决它。 我想让tmp=store.clone这样做会更好

我有过滤器:

pub fn haystack_auth_header(store: Store) -> impl Filter<Extract = (Store,), Error = Rejection> + Clone {

   let tmp = store.clone();

    warp::header("Authorization").and_then (|auth_header: String| async move {

        // Authorization: BEARER authToken=xxxyyyzzz
        let result = auth_token(&auth_header); //-> IResult<&'a str, (&'a str, &'a str), (&'a str, ErrorKind)> {

        if result.is_err() {
            return Err(reject::custom(HayStackAuthToken));
        }

        let (_, key_value) = result.unwrap();

        let auth_token_result = tmp.read().get_authtoken();

        if auth_token_result.is_err() {
            return Err(reject::custom(HayStackAuthToken));
        }

        let auth_token_option = auth_token_result.unwrap();

        if auth_token_option.is_none() {
            return Err(reject::custom(HayStackAuthToken));
        }

        let auth_token = auth_token_option.unwrap();

        if auth_token != key_value.1 {
            return Err(reject::custom(HayStackAuthToken));
        }

        Ok(tmp)
    })
}
为什么克隆在这里不起作用

完全错误是

error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
    --> src/server/mod.rs:997:45
     |
997  |       warp::header("Authorization").and_then (|auth_header: String| async move {
     |  ___________________________________--------__^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_-
     | |                                   |         |
     | |                                   |         this closure implements `FnOnce`, not `Fn`
     | |                                   the requirement to implement `Fn` derives from here
998  | |
999  | |         // Authorization: BEARER authToken=xxxyyyzzz
1000 | |         let result = auth_token(&auth_header); //-> IResult<&'a str, (&'a str, &'a str), (&'a str, ErrorKind)> {
...    |
1026 | |         Ok(tmp.clone())
1027 | |     })
     | |_____- closure is `FnOnce` because it moves the variable `tmp` out of its environment

这个问题表明,您对fn层级还没有明确的区分: 摘自

Warp的过滤功能需要实现这个特性。 这意味着您无法访问外部contextread:环境

第一次调用闭包,然后调用闭包,该函数将使用唯一可用的tmp变量,因此它在以后的调用中不可用。由于闭包是对上下文的所有权,这意味着它只实现了一次


正如@msrd0在评论中所建议的,这可能可以通过在函数中移动该调用来解决,但我需要一个MRE来确定这一点。

在创建了一个简单的测试用例后,我成功地使用了以下函数

pub fn haystack_auth_header(store: Store) -> impl Filter<Extract = (Store,), Error = Rejection> + Clone {

    warp::header("Authorization").and_then (
        
            move |auth_header: String| 
            {
                let tmp = store.clone();
                async move {

                    let tmp = tmp.clone();

                    if tmp.read().get_authtoken().is_none() {
                        return Err(reject::custom(HayStackAuthToken));   
                    }
                    
                    Ok(tmp.clone())
                }
            }
    )
}

因此,最后只需要在正确的位置进行克隆。

请回答您的问题,并粘贴您得到的准确完整的错误-这将帮助我们了解问题所在,以便我们能够提供最好的帮助。有时,试图解释错误消息是很棘手的,而这实际上是错误消息的另一个重要部分。请使用直接运行编译器的消息,而不是IDE生成的消息,IDE可能会试图为您解释错误。很难回答您的问题,因为它不包含错误。我们无法说出代码中存在哪些板条箱及其版本、类型、特征、字段等。如果您试图重现您的错误(如果可能的话),或者在全新的货运项目中,那么我们将更容易帮助您,然后您的问题将包括附加信息。您可以使用以下方法减少在此处发布的原始代码。谢谢商店是。。。UserAuthStore是-请不要仅使用散文描述代码。相反,请提供一个包含再现错误所需的所有定义,但不包括其他内容的示例。例如,您的筛选器的大部分逻辑可能可以替换为像true这样的硬编码值。我假设问题是您将tmp=store.clone放在了闭包的外部而不是内部,但如果没有示例,很难说我可以编译自己。我看到您正在编辑以添加更多信息,但您似乎忽略了生成最小示例的请求。请不要忽视这一点。
pub fn haystack_auth_header(store: Store) -> impl Filter<Extract = (Store,), Error = Rejection> + Clone {

    warp::header("Authorization").and_then (
        
            move |auth_header: String| 
            {
                let tmp = store.clone();
                async move {

                    let tmp = tmp.clone();

                    if tmp.read().get_authtoken().is_none() {
                        return Err(reject::custom(HayStackAuthToken));   
                    }
                    
                    Ok(tmp.clone())
                }
            }
    )
}