首页 > 解决方案 > 如何在rocket.rs 中建立一个全局的postgres 池连接并使FromRequest 自定义守卫异步?

问题描述

我正在制作一个授权系统,它将实现FromRequestweb 框架火箭的特征,这是制作自定义警卫所必需的。

我遇到的第一个问题是我必须如何使连接成为全球性的。我应该将它转换为常量,以便可以从实现中的函数访问它,还是火箭中的缓存或某种形式的存储PgPool可以访问连接(因为我使用的是 sqlx)& 可以进行查询.

我遇到的第二个问题是使 FromRequest 函数异步。由于 sqlx 是本机异步 afaik,我不知道火箭是否还支持这一点。我正在考虑制作一个 tokio 线程,或者是否有.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(())
    }
}

标签: rustrust-rocketrust-sqlx

解决方案


对 Rocket 的异步支持在 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 :一个很好的代码示例显示了这个
https://github.com/samyak-jain/unagi:这个 repo 是我正在使用的一个应用程序Rocket 的主分支允许它使用异步。这个 repo 也是用于数据库连接的rocket-contrib。


推荐阅读