如何将 axum::extract::Query 和 axum::extract::State 与 Axum 一起使用?

Fin*_*ber 6 rust rust-axum

我正在构建一个需要注入状态并且还需要提取查询参数的处理程序。

我一开始只提取状态并且有效。其代码如下所示:

    #[derive(ValueEnum, Clone, Debug, serde::Deserialze, serde::Serialize)]
    pub enum MyParams {
       Normal,
       Verbose,
    }

    #[derive(Debug)]
   pub struct MyState {
      port: u16,
   }
    
    pub async fn serve(self) {
        let port = self.port;
        let app = Router::new()
            .route("/path", axum::routing::get(path))
            .with_state(Arc::new(self));

        let addr = SocketAddr::from(([127, 0, 0, 1], port));
        axum::Server::bind(&addr)
            .serve(app.into_make_service())
            .await
            .unwrap();
    }

async fn path(State(middle_ware): State<Arc<MyState>>) -> impl IntoResponse {
    let result = middle_ware.process().await;
    (StatusCode::OK, Json(result))
}

Run Code Online (Sandbox Code Playgroud)

现在我想提取查询参数,所以我更新了代码如下:

async fn path(State(middle_ware): State<Arc<MyState>>, params: Query<MyParams>) -> impl IntoResponse {
    println!("{:?}", params);
    let result = middle_ware.process().await;
    (StatusCode::OK, Json(result))
}
Run Code Online (Sandbox Code Playgroud)

但这无法编译并出现错误

    |
24  |             .route("/path", axum::routing::get(path))
    |                                  ------------------ ^^^^^^^^^ the trait `Handler<_, _, _>` is not implemented for fn item `fn(State<Arc<MyState>>, Query<MyParams>) -> impl futures::Future<Output = impl IntoResponse> {path}`
    |                                  |
    |                                  required by a bound introduced by this call

Run Code Online (Sandbox Code Playgroud)

有什么想法可以做什么,以便能够将 axum::extract::Query 和 axum::extract::State 与 Axum 一起使用?

Fra*_*eno 7

该文档提供了以下示例:

https://docs.rs/axum/latest/axum/extract/index.html#applying-multiple-extractors

PS:不要忘记注意提取器的顺序。

use axum::{
    extract::{Path, Query},
    routing::get,
    Router,
};
use uuid::Uuid;
use serde::Deserialize;

let app = Router::new().route("/users/:id/things", get(get_user_things));

#[derive(Deserialize)]
struct Pagination {
    page: usize,
    per_page: usize,
}

impl Default for Pagination {
    fn default() -> Self {
        Self { page: 1, per_page: 30 }
    }
}

async fn get_user_things(
    Path(user_id): Path<Uuid>,
    pagination: Option<Query<Pagination>>,
) {
    let Query(pagination) = pagination.unwrap_or_default();

    // ...
}
Run Code Online (Sandbox Code Playgroud)