1Nest a [`Router`] at some path. 2 3This allows you to break your application into smaller pieces and compose 4them together. 5 6# Example 7 8```rust 9use axum::{ 10 routing::{get, post}, 11 Router, 12}; 13 14let user_routes = Router::new().route("/:id", get(|| async {})); 15 16let team_routes = Router::new().route("/", post(|| async {})); 17 18let api_routes = Router::new() 19 .nest("/users", user_routes) 20 .nest("/teams", team_routes); 21 22let app = Router::new().nest("/api", api_routes); 23 24// Our app now accepts 25// - GET /api/users/:id 26// - POST /api/teams 27# async { 28# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); 29# }; 30``` 31 32# How the URI changes 33 34Note that nested routes will not see the original request URI but instead 35have the matched prefix stripped. This is necessary for services like static 36file serving to work. Use [`OriginalUri`] if you need the original request 37URI. 38 39# Captures from outer routes 40 41Take care when using `nest` together with dynamic routes as nesting also 42captures from the outer routes: 43 44```rust 45use axum::{ 46 extract::Path, 47 routing::get, 48 Router, 49}; 50use std::collections::HashMap; 51 52async fn users_get(Path(params): Path<HashMap<String, String>>) { 53 // Both `version` and `id` were captured even though `users_api` only 54 // explicitly captures `id`. 55 let version = params.get("version"); 56 let id = params.get("id"); 57} 58 59let users_api = Router::new().route("/users/:id", get(users_get)); 60 61let app = Router::new().nest("/:version/api", users_api); 62# async { 63# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); 64# }; 65``` 66 67# Differences from wildcard routes 68 69Nested routes are similar to wildcard routes. The difference is that 70wildcard routes still see the whole URI whereas nested routes will have 71the prefix stripped: 72 73```rust 74use axum::{routing::get, http::Uri, Router}; 75 76let nested_router = Router::new() 77 .route("/", get(|uri: Uri| async { 78 // `uri` will _not_ contain `/bar` 79 })); 80 81let app = Router::new() 82 .route("/foo/*rest", get(|uri: Uri| async { 83 // `uri` will contain `/foo` 84 })) 85 .nest("/bar", nested_router); 86# async { 87# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); 88# }; 89``` 90 91# Fallbacks 92 93If a nested router doesn't have its own fallback then it will inherit the 94fallback from the outer router: 95 96```rust 97use axum::{routing::get, http::StatusCode, handler::Handler, Router}; 98 99async fn fallback() -> (StatusCode, &'static str) { 100 (StatusCode::NOT_FOUND, "Not Found") 101} 102 103let api_routes = Router::new().route("/users", get(|| async {})); 104 105let app = Router::new() 106 .nest("/api", api_routes) 107 .fallback(fallback); 108# let _: Router = app; 109``` 110 111Here requests like `GET /api/not-found` will go into `api_routes` but because 112it doesn't have a matching route and doesn't have its own fallback it will call 113the fallback from the outer router, i.e. the `fallback` function. 114 115If the nested router has its own fallback then the outer fallback will not be 116inherited: 117 118```rust 119use axum::{ 120 routing::get, 121 http::StatusCode, 122 handler::Handler, 123 Json, 124 Router, 125}; 126 127async fn fallback() -> (StatusCode, &'static str) { 128 (StatusCode::NOT_FOUND, "Not Found") 129} 130 131async fn api_fallback() -> (StatusCode, Json<serde_json::Value>) { 132 ( 133 StatusCode::NOT_FOUND, 134 Json(serde_json::json!({ "status": "Not Found" })), 135 ) 136} 137 138let api_routes = Router::new() 139 .route("/users", get(|| async {})) 140 .fallback(api_fallback); 141 142let app = Router::new() 143 .nest("/api", api_routes) 144 .fallback(fallback); 145# let _: Router = app; 146``` 147 148Here requests like `GET /api/not-found` will go to `api_fallback`. 149 150# Nesting routers with state 151 152When combining [`Router`]s with this method, each [`Router`] must have the 153same type of state. If your routers have different types you can use 154[`Router::with_state`] to provide the state and make the types match: 155 156```rust 157use axum::{ 158 Router, 159 routing::get, 160 extract::State, 161}; 162 163#[derive(Clone)] 164struct InnerState {} 165 166#[derive(Clone)] 167struct OuterState {} 168 169async fn inner_handler(state: State<InnerState>) {} 170 171let inner_router = Router::new() 172 .route("/bar", get(inner_handler)) 173 .with_state(InnerState {}); 174 175async fn outer_handler(state: State<OuterState>) {} 176 177let app = Router::new() 178 .route("/", get(outer_handler)) 179 .nest("/foo", inner_router) 180 .with_state(OuterState {}); 181# let _: axum::Router = app; 182``` 183 184Note that the inner router will still inherit the fallback from the outer 185router. 186 187# Panics 188 189- If the route overlaps with another route. See [`Router::route`] 190for more details. 191- If the route contains a wildcard (`*`). 192- If `path` is empty. 193 194[`OriginalUri`]: crate::extract::OriginalUri 195[fallbacks]: Router::fallback 196