You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rocket框架FromRequest实现中or_forward类型不匹配问题求助

Rocket框架中FromRequest实现返回Unauthorized状态码时的类型不匹配问题解决

我在学习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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 12:22:37