这个路由,只是在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
路线演示了复制此类状态。
我通过请求防护而不是通过
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
}
我在文档中找到了这个这里。