我初始化了一个 Mutex< Pool<Postgres>>实例并将其传递给实例上的管理方法Rocket
,以便访问我的控制器上的数据库。我通常做的是:
// this is purely for example
#[get("/foo/bar")]
pub async fn controller<'a>(
// ... others ...
db_pool: &State<Mutex<PgPool>>,
// ... others ...
) {
// ... do other things ...
let query_r = sqlx::query("SELECT * FROM users WHERE id=$1")
.bind(&id)
.fetch_optional(&mut db_pool.inner().lock().await.acquire().await.unwrap()) // i reach `inner` of state, then `lock` the mutex, lastly `acquire` a pool connection
.await; // type is Result<Option<PgRow>> i suppose, rust-analyzer is not very good at inferring it
// ... do other things ...
}
这很酷,但这是我的问题:我写了一个结构如下......
pub struct User {
id: usize,
username: String,
email: String,
}
...而且我实际上想将它用作请求保护,以便客户端在没有提供正确凭据的情况下无法访问控制器。
Rocket 的官方指南告诉实现FromRequest特征,以便可以将其解析为警卫。
但是,为了初始化一个User
实例,我需要在这个FromRequest特征中获取一个PoolConnection。我已经深入研究了 Rocket 的 API 文档,似乎FromRequest 上的请求参数有一个名为 Rocket 的方法,它返回一个实例,并且通过它,我可以访问 state。Rocket<Orbit>
但是,问题是state方法返回&Mutex<Pool<Postgres>>
,这是一个不可变的引用,所以我不能用它对数据库做任何操作。
我已经走了这么远,想问是否有人知道Mutex<Pool<Postgres>>
无需参考即可访问的方法。
提前致谢。
我走了多远
下面是我如何实现FromRequest。
pub struct User {
id: usize,
username: String,
email: String,
}
#[derive(Debug)]
pub enum UserError {
TokenError(TokenError),
MissingToken,
DatabasePoolError,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for User {
type Error = UserError;
async fn from_request(request: &'r rocket::Request<'_>) -> request::Outcome<Self, Self::Error> {
let encrypted_token_o = request.headers().get_one("Authorization");
match encrypted_token_o {
Some(encrypted_token) => {
let claims_r = Claims::try_from(encrypted_token.to_owned());
match claims_r {
Ok(claims) => {
let db_pool_o = request.rocket().state::<Mutex<PgPool>>();
match db_pool_o {
Some(db_pool) => {
let id = 0; // a test id
let query_r = sqlx::query(
"SELECT id, username, email FROM users WHERE id=$1",
)
.bind(&id)
.fetch_optional(
// ERROR: no method named `inner` found for reference `&rocket::futures::lock::Mutex<Pool<Postgres>>` in the current scope
&mut db_pool.inner().lock().await.acquire().await.unwrap(),
)
.await;
todo!()
}
None => request::Outcome::Failure((
http::Status::InternalServerError,
UserError::DatabasePoolError,
)),
}
}
Err(e) => request::Outcome::Failure((
http::Status::InternalServerError,
UserError::TokenError(e),
)),
}
}
None => request::Outcome::Failure((http::Status::BadRequest, UserError::MissingToken)),
}
}
}
环境
- 锈病 1.55.0
- 火箭 0.5.0-rc.1 具有功能
default
和json
- sqlx 0.5.7 的特性
runtime-tokio-native-tls
,all-types
和postgres
migrate