poem-web / poem

A full-featured and easy-to-use web framework with the Rust programming language.
Apache License 2.0
3.6k stars 293 forks source link

Tuple vs Struct - Option<T> in Path Extractor #554

Open ToranSharma opened 1 year ago

ToranSharma commented 1 year ago

I have been trying to set up a handler that takes 2 path parameters where the second one is optional.

This only seems to work as I expect when the generic type for the Path parameter is a struct where the second path param is an Option type. But it doesn't work if I try to use a 2 entry tuple type with the second type being an Option.

Is this expected and if so what is the reason?

Here is my attempt at a fairly minimal example

use poem::{handler, test::TestClient, web::Path, Route};

#[derive(serde::Deserialize)]
pub struct TestParams {
    param_1: String,
    param_2: Option<String>,
}

#[handler]
pub fn test_struct_handler(Path(TestParams { param_1, param_2 }): Path<TestParams>) -> String {
    format! {"struct: {param_1} & {param_2:?}"}
}

#[handler]
pub fn test_tuple_handler(Path((param_1, param_2)): Path<(String, Option<String>)>) -> String {
    format! {"tuple: {param_1} & {param_2:?}"}
}

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let app = Route::new()
        .at("/struct/:param_1", test_struct_handler)
        .at("/struct/:param_1/:param_2", test_struct_handler)
        .at("/tuple/:param_1", test_tuple_handler)
        .at("/tuple/:param_1/:param_2", test_tuple_handler);

    let cli = TestClient::new(app);

    cli.get("/struct/foo/bar").send().await
        .assert_text("struct: foo & Some(\"bar\")").await;

    cli.get("/struct/foo").send().await
        .assert_text("struct: foo & None").await;

    cli.get("/tuple/foo/bar").send().await
        .assert_text("tuple: foo & Some(\"bar\")").await;

    cli.get("/tuple/foo").send().await
        .assert_text("tuple: foo & None").await; // This fails with status 400, with message "invalid path params"
}

Thanks!

TheCataliasTNT2k commented 3 months ago

Same problem here.