Skip to content

Path extractor Vec<String> deserialization support for wildcard paths #3621

Description

@TristanWasTaken
  • I have looked for existing issues (including closed) about this

Feature Request

The path extractor currently only supports greedy extraction of the entire wildcard path value into a String value. It should also support Vec<T> and handle the value extraction and parsing to T.

Though I personally only need support for Vec<String> :)

Motivation

Currently wildcard values are generally deserialized into a String and the user has to handle value extraction.

For a project I would like to implement nested groups/namespaces, which requires using wildcards. This would require me to handle extracting the path values into a Vec<String> before I can run logic for the strings.

I don't see why axum's Path extractor shouldn't support Vec<String>, so here I am.

Proposal

In axum\src\extract\path\de.rs have ValueDeserializer support serde deserialization with deserialize_seq.

The PathDeserializer would supply the wildcard path as string, which could then be split by / and pushed to the sequence.

Alternatives

Manually implement wildcard String value splitting by / chars for each wildcard route or write a custom path extractor and maybe submit that for axum-extra.

Activity

  1. jplatte commented on Jan 15, 2026

    @jplatte
    Contributor

    To be clear, you're looking for something like this to work, right?

    #[derive(Deserialize)]
    struct PathParams {
        bucket: String,
        key: Vec<String>,
    }
    
    fn get_key_from_bucket(
        Path(params): Path<PathParams>,
        // other extractors
    ) -> impl IntoResponse {
        // handler implementation
    }
    
    router.route("/{bucket}/{*key}", get(get_key_from_bucket));

    I verified that this does not work currently, and I agree that it should. Could take me a while to implement though, I've got a lot of stuff on my plate and the path deserialization code is unfortunately not simple, and not well-commented either.

  2. TristanWasTaken commented on Jan 16, 2026

    @TristanWasTaken
    Author

    @jplatte yes.
    Or from the docs example (https://docs.rs/axum/latest/axum/routing/struct.Router.html#method.route):

    use axum::{
        Router,
        routing::get,
        extract::Path,
    };
    
    let app: Router = Router::new().route("/{*key}", get(handler));
    
    async fn handler(Path(path): Path<Vec<String>>) -> String {
        path
    }

    I'm not familiar with axum's source code so I'm unsure if the path extractor has code at more locations than axum\src\extract\path.

    From what I see, it uses the serde PathDeserializer to parse the route segments and then the serde ValueDeserializer to extract the values.
    Wildcard segments are greedily matched and then forwarded to ValueDeserializer as a string. So I think it is enough to implement serde's deserialize_seq to support Vec<T>?

    I already wrote a prototype that should(?) work. I just kind of got stuck at trying to reuse ValueDeserializer and got into a fight with the borrow checker over lifetimes 😅
    I'll try again this Saturday with owned types and a WildcardValueDeserializer that uses Vec<PercentDecodedStr> instead of &'de PercentDecodedStr.

  3. jplatte commented on Jan 16, 2026

    @jplatte
    Contributor

    Oh, that doesn't work either? I was sure it does, but can't immediately find any tests for it.

    Feel free to post a draft PR even if you can't actually get it to compile. Happy to help.

  4. added this to the 0.9 milestone on Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions