Extractor that will get captures from the URL and parse them using serde.
Any percent encoded parameters will be automatically decoded. The decoded parameters must be valid UTF-8, otherwise Path will fail and return a 400 Bad Request response.
Type signature
pub struct Path<T>(pub T);
Usage
Single parameter
If the path contains only one parameter, you can omit the tuple:
use axum::{
extract::Path,
routing::get,
Router,
};
use uuid::Uuid;
async fn user_info(Path(user_id): Path<Uuid>) {
// user_id is a Uuid
}
let app = Router::new().route("/users/{user_id}", get(user_info));
Multiple parameters with tuple
use axum::{
extract::Path,
routing::get,
Router,
};
use uuid::Uuid;
async fn users_teams_show(
Path((user_id, team_id)): Path<(Uuid, Uuid)>,
) {
// user_id and team_id are both Uuid
}
let app = Router::new()
.route("/users/{user_id}/team/{team_id}", get(users_teams_show));
Multiple parameters with struct
Path segment labels will be matched with struct field names:
use axum::{
extract::Path,
routing::get,
Router,
};
use serde::Deserialize;
use uuid::Uuid;
#[derive(Deserialize)]
struct Params {
user_id: Uuid,
team_id: Uuid,
}
async fn users_teams_show(
Path(Params { user_id, team_id }): Path<Params>,
) {
// use user_id and team_id
}
let app = Router::new()
.route("/users/{user_id}/team/{team_id}", get(users_teams_show));
Capturing all parameters
You can use HashMap or Vec to capture all path parameters:
use axum::{
extract::Path,
routing::get,
Router,
};
use std::collections::HashMap;
async fn params_map(
Path(params): Path<HashMap<String, String>>,
) {
// params contains all path parameters as key-value pairs
}
async fn params_vec(
Path(params): Path<Vec<(String, String)>>,
) {
// params contains all path parameters as tuples
}
let app = Router::new()
.route("/users/{user_id}/team/{team_id}",
get(params_map).post(params_vec));
Error handling
Returned when path parameters cannot be deserialized into the target type.
Error kinds
The PathRejection type contains an ErrorKind enum with detailed error information:
WrongNumberOfParameters - The URI contained a different number of parameters than expected
ParseErrorAtKey - Failed to parse a value at a specific key (for structs)
ParseErrorAtIndex - Failed to parse a value at a specific index (for tuples)
ParseError - Failed to parse a value (for primitives)
InvalidUtf8InPathParam - A parameter contained invalid UTF-8 after percent decoding
UnsupportedType - Attempted to deserialize into an unsupported type
DeserializeError - Custom deserialization error
Customizing rejections
See the customize-path-rejection example for how to provide custom error responses.
Optional path parameters
You can use Option<Path<T>> to allow the same handler to be used in routes with and without parameters:
async fn handler(path: Option<Path<String>>) {
match path {
Some(Path(param)) => {
// Route had a parameter
}
None => {
// Route had no parameters
}
}
}
Percent decoding
Path parameters are automatically percent decoded. For example, %20 becomes a space:
// GET /files/my%20document.pdf
async fn handler(Path(filename): Path<String>) {
// filename = "my document.pdf"
}
Raw path parameters
For lower-level access without deserialization, use RawPathParams:
use axum::extract::RawPathParams;
async fn handler(params: RawPathParams) {
for (key, value) in ¶ms {
println!("{key} = {value}");
}
}