4

I am making an authorization system which will implement the FromRequest trait from the web framework rocket, which is needed to make custom guards.

The first problem I have gone into is how I have to make the connection global. Should I cast it as a constant, so it can be accessed from the functions in the implementation, or is there a cache in rocket or some form of storage where the PgPool connection (since I am using sqlx) can be accessed & queries can be made.

The second problem I have gone through is making the FromRequest functions asynchronous. Since sqlx is natively async afaik, I do not know if rocket has yet to support this. I was thinking of either making a tokio thread, or if there is a version of .then() in Rust, but I do not know

#[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(())
    }
}
Simon Kissane
  • 4,373
  • 3
  • 34
  • 59
tsu_katana
  • 47
  • 1
  • 5

1 Answers1

3

Async support for Rocket lands in Version 0.5. For now, you can use the master branch: https://github.com/SergioBenitez/Rocket

The idiomatic way to handle this use case in Rocket would be to use rocket-contrib adapter for databases: https://docs.rs/rocket_contrib/0.4.7/rocket_contrib/databases/index.html#provided

You'll need to implement the Poolable Trait for your database. Here are the docs for that: https://docs.rs/rocket_contrib/0.4.7/rocket_contrib/databases/trait.Poolable.html

Rocket already provides the trait for the following:

diesel::MysqlConnection
diesel::PgConnection
diesel::SqliteConnection
postgres::Connection
mysql::Conn
rusqlite::Connection
rusted_cypher::GraphClient
redis::Connection

You can then use the database macro like so:

use rocket_contrib::databases::postgres;

#[database("db_name")]
struct MyPgDatabase(postgres::Connection);

fn main() {
    rocket::custom(config)
        .attach(MyPgDatabase::fairing())
        .launch();
}

You can then just use this type as a request guard and then retrieve the database connection since the macro above automatically generates the FromRequest implementation for you

#[get("/")]
fn my_handler(conn: MyPgDatabase) {
    // ...
}

The macro also generates a Deref implementation allowing you access to the inner connection type.

For Reference:
https://github.com/TatriX/realworld-rust-rocket: A great code example showing this

Samyak
  • 405
  • 3
  • 13