我正在制作一个授权系统,该系统将实现web框架火箭的FromRequest
特性,这是制作自定义警卫所需的。
我要讨论的第一个问题是如何使连接全局。我是否应该将其转换为常量,以便可以从实现中的函数访问,或者在火箭或某种形式的存储中缓存PgPool
连接(因为我使用sqlx)可以访问&可以进行查询
我经历的第二个问题是使FromRequest函数异步。由于sqlx本身就是异步的,我不知道rocket是否已经支持这个功能。我在想要么做一个东京线程,或者如果有一个版本的.then()
在Rust,但我不知道
#[derive(Debug)]
struct User {
username: String,
password: String,
user_id: i16,
phone_number: String,
display_name: String,
//other fields omitted
}
impl<'a, 'r> FromRequest<'a, 'r> for &'a User {
type Error = !;
fn from_request(request: &'a Request<'r>) -> request::Outcome<&'a User, !> {
let user_result = request.local_cache(|| {
//..need to fetch user with sqlx [but sqlx is async]
//and later get cookies and check
});
user_result.as_ref().or_forward(())
}
}
Rocket lands在0.5版的异步支持。现在,您可以使用主分支:https://github.com/SergioBenitez/Rocket
在Rocket中处理这个用例的惯用方法是为数据库使用Rocket -contrib适配器:https://docs.rs/rocket_contrib/0.4.7/rocket_contrib/databases/index.html#provided您需要为数据库实现Poolable Trait。以下是相关文档:https://docs.rs/rocket_contrib/0.4.7/rocket_contrib/databases/trait.Poolable.html
Rocket已经提供了以下特性:
diesel::MysqlConnection
diesel::PgConnection
diesel::SqliteConnection
postgres::Connection
mysql::Conn
rusqlite::Connection
rusted_cypher::GraphClient
redis::Connection
你可以这样使用数据库宏:
use rocket_contrib::databases::postgres;
#[database("db_name")]
struct MyPgDatabase(postgres::Connection);
fn main() {
rocket::custom(config)
.attach(MyPgDatabase::fairing())
.launch();
}
您可以使用此类型作为请求保护,然后检索数据库连接,因为上面的宏会自动为您生成FromRequest
实现
#[get("/")]
fn my_handler(conn: MyPgDatabase) {
// ...
}
宏还生成一个Deref
实现,允许您访问内部连接类型。
参考:
https://github.com/TatriX/realworld-rust-rocket:一个很好的代码示例,显示了这个