Struct Path

struct Path<T>(693)

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.

Option<Path<T>> behavior

You can use Option<Path<T>> as an extractor to allow the same handler to be used in a route with parameters that deserialize to T, and another route with no parameters at all.

Example

These examples assume the serde feature of the uuid crate is enabled.

One Path can extract multiple captures. It is not necessary (and does not work) to give a handler more than one Path argument.

use axum::{
    extract::Path,
    routing::get,
    Router,
};
use uuid::Uuid;

async fn users_teams_show(
    Path((user_id, team_id)): Path<(Uuid, Uuid)>,
) {
    // ...
}

let app = Router::new().route("/users/{user_id}/team/{team_id}", get(users_teams_show));
# let _: Router = app;

If the path contains only one parameter, then you can omit the tuple.

use axum::{
    extract::Path,
    routing::get,
    Router,
};
use uuid::Uuid;

async fn user_info(Path(user_id): Path<Uuid>) {
    // ...
}

let app = Router::new().route("/users/{user_id}", get(user_info));
# let _: Router = app;

Path segments also can be deserialized into any type that implements serde::Deserialize. This includes tuples and structs:

use axum::{
    extract::Path,
    routing::get,
    Router,
};
use serde::Deserialize;
use uuid::Uuid;

// Path segment labels will be matched with struct field names
#[derive(Deserialize)]
struct Params {
    user_id: Uuid,
    team_id: Uuid,
}

async fn users_teams_show(
    Path(Params { user_id, team_id }): Path<Params>,
) {
    // ...
}

// When using tuples the path segments will be matched by their position in the route
async fn users_teams_create(
    Path((user_id, team_id)): Path<(String, String)>,
) {
    // ...
}

let app = Router::new().route(
    "/users/{user_id}/team/{team_id}",
    get(users_teams_show).post(users_teams_create),
);
# let _: Router = app;

If you wish to capture all path parameters you can use HashMap or Vec:

use axum::{
    extract::Path,
    routing::get,
    Router,
};
use std::collections::HashMap;

async fn params_map(
    Path(params): Path<HashMap<String, String>>,
) {
    // ...
}

async fn params_vec(
    Path(params): Path<Vec<(String, String)>>,
) {
    // ...
}

let app = Router::new()
    .route("/users/{user_id}/team/{team_id}", get(params_map).post(params_vec));
# let _: Router = app;

Providing detailed rejection output

If the URI cannot be deserialized into the target type the request will be rejected and an error response will be returned. See customize-path-rejection for an example of how to customize that error.

Implementations

impl<P, T> Receiver for Path<T>

impl<R> Rng for Path<T>

impl<R> TryCryptoRng for Path<T>

impl<R> TryRngCore for Path<T>

fn try_next_u32(self: &mut Self) -> Result<u32, <R as TryRngCore>::Error>
fn try_next_u64(self: &mut Self) -> Result<u64, <R as TryRngCore>::Error>
fn try_fill_bytes(self: &mut Self, dst: &mut [u8]) -> Result<(), <R as TryRngCore>::Error>

impl<S, T> FromRequest for Path<T>

fn from_request(req: Request<Body>, state: &S) -> impl Future<Output = Result<T, <T as FromRequest<S, ViaParts>>::Rejection>>

impl<T> Any for Path<T>

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for Path<T>

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for Path<T>

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> CryptoRng for Path<T>

impl<T> Deref for Path<T>

fn deref(self: &Self) -> &<Self as >::Target

impl<T> DerefMut for Path<T>

fn deref_mut(self: &mut Self) -> &mut <Self as >::Target

impl<T> Freeze for Path<T>

impl<T> From for Path<T>

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> Instrument for Path<T>

impl<T> RefUnwindSafe for Path<T>

impl<T> RngCore for Path<T>

fn next_u32(self: &mut Self) -> u32
fn next_u64(self: &mut Self) -> u64
fn fill_bytes(self: &mut Self, dst: &mut [u8])

impl<T> Same for Path<T>

impl<T> Send for Path<T>

impl<T> Sync for Path<T>

impl<T> Unpin for Path<T>

impl<T> UnwindSafe for Path<T>

impl<T> WithSubscriber for Path<T>

impl<T, S> FromRequestParts for Path<T>

async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, <Self as >::Rejection>

impl<T, S> OptionalFromRequestParts for Path<T>

async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Option<Self>, <Self as >::Rejection>

impl<T, U> Into for Path<T>

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom for Path<T>

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for Path<T>

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>

impl<T: $crate::fmt::Debug> Debug for Path<T>

fn fmt(self: &Self, f: &mut $crate::fmt::Formatter<'_>) -> $crate::fmt::Result

impl<V, T> VZip for Path<T>

fn vzip(self: Self) -> V