gpt4 book ai didi

rust - 使用自定义 Rocket Responder 处理 RequestGuard 中的错误

转载 作者:行者123 更新时间:2023-11-29 08:26:06 24 4
gpt4 key购买 nike

在使用 rocket.rs 的 Web 服务器应用程序中,我使用了一个在我的 API 中实现 Responder 的错误类型。此错误类型可确保统一呈现所有错误(如 RFC 7807 json)。

但是,我找不到在 RequestGuards 中使用这些错误响应的方法。似乎 from_request 函数产生了一个 Outcome,它使用完全不同的模型,返回 Outcome::Failure((Status, T))关于错误。

如何确保这些请求守卫中的错误以相同的 JSON 格式呈现?它甚至可以定制吗?

我曾尝试使用捕手,但这似乎并没有检索到任何错误信息。

最佳答案

docs for FromRequest 's Outcome 状态:

Note that users can request types of Result<S, E> and Option<S> to catch Failures and retrieve the error value.

  1. 在您的 FromRequest 开始处实现,定义 type Error = JsonValue;

  2. from_request函数,确保它返回 request::Outcome<S, Self::Error>其中 S是您实现的目的。

  3. from_request函数,当你想返回失败时,做类似 Outcome::Failure((Status::Unauthorized, json!({"error": "unauthorised"}))) 的事情,或者您想要返回的任何内容。

  4. 在你的路线函数中使用Result<S, JsonValue>作为请求守卫的类型,其中 S是您实现的目的。在您的 route ,使用 match将其匹配到 Ok(S)Err(json_error)例如。

可能有一种方法可以传递 Outcome::Failure 的状态,但我描述的解决方案意味着如果您使用自定义响应程序,您将在响应程序中设置状态,而不是基于 Outcome::Failure - 例如下面的代码。

这是一个应用于 ApiKey 的示例从文档中请求守卫示例,其中包含一个名为 ApiResponse 的示例自定义响应程序设置自己的状态:

#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;

use rocket::Outcome;
use rocket::http::{ContentType, Status};
use rocket::request::{self, Request, FromRequest};
use rocket::response::{self, Responder, Response};
use rocket_contrib::json::{Json, JsonValue};

#[derive(Debug)]
pub struct ApiResponse {
pub json: JsonValue,
pub status: Status,
}

impl<'r> Responder<'r> for ApiResponse {
fn respond_to(self, req: &Request) -> response::Result<'r> {
Response::build_from(self.json.respond_to(req).unwrap())
.status(self.status)
.header(ContentType::JSON)
.ok()
}
}

#[derive(Debug, Deserialize, Serialize)]
struct ApiKey(String);

/// Returns true if `key` is a valid API key string.
fn is_valid(key: &str) -> bool {
key == "valid_api_key"
}

impl<'a, 'r> FromRequest<'a, 'r> for ApiKey {
type Error = JsonValue;

fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
let keys: Vec<_> = request.headers().get("x-api-key").collect();
match keys.len() {
0 => Outcome::Failure((Status::BadRequest, json!({ "error": "api key missing" }))),
1 if is_valid(keys[0]) => Outcome::Success(ApiKey(keys[0].to_string())),
1 => Outcome::Failure((Status::BadRequest, json!({ "error": "api key invalid" }))),
_ => Outcome::Failure((Status::BadRequest, json!({ "error": "bad api key count" }))),
}
}
}

#[get("/sensitive")]
fn sensitive(key: Result<ApiKey, JsonValue>) -> ApiResponse {
match key {
Ok(_ApiKey) => ApiResponse {
json: json!({ "data": "sensitive data." }),
status: Status::Ok
},
Err(json_error) => ApiResponse {
json: json_error,
status: Status::BadRequest
}
}
}

我是 Rust 和 Rocket 的新手,所以这可能不是最好的解决方案。

关于rust - 使用自定义 Rocket Responder 处理 RequestGuard 中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58030378/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com