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

为何执行println后未触发StatusCode::BAD_REQUEST错误?

Rust API认证中间件返回200而非BAD_REQUEST的问题分析

问题场景

调试Rust API时,终端输出如下:

Server running on localhost:3000
auth
auth err1
...

auth err1来自认证中间件的.ok_or()闭包,但接口返回的却是200 OK,并未触发预期的StatusCode::BAD_REQUEST。

对应的中间件代码:

pub async fn auth<T>(mut request: Request<T>, next: Next<T>) -> Result<Response, StatusCode> {
    println!("auth");
    let token = request
        .headers()
        .typed_get::<Authorization<Bearer>>()
        .ok_or({
            println!("auth err1");
            StatusCode::BAD_REQUEST
        })?
        .token()
        .to_owned();
    //other code to connect to DB and retrieve user data...
}

原因分析

核心问题是中间件返回的错误没有被Web框架正确转换为HTTP错误响应:

  • 当typed_get返回None时,.ok_or()会执行闭包打印auth err1,并返回Err(StatusCode::BAD_REQUEST),?操作符会将这个错误从函数返回。
  • 但多数Rust Web框架(比如Axum)要求中间件的错误类型必须能被转换为合法的HTTP响应。直接返回StatusCode类型的错误,框架无法正确识别并生成400响应,反而会默认返回200,或忽略错误继续执行后续逻辑。

解决方法

  1. 调整错误返回格式,让错误可转换为响应
    修改中间件的返回类型,让错误包含状态码和响应体,确保框架能正确生成400响应:

    pub async fn auth<T>(mut request: Request<T>, next: Next<T>) -> Result<Response, impl IntoResponse> {
        println!("auth");
        let token = request
            .headers()
            .typed_get::<Authorization<Bearer>>()
            .ok_or_else(|| {
                println!("auth err1");
                (StatusCode::BAD_REQUEST, "Missing authorization token")
            })?
            .token()
            .to_owned();
        // 后续数据库操作...
        Ok(next.run(request).await)
    }
    

    这里用ok_or_else替代ok_or(更符合闭包延迟执行的语义),返回的元组(StatusCode, &str)会自动实现IntoResponse trait,框架能据此生成正确的400响应。

  2. 检查框架错误处理规则
    确认你使用的Web框架对中间件错误的处理逻辑,确保返回的错误类型实现了IntoResponse trait。如果直接返回StatusCode,部分框架需要额外转换逻辑才能生成响应。

  3. 验证中间件挂载正确性
    确认auth中间件被正确挂载到需要认证的路由上,没有被路由规则跳过,也没有因中间件顺序问题导致错误处理逻辑未生效。

内容的提问来源于stack exchange,提问作者Russo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:25:53