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

Axum中向授权中间件传递共享状态时出现签名错误

问题:Axum中间件获取共享状态时的Trait Bound错误

我尝试将State(app_state): State<AppState>中的DB池从api.rs传入auth.rs内的authorize函数,该中间件用于JWT保护接口,代码如下:

api.rs

pub fn api_routes() -> Router<AppState> {
    let route = Router::new()
        .route("/api", get(main_page_get).post(main_page_post))
        .route("/api/{query}", get(id_page_get))
        .route("/demo.json", get(get_demo_json).put(put_demo_json))
        .layer(middleware::from_fn(auth::authorize));

    route
}

auth.rs

pub async fn authorize(
    mut req: Request<Body>,
    State(app_state): State<AppState>,
    next: Next
) -> Result<Response<Body>, AuthError> {
    // 逻辑代码
}

在middleware::from_fn(auth::authorize)行出现错误:

the trait bound `axum::middleware::FromFn<fn(http::Request<Body>, axum::extract::State<AppState>, Next) -> impl Future<Output = Result<Response<Body>, AuthError>> {authorize}, (), Route, _>: tower_service::Service<http::Request<Body>>` is not satisfied
the trait `tower_service::Service<http::Request<Body>>` is not implemented for `FromFn<fn(Request<Body>, ..., ...) -> ... {authorize}, ..., ..., ...>`
the following other types implement trait `tower_service::Service<Request>`:
  axum::middleware::FromFn<F, S, I, (T1, T2)>
  axum::middleware::FromFn<F, S, I, (T1, T2, T3)>
  axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4)>
  axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5)>
  axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6)>
  axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6, T7)>
  axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6, T7, T8)>
  axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6, T7, T8, T9)>
and 8 othersrustcClick for full compiler diagnostic
api.rs(17, 10): required by a bound introduced by this call
method_routing.rs(967, 21): required by a bound in `MethodRouter::<S, E>::layer`

补充:共享状态实现

use std::sync::Arc;
use sqlx::postgres::PgPool;

#[derive(Clone)]
pub struct AppState {
    pub html_path: Arc<String>,
    pub db_pool: Arc<PgPool>,
}

impl AppState {
    pub fn new(html_path: String, db_pool: PgPool) -> Self {
        AppState {
            html_path: Arc::new(html_path),
            db_pool: Arc::new(db_pool),
        }
    }
}

解决方案

错误原因是中间件函数的参数顺序不符合Axum的要求:使用from_fn创建中间件时,提取器(比如State)必须放在Request参数之前,最后才是Next参数。

调整auth.rs中authorize函数的参数顺序即可解决:

pub async fn authorize(
    State(app_state): State<AppState>, // 提取器放在最前面
    mut req: Request<Body>,
    next: Next
) -> Result<Response<Body>, AuthError> {
    // 现在可以正常使用app_state.db_pool了
    let _db_pool = app_state.db_pool;
    next.run(req).await
}

另外注意api.rs中.route("/demo.json", ...)的括号缺失,补充完整后代码才能正常编译。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:29:51