1Provide the state for the router. 2 3```rust 4use axum::{Router, routing::get, extract::State}; 5 6#[derive(Clone)] 7struct AppState {} 8 9let routes = Router::new() 10 .route("/", get(|State(state): State<AppState>| async { 11 // use state 12 })) 13 .with_state(AppState {}); 14 15# async { 16axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 17 .serve(routes.into_make_service()) 18 .await; 19# }; 20``` 21 22# Returning routers with states from functions 23 24When returning `Router`s from functions it is generally recommend not set the 25state directly: 26 27```rust 28use axum::{Router, routing::get, extract::State}; 29 30#[derive(Clone)] 31struct AppState {} 32 33// Don't call `Router::with_state` here 34fn routes() -> Router<AppState> { 35 Router::new() 36 .route("/", get(|_: State<AppState>| async {})) 37} 38 39// Instead do it before you run the server 40let routes = routes().with_state(AppState {}); 41 42# async { 43axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 44 .serve(routes.into_make_service()) 45 .await; 46# }; 47``` 48 49If you do need to provide the state, and you're _not_ nesting/merging the router 50into another router, then return `Router` without any type parameters: 51 52```rust 53# use axum::{Router, routing::get, extract::State}; 54# #[derive(Clone)] 55# struct AppState {} 56# 57// Don't return `Router<AppState>` 58fn routes(state: AppState) -> Router { 59 Router::new() 60 .route("/", get(|_: State<AppState>| async {})) 61 .with_state(state) 62} 63 64let routes = routes(AppState {}); 65 66# async { 67axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 68 .serve(routes.into_make_service()) 69 .await; 70# }; 71``` 72 73This is because we can only call `Router::into_make_service` on `Router<()>`, 74not `Router<AppState>`. See below for more details about why that is. 75 76Note that the state defaults to `()` so `Router` and `Router<()>` is the same. 77 78If you are nesting/merging the router it is recommended to use a generic state 79type on the resulting router: 80 81```rust 82# use axum::{Router, routing::get, extract::State}; 83# #[derive(Clone)] 84# struct AppState {} 85# 86fn routes<S>(state: AppState) -> Router<S> { 87 Router::new() 88 .route("/", get(|_: State<AppState>| async {})) 89 .with_state(state) 90} 91 92let routes = Router::new().nest("/api", routes(AppState {})); 93 94# async { 95axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 96 .serve(routes.into_make_service()) 97 .await; 98# }; 99``` 100 101# State is global within the router 102 103The state passed to this method will be used for all requests this router 104receives. That means it is not suitable for holding state derived from a 105request, such as authorization data extracted in a middleware. Use [`Extension`] 106instead for such data. 107 108# What `S` in `Router<S>` means 109 110`Router<S>` means a router that is _missing_ a state of type `S` to be able to 111handle requests. It does _not_ mean a `Router` that _has_ a state of type `S`. 112 113For example: 114 115```rust 116# use axum::{Router, routing::get, extract::State}; 117# #[derive(Clone)] 118# struct AppState {} 119# 120// A router that _needs_ an `AppState` to handle requests 121let router: Router<AppState> = Router::new() 122 .route("/", get(|_: State<AppState>| async {})); 123 124// Once we call `Router::with_state` the router isn't missing 125// the state anymore, because we just provided it 126// 127// Therefore the router type becomes `Router<()>`, i.e a router 128// that is not missing any state 129let router: Router<()> = router.with_state(AppState {}); 130 131// Only `Router<()>` has the `into_make_service` method. 132// 133// You cannot call `into_make_service` on a `Router<AppState>` 134// because it is still missing an `AppState`. 135# async { 136axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 137 .serve(router.into_make_service()) 138 .await; 139# }; 140``` 141 142Perhaps a little counter intuitively, `Router::with_state` doesn't always return a 143`Router<()>`. Instead you get to pick what the new missing state type is: 144 145```rust 146# use axum::{Router, routing::get, extract::State}; 147# #[derive(Clone)] 148# struct AppState {} 149# 150let router: Router<AppState> = Router::new() 151 .route("/", get(|_: State<AppState>| async {})); 152 153// When we call `with_state` we're able to pick what the next missing state type is. 154// Here we pick `String`. 155let string_router: Router<String> = router.with_state(AppState {}); 156 157// That allows us to add new routes that uses `String` as the state type 158let string_router = string_router 159 .route("/needs-string", get(|_: State<String>| async {})); 160 161// Provide the `String` and choose `()` as the new missing state. 162let final_router: Router<()> = string_router.with_state("foo".to_owned()); 163 164// Since we have a `Router<()>` we can run it. 165# async { 166axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 167 .serve(final_router.into_make_service()) 168 .await; 169# }; 170``` 171 172This why this returning `Router<AppState>` after calling `with_state` doesn't 173work: 174 175```rust,compile_fail 176# use axum::{Router, routing::get, extract::State}; 177# #[derive(Clone)] 178# struct AppState {} 179# 180// This wont work because we're returning a `Router<AppState>` 181// i.e. we're saying we're still missing an `AppState` 182fn routes(state: AppState) -> Router<AppState> { 183 Router::new() 184 .route("/", get(|_: State<AppState>| async {})) 185 .with_state(state) 186} 187 188let app = routes(AppState {}); 189 190// We can only call `Router::into_make_service` on a `Router<()>` 191// but `app` is a `Router<AppState>` 192# async { 193axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 194 .serve(app.into_make_service()) 195 .await; 196# }; 197``` 198 199Instead return `Router<()>` since we have provided all the state needed: 200 201```rust 202# use axum::{Router, routing::get, extract::State}; 203# #[derive(Clone)] 204# struct AppState {} 205# 206// We've provided all the state necessary so return `Router<()>` 207fn routes(state: AppState) -> Router<()> { 208 Router::new() 209 .route("/", get(|_: State<AppState>| async {})) 210 .with_state(state) 211} 212 213let app = routes(AppState {}); 214 215// We can now call `Router::into_make_service` 216# async { 217axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 218 .serve(app.into_make_service()) 219 .await; 220# }; 221``` 222 223# A note about performance 224 225If you need a `Router` that implements `Service` but you don't need any state (perhaps 226you're making a library that uses axum internally) then it is recommended to call this 227method before you start serving requests: 228 229```rust 230use axum::{Router, routing::get}; 231 232let app = Router::new() 233 .route("/", get(|| async { /* ... */ })) 234 // even though we don't need any state, call `with_state(())` anyway 235 .with_state(()); 236# let _: Router = app; 237``` 238 239This is not required but it gives axum a chance to update some internals in the router 240which may impact performance and reduce allocations. 241 242Note that [`Router::into_make_service`] and [`Router::into_make_service_with_connect_info`] 243do this automatically. 244 245[`Extension`]: crate::Extension 246