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(())
}
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With