在 Rust 的 Rocket 中,为什么我可以从请求守卫复制状态,但通过 Rocket::state 检索状态时却不能?

问题描述 投票:0回答:1

这个路由,只是在Redis中设置一个key-value,编译运行成功:

#[post("/thing", data = "<msg>")]                                                                                                                                                                                     
async fn post_thing(mut redis_conn: Connection<Redis>, msg: Json<Thing<'_>>) -> Value {                                                                                                                               
    redis::cmd("SET")                                                                                                                                                                                                 
        .arg(&[msg.name, msg.description])                                                                                                                                                                            
        .query_async::<_, ()>(&mut *redis_conn)                                                                                                                                                                       
        .await                                                                                                                                                                                                        
        .unwrap();                                                                                                                                                                                                    
    json!({ "name": msg.name, "description": msg.description })                                                                                                                                                       
}

我正在尝试实现 FromRequest 以将我的用户类型公开给某些路由。这涉及从 Redis 检索与给定会话 ID 关联的用户 ID。在 FromRequest 实现内部,状态的访问方式略有不同。

mut redis_conn: Connection<Redis>
是一个函数参数,它是通过
request.rocket().state::<Connection<Redis>>()
:

检索的
let redis_conn = match request.rocket().state::<Connection<Redis>>() {                                                                                                                                        
            Some(x) => x,                                                                                                                                                                                             
            None => {                                                                                                                                                                                                 
                return rocket::outcome::Outcome::Error((                                                                                                                                                              
                    http::Status::InternalServerError,                                                                                                                                                                
                    UserGuardError::FailedToGetDatabaseConnection,                                                                                                                                                    
                ))                                                                                                                                                                                                    
            }                                                                                                                                                                                                         
        };

问题是这样的 ---

request.rocket().state::<Connection<Redis>>()
给了我一个对状态的不可变引用(a
&Connection<Redis>
)而不是它的副本。这让我无法打电话
redis::cmd("GET").arg(...).query_async::<_, String>(&mut *redis_conn)
:

`redis_conn` is a `&` reference, so the data it refers to cannot be borrowed as mutable

我尝试通过

*
复制 Rocket State,但它没有实现
Copy
。我预计这会起作用,因为我的
post_thing
路线演示了复制此类状态。

rust copy rust-rocket
1个回答
0
投票

我通过请求防护而不是通过

Connection<Redis>
检索
request.rocket().state::<T>()
对象解决了我的问题。示例:

    async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
        // Using `State` as a request guard. Use `inner()` to get an `'r`.
        let outcome = request.guard::<&State<MyConfig>>().await
            .map(|my_config| Item(&my_config.user_val));

        // Or alternatively, using `Rocket::state()`:
        let outcome = request.rocket().state::<MyConfig>()
            .map(|my_config| Item(&my_config.user_val))
            .or_forward(Status::InternalServerError);

        outcome
    }

我在文档中找到了这个这里

© www.soinside.com 2019 - 2024. All rights reserved.