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