salvo-rs / salvo

A powerful web framework built with a simplified design.
https://salvo.rs
Apache License 2.0
3.26k stars 197 forks source link

使用PathParam时,路由通配符<**id>不生效 #842

Closed z91300 closed 1 month ago

z91300 commented 1 month ago

Is your feature request related to a problem? Please describe. 定义了两个路由,分别为以下:↓

路由1:

Router::with_path("/system/roles").get(role_controller::get_list)

路由2:

Router::with_path("/system/roles/<id>").get(role_controller::get_one)

路由2相关代码定义:

use salvo::{
    oapi::{endpoint, extract::PathParam},
    Depot, Writer,
};
......

/// 获取单条角色
#[endpoint(operation_id = "system_role_findById", tags("系统->角色"))]
pub async fn get_one(
    id: PathParam<i64>,
    depot: &mut Depot,
) -> Result<AppResponse<SysRoleModel>, AppError> {
    let ctx = depot.obtain_mut::<Context>().unwrap();
    // let real_id = transform::decrypt_id(&*id)?;

    let result = role_service::view(ctx, *id).await;
    Ok(AppResponse(result))
}

具体情况

但当访问 /system/roles/ 路由时,即前端传参id可能为undefined时 期望:走路由2,然后报错id不存在 实际:走路由1

相关尝试:

// 1
Router::with_path("/system/roles/<**id>").get(role_controller::get_one)
// 2
Router::with_path("/system/roles/<**>").get(role_controller::get_one)

报错信息:

path parameter id not found or convert to type failed

Describe the solution you'd like 在使用endpoint openapi的情况下,也能通过**通配符或者其它方案实现上述期望

Describe alternatives you've considered

Additional context

z91300 commented 1 month ago

使用 router-params 分支进行测试后还是无法实现上述效果

测试路由及对应结果如下: 75dabefa9ddc957d76b22b5c34a093a

chrislearn commented 1 month ago

我这么测试没有问题哈, 已经合并主分支,直接主分支上测试。

use salvo::oapi::extract::*;
use salvo::prelude::*;

#[endpoint]
async fn hello_id(id: PathParam<String>) -> String {
    format!("Hello, {}!", id.into_inner())
}

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().init();

    let router = Router::new()
    .push(Router::with_path("<**id>").get(hello_id));

    let doc = OpenApi::new("test api", "0.0.1").merge_router(&router);

    let router = router
        .unshift(doc.into_router("/api-doc/openapi.json"))
        .unshift(SwaggerUi::new("/api-doc/openapi.json").into_router("/swagger-ui"));

    let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}
chrislearn commented 1 month ago

image