Axum optional routing path

I have a method router with a path and want to use it for 2 url path (one have a path and 1 doesn't).
tried to use Option but cannot make it work

let app = Router::new()
    .route("/users/add", get(add_update_user))
    ,route("/users/:id/edit", post(add_update_user))

// here's the code that not working
async fn add_update_user(Path(Some(user_id)): Path<Option<String>>){

}

is it possible to make the method router shared in the above case?

You can't have refutable patterns in function signatures. What should happen if the passed value doesn't match the pattern, after all?

Just put Path(user_id) so that user_id is bound to an Option, and then match on it.

This probably resolves the immediate type error, but to be honest, I'm not sure whether Axum can handle such optional components, or how you think it should work.

If you want to match both /users/12/edit and /users/edit you need two different routes. You can use an optional extractor so you can share a single handler between the two routes, but it doesn't stop you from needing to define two routes

#[tokio::main]
async fn main() {
    // build our application with a single route
    let app = Router::new()
        .route("/users/:id/edit", post(edit_user))
        .route("/users/edit", post(edit_user));

    // run it with hyper on localhost:3000
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

async fn edit_user(path: Option<Path<String>>) -> String {
    format!("{path:?}")
}

When /users/12/edit is the route that is hit, path will be Some(Path("12")). When /users/edit is hit, path will be None.

2 Likes

Thanks for the response.

@semicoleon Yes, I need two routes, and the optional extractor solve the problem Thank you!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.