火箭-由于未实现特征,我的守卫中的使用状态失败
Rocket - Use state within my guards fails as traits are not implemented
我想在我的守卫中使用状态。我希望路由需要使用 api 密钥进行身份验证,我想在我的 Rocket.toml
中定义该密钥。但是 运行 此代码出现以下错误:
特征 From<(Status, ())>
没有为 (Status, ApiKeyError)
实现
对于这行代码let config_state = try_outcome!(req.guard::<State<'_, Config>>().await);
如何实现这个特性?或者是否有更好的解决方案来管理 Rocket 中的 api 令牌。
我正在使用0.5.0-dev
版本的 Rocket。
#[macro_use] extern crate rocket;
use rocket::http::Status;
use rocket::request::{Outcome, Request, FromRequest};
use rocket::State;
use rocket::fairing::AdHoc;
use serde::Deserialize;
#[derive(Deserialize)]
struct Config {
api_key: String,
}
struct ApiKey<'r>(&'r str);
#[derive(Debug)]
enum ApiKeyError {
Missing,
Invalid,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKey<'r> {
type Error = ApiKeyError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let config_state = try_outcome!(req.guard::<State<'_, Config>>().await);
/// Returns true if `key` is a valid API key string.
fn is_valid(key: &str, api_key: String) -> bool {
key == api_key
}
match req.headers().get_one("Authorization") {
None => Outcome::Failure((Status::Unauthorized, ApiKeyError::Missing)),
Some(key) if is_valid(key, config_state.api_key) => Outcome::Success(ApiKey(key)),
Some(_) => Outcome::Failure((Status::Unauthorized, ApiKeyError::Invalid)),
}
}
}
#[get("/")]
async fn index(config: State<'_, Config>, key: ApiKey<'_>) -> &'static str {
"Hello, world!"
}
fn rocket() -> rocket::Rocket {
let rocket = rocket::ignite();
let figment = rocket.figment();
let config: Config = figment.extract().expect("config");
rocket
.mount("/", routes![index])
.attach(AdHoc::config::<Config>())
}
#[rocket::main]
async fn main() {
rocket()
.launch()
.await;
}
我已经使用 AdHoch::config()
存储了配置,但要在 guard 中检索它,我需要使用 request.rocket().state::<Config>()
。更正后的源代码如下:
#[macro_use] extern crate rocket;
use rocket::http::Status;
use rocket::request::{Outcome, Request, FromRequest};
use rocket::State;
use rocket::fairing::AdHoc;
use serde::Deserialize;
#[derive(Deserialize)]
struct Config {
api_key: String,
}
struct ApiKey<'r>(&'r str);
#[derive(Debug)]
enum ApiKeyError {
Missing,
Invalid,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKey<'r> {
type Error = ApiKeyError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
// Retrieve the config state like this
let config = req.rocket().state::<Config>().unwrap();
/// Returns true if `key` is a valid API key string.
fn is_valid(key: &str, api_key: &str) -> bool {
key == api_key
}
match req.headers().get_one("Authorization") {
None => Outcome::Failure((Status::Unauthorized, ApiKeyError::Missing)),
Some(key) if is_valid(key, &config.api_key) => Outcome::Success(ApiKey(key)),
Some(_) => Outcome::Failure((Status::Unauthorized, ApiKeyError::Invalid)),
}
}
}
#[get("/")]
async fn index(config: State<'_, Config>, key: ApiKey<'_>) -> &'static str {
"Hello, world!"
}
fn rocket() -> rocket::Rocket {
let rocket = rocket::ignite();
let figment = rocket.figment();
let config: Config = figment.extract().expect("config");
rocket
.mount("/", routes![index])
.attach(AdHoc::config::<Config>())
}
#[rocket::main]
async fn main() {
rocket()
.launch()
.await;
}
我想在我的守卫中使用状态。我希望路由需要使用 api 密钥进行身份验证,我想在我的 Rocket.toml
中定义该密钥。但是 运行 此代码出现以下错误:
特征 From<(Status, ())>
没有为 (Status, ApiKeyError)
对于这行代码let config_state = try_outcome!(req.guard::<State<'_, Config>>().await);
如何实现这个特性?或者是否有更好的解决方案来管理 Rocket 中的 api 令牌。
我正在使用0.5.0-dev
版本的 Rocket。
#[macro_use] extern crate rocket;
use rocket::http::Status;
use rocket::request::{Outcome, Request, FromRequest};
use rocket::State;
use rocket::fairing::AdHoc;
use serde::Deserialize;
#[derive(Deserialize)]
struct Config {
api_key: String,
}
struct ApiKey<'r>(&'r str);
#[derive(Debug)]
enum ApiKeyError {
Missing,
Invalid,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKey<'r> {
type Error = ApiKeyError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let config_state = try_outcome!(req.guard::<State<'_, Config>>().await);
/// Returns true if `key` is a valid API key string.
fn is_valid(key: &str, api_key: String) -> bool {
key == api_key
}
match req.headers().get_one("Authorization") {
None => Outcome::Failure((Status::Unauthorized, ApiKeyError::Missing)),
Some(key) if is_valid(key, config_state.api_key) => Outcome::Success(ApiKey(key)),
Some(_) => Outcome::Failure((Status::Unauthorized, ApiKeyError::Invalid)),
}
}
}
#[get("/")]
async fn index(config: State<'_, Config>, key: ApiKey<'_>) -> &'static str {
"Hello, world!"
}
fn rocket() -> rocket::Rocket {
let rocket = rocket::ignite();
let figment = rocket.figment();
let config: Config = figment.extract().expect("config");
rocket
.mount("/", routes![index])
.attach(AdHoc::config::<Config>())
}
#[rocket::main]
async fn main() {
rocket()
.launch()
.await;
}
我已经使用 AdHoch::config()
存储了配置,但要在 guard 中检索它,我需要使用 request.rocket().state::<Config>()
。更正后的源代码如下:
#[macro_use] extern crate rocket;
use rocket::http::Status;
use rocket::request::{Outcome, Request, FromRequest};
use rocket::State;
use rocket::fairing::AdHoc;
use serde::Deserialize;
#[derive(Deserialize)]
struct Config {
api_key: String,
}
struct ApiKey<'r>(&'r str);
#[derive(Debug)]
enum ApiKeyError {
Missing,
Invalid,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKey<'r> {
type Error = ApiKeyError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
// Retrieve the config state like this
let config = req.rocket().state::<Config>().unwrap();
/// Returns true if `key` is a valid API key string.
fn is_valid(key: &str, api_key: &str) -> bool {
key == api_key
}
match req.headers().get_one("Authorization") {
None => Outcome::Failure((Status::Unauthorized, ApiKeyError::Missing)),
Some(key) if is_valid(key, &config.api_key) => Outcome::Success(ApiKey(key)),
Some(_) => Outcome::Failure((Status::Unauthorized, ApiKeyError::Invalid)),
}
}
}
#[get("/")]
async fn index(config: State<'_, Config>, key: ApiKey<'_>) -> &'static str {
"Hello, world!"
}
fn rocket() -> rocket::Rocket {
let rocket = rocket::ignite();
let figment = rocket.figment();
let config: Config = figment.extract().expect("config");
rocket
.mount("/", routes![index])
.attach(AdHoc::config::<Config>())
}
#[rocket::main]
async fn main() {
rocket()
.launch()
.await;
}