I need to get the managed redis client to create/check jwt tokens for an authentication middleware, but I am getting an error:
the trait bound `rocket::State<RedisRepo>: FromRequest<'_>` is not satisfied
the trait `FromRequest<'r>` is implemented for `&'r rocket::State<T>
first, I created a RedisRepo
:
use std::env;
extern crate dotenv;
use dotenv::dotenv;
use rocket::{
http::Status,
request::{FromRequest, Outcome, Request},
};
use crate::error::common::CommonError;
extern crate redis;
pub fn create_redis_connection() -> redis::Client {
dotenv().ok();
let uri = match env::var("REDIS_URL") {
Ok(v) => v.to_string(),
Err(_) => format!("Error loading env variable"),
};
let client = redis::Client::open(uri);
return client.ok().unwrap();
}
pub struct RedisRepo {
pub client: redis::Client,
}
impl RedisRepo {
pub fn init() -> Self {
let client = create_redis_connection();
RedisRepo { client }
}
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for RedisRepo {
type Error = CommonError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let state = req.rocket().state::<RedisRepo>();
if state.is_none() {
return Outcome::Failure((
Status::InternalServerError,
CommonError {
description: "unable to get redis database".to_string(),
},
));
}
Outcome::Success(*state.unwrap())
}
}
then I added an authentication middleware:
use rocket::request::{self, FromRequest, Request};
use crate::{error::response::RequestError, repository::redis_repos::RedisRepo};
pub struct AuthContext {
pub user_id: String,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for AuthContext {
type Error = RequestError;
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
// get redis client
let cache = req.guard::<rocket::State<RedisRepo>>().await;
// ^ error here : the trait bound `rocket::State<RedisRepo>:
// FromRequest<'_>` is not satisfied the trait `FromRequest<'r>`
// is implemented for `&'r rocket::State<T>
// TODO: get token from header
// TODO: verify token
// TODO: get user and check existing
// TODO: get time and check that is not expiring
request::Outcome::Success(AuthContext {
// TODO: add user id
user_id: "".to_string(),
})
}
}
and here is main.rs
:
mod api;
mod controller;
mod error;
mod helpers;
mod middleware;
mod models;
mod repository;
#[macro_use]
extern crate rocket;
use api::{
text_annotation_api::create_text_annotation,
user_api::{create_user, get_user, update_user},
};
use repository::{mongodb_repos::MongoRepo, redis_repos::RedisRepo};
#[launch]
fn rocket() -> _ {
let db = MongoRepo::init();
let cache = RedisRepo::init();
rocket::build()
.manage(db)
.manage(cache)
.mount("/", routes![create_user, get_user, update_user])
}