axum one route multiple excluding url parameter types

393 views Asked by At

I want to create these routes in axum:

/v1/users/:username  # String
/v1/users/:user_id   # u64

But creating these routes:

Router::new()
    .route("/v1/users/:username", get(get_user))
    .route("/v1/users/:user_id", get(get_user))

Is not possible due to this error:

thread 'main' panicked at 'Invalid route "/v1/users/:user_id": insertion failed due to conflict with previously registered route: /v1/users/:username'

How can I create the same route which accepts many different URL-Parameter types?

1

There are 1 answers

0
Aleksander Krauze On BEST ANSWER

This doesn't even make sense on a conceptual level. Imagine you receive a request with uri path /v1/users/12345. How should the 12345 part be interpreted? As a username, or as a numeric id? If you have some internal logic that for example requires that username must start with a letter, then you could do the following:

  1. Add a single route route("/v1/users/:username-or-id", get(get_user)).

  2. In get_user handler use Path(String) extractor.

  3. Inside get_user manually try to parse path segment and use different business logic depending on the result.

For example:

async fn get_user(Path(username_or_id): Path<String>) -> impl IntoResponse {
    if let Ok(numeric_id) = username_or_id.parse::<u64>() {
        // use `numeric_id: u64`
    } else {
        let username = username_or_id;
        // use `username: String`
    }
}

Instead of this you could just have two separate endpoints, which probably will be clearer and harder to misuse.

/v1/users/:username  # String
/v1/users/id/:user_id   # u64