Rocket框架FromRequest实现中or_forward类型不匹配问题求助
我在学习Rust并尝试运行Rocket仓库的cookies/session示例时,编写了如下代码:
use rocket::http::Status; use rocket::outcome::IntoOutcome; use rocket::request::{self, FromRequest, Request}; #[derive(Debug)] pub struct User(usize); #[rocket::async_trait] impl<'r> FromRequest<'r> for User { type Error = std::convert::Infallible; async fn from_request(request: &'r Request<'_>) -> request::Outcome<User, Self::Error> { request .cookies() .get_private("user_id") .and_then(|cookie| cookie.value().parse().ok()) .map(User) .or_forward(Status::Unauthorized) } }
运行时出现类型不匹配错误:
| .or_forward(Status::Unauthorized) | ---------- ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Status` | | | arguments to this method are incorrect
将参数改为.or_forward(())可以编译,但无法返回401状态码,希望解决这个问题。
解决方案
根据你的需求,分两种场景处理:
场景1:拒绝请求并返回401未授权状态码
如果你希望在没有有效user_id Cookie时直接返回401错误响应,需要调整Error类型并使用into_outcome替代or_forward:
use rocket::http::Status; use rocket::outcome::IntoOutcome; use rocket::request::{self, FromRequest, Request}; #[derive(Debug)] pub struct User(usize); #[rocket::async_trait] impl<'r> FromRequest<'r> for User { // 将Error类型改为()(或其他自定义错误类型) type Error = (); async fn from_request(request: &'r Request<'_>) -> request::Outcome<User, Self::Error> { request .cookies() .get_private("user_id") .and_then(|cookie| cookie.value().parse().ok()) .map(User) // 指定失败时返回的状态码和错误值 .into_outcome((Status::Unauthorized, ())) } }
场景2:转发请求并携带状态码
如果你确实需要将请求转发给其他路由,同时携带状态码,直接手动构造Outcome::Forward即可:
use rocket::http::Status; use rocket::request::{self, FromRequest, Request, Outcome}; #[derive(Debug)] pub struct User(usize); #[rocket::async_trait] impl<'r> FromRequest<'r> for User { type Error = std::convert::Infallible; async fn from_request(request: &'r Request<'_>) -> request::Outcome<User, Self::Error> { match request .cookies() .get_private("user_id") .and_then(|cookie| cookie.value().parse().ok()) { Some(user_id) => Outcome::Success(User(user_id)), None => Outcome::Forward(Status::Unauthorized), } } }
原因说明
- 原错误是因为
or_forward方法的参数类型要求为()(当Error类型为Infallible时),而你传入了Status类型,导致类型不匹配。 IntoOutcome的or_forward方法用于生成转发请求的Outcome,而不是返回错误响应;若要返回错误,应使用into_outcome并指定状态码,此时需要Error类型为非Infallible(因为Failure变体需要关联错误值)。- 手动构造
Outcome::Forward可以直接携带Status,满足转发时传递状态码的需求。
内容的提问来源于stack exchange,提问作者ekimpl
相关产品推荐
相关产品推荐

