Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tokio-rs/axum/llms.txt
Use this file to discover all available pages before exploring further.
MatchedPath is an extractor that provides the route pattern (not the actual request path) that matched the current request.
Basic usage
use axum::{Router, routing::get, extract::MatchedPath};
let app = Router::new().route(
"/users/{id}",
get(|path: MatchedPath| async move {
let pattern = path.as_str();
// pattern will be "/users/{id}", not "/users/123"
format!("Matched pattern: {}", pattern)
})
);
The matched path is the route pattern (e.g., /users/{id}), not the actual request URI (e.g., /users/123). Use Uri or OriginalUri to get the actual request path.
Using in middleware
MatchedPath is commonly used in middleware for logging, metrics, and tracing:
use axum::{
Router,
routing::get,
extract::{MatchedPath, Request},
};
use tower_http::trace::TraceLayer;
let app = Router::new()
.route("/users/{id}", get(|| async { /* ... */ }))
.layer(
TraceLayer::new_for_http().make_span_with(|req: &Request<_>| {
let path = if let Some(matched_path) = req.extensions().get::<MatchedPath>() {
matched_path.as_str()
} else {
req.uri().path()
};
tracing::info_span!("http-request", %path)
})
);
Nested routes
When using nested routers, MatchedPath includes the full pattern from all nesting levels:
use axum::{Router, routing::get, extract::MatchedPath};
let api_routes = Router::new().route(
"/{version}",
get(|path: MatchedPath| async move {
// path.as_str() will be "/api/{version}"
path.as_str().to_owned()
})
);
let app = Router::new().nest("/api", api_routes);
MatchedPath won’t be available in fallback handlers or when using nest_service. Use Option<MatchedPath> to handle these cases:
use axum::{Router, routing::get, extract::MatchedPath};
async fn handler(path: Option<MatchedPath>) -> String {
match path {
Some(p) => format!("Matched: {}", p.as_str()),
None => "No matched path available".to_string(),
}
}
let app = Router::new().fallback(handler);
MatchedPath is not available in fallback handlers. It will always be None when extracted in a fallback.
Type signature
Returns a string representation of the matched route pattern.
Rejection
Rejects with MatchedPathMissing if:
- The request didn’t match any route (fallback handler)
- Used with
nest_service instead of nest
- Extracted before routing has occurred
Common use cases
- Structured logging: Group logs by route pattern instead of specific paths
- Metrics collection: Track request counts and latencies per route
- Rate limiting: Apply different rate limits based on route patterns
- Debugging: Understand which route handler is processing a request
Example: Metrics middleware
use axum::{
Router,
routing::get,
extract::Request,
middleware::{self, Next},
response::Response,
};
use std::time::Instant;
async fn track_metrics(req: Request, next: Next) -> Response {
let path = req.extensions()
.get::<axum::extract::MatchedPath>()
.map(|p| p.as_str().to_owned())
.unwrap_or_else(|| "unknown".to_string());
let start = Instant::now();
let response = next.run(req).await;
let duration = start.elapsed();
// Record metrics with route pattern, not specific path
println!("Route: {}, Duration: {:?}", path, duration);
response
}
let app = Router::new()
.route("/users/{id}", get(|| async { "User" }))
.layer(middleware::from_fn(track_metrics));
See also
- Uri - Extract the actual request URI
- OriginalUri - Extract the original URI before nesting modifications