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
相关产品推荐
相关产品推荐

