axum/extract/state.rs
1use axum_core::extract::{FromRef, FromRequestParts};
2use http::request::Parts;
3use std::{
4 convert::Infallible,
5 ops::{Deref, DerefMut},
6};
7
8/// Extractor for state.
9///
10/// See ["Sharing state with handlers"][sharing-state] for an overview of all approaches to
11/// sharing state, including when to use `Arc`, how `FromRef` substates work, and what the
12/// `Router<S>` type parameter means.
13///
14/// See ["Accessing state in middleware"][state-from-middleware] for how to
15/// access state in middleware.
16///
17/// State is global and used in every request a router with state receives.
18/// For accessing data derived from requests, such as authorization data, see [`Extension`].
19///
20/// [sharing-state]: crate#sharing-state-with-handlers
21/// [state-from-middleware]: crate::middleware#accessing-state-in-middleware
22/// [`Extension`]: crate::Extension
23///
24/// # With `Router`
25///
26/// ```
27/// use axum::{Router, routing::get, extract::State};
28///
29/// // the application state
30/// //
31/// // here you can put configuration, database connection pools, or whatever
32/// // state you need
33/// #[derive(Clone)]
34/// struct AppState {}
35///
36/// let state = AppState {};
37///
38/// // create a `Router` that holds our state
39/// let app = Router::new()
40/// .route("/", get(handler))
41/// // provide the state so the router can access it
42/// .with_state(state);
43///
44/// async fn handler(
45/// // access the state via the `State` extractor
46/// // extracting a state of the wrong type results in a compile error
47/// State(state): State<AppState>,
48/// ) {
49/// // use `state`...
50/// }
51/// # let _: axum::Router = app;
52/// ```
53///
54/// Note that `State` is an extractor, so be sure to put it before any body
55/// extractors, see ["the order of extractors"][order-of-extractors].
56///
57/// [order-of-extractors]: crate::extract#the-order-of-extractors
58///
59/// ## Combining stateful routers
60///
61/// Multiple [`Router`]s can be combined with [`Router::nest`] or [`Router::merge`]
62/// When combining [`Router`]s with one of these methods, the [`Router`]s must have
63/// the same state type. Generally, this can be inferred automatically:
64///
65/// ```
66/// use axum::{Router, routing::get, extract::State};
67///
68/// #[derive(Clone)]
69/// struct AppState {}
70///
71/// let state = AppState {};
72///
73/// // create a `Router` that will be nested within another
74/// let api = Router::new()
75/// .route("/posts", get(posts_handler));
76///
77/// let app = Router::new()
78/// .nest("/api", api)
79/// .with_state(state);
80///
81/// async fn posts_handler(State(state): State<AppState>) {
82/// // use `state`...
83/// }
84/// # let _: axum::Router = app;
85/// ```
86///
87/// However, if you are composing [`Router`]s that are defined in separate scopes,
88/// you may need to annotate the [`State`] type explicitly:
89///
90/// ```
91/// use axum::{Router, routing::get, extract::State};
92///
93/// #[derive(Clone)]
94/// struct AppState {}
95///
96/// fn make_app() -> Router {
97/// let state = AppState {};
98///
99/// Router::new()
100/// .nest("/api", make_api())
101/// .with_state(state) // the outer Router's state is inferred
102/// }
103///
104/// // the inner Router must specify its state type to compose with the
105/// // outer router
106/// fn make_api() -> Router<AppState> {
107/// Router::new()
108/// .route("/posts", get(posts_handler))
109/// }
110///
111/// async fn posts_handler(State(state): State<AppState>) {
112/// // use `state`...
113/// }
114/// # let _: axum::Router = make_app();
115/// ```
116///
117/// In short, a [`Router`]'s generic state type defaults to `()`
118/// (no state) unless [`Router::with_state`] is called or the value
119/// of the generic type is given explicitly.
120///
121/// [`Router`]: crate::Router
122/// [`Router::merge`]: crate::Router::merge
123/// [`Router::nest`]: crate::Router::nest
124/// [`Router::with_state`]: crate::Router::with_state
125///
126/// # With `MethodRouter`
127///
128/// ```
129/// use axum::{routing::get, extract::State};
130///
131/// #[derive(Clone)]
132/// struct AppState {}
133///
134/// let state = AppState {};
135///
136/// let method_router_with_state = get(handler)
137/// // provide the state so the handler can access it
138/// .with_state(state);
139/// # let _: axum::routing::MethodRouter = method_router_with_state;
140///
141/// async fn handler(State(state): State<AppState>) {
142/// // use `state`...
143/// }
144/// ```
145///
146/// # With `Handler`
147///
148/// ```
149/// use axum::{routing::get, handler::Handler, extract::State};
150///
151/// #[derive(Clone)]
152/// struct AppState {}
153///
154/// let state = AppState {};
155///
156/// async fn handler(State(state): State<AppState>) {
157/// // use `state`...
158/// }
159///
160/// // provide the state so the handler can access it
161/// let handler_with_state = handler.with_state(state);
162///
163/// # async {
164/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
165/// axum::serve(listener, handler_with_state.into_make_service()).await.unwrap();
166/// # };
167/// ```
168///
169/// # Substates
170///
171/// [`State`] only allows a single state type but you can use [`FromRef`] to extract "substates":
172///
173/// ```
174/// use axum::{Router, routing::get, extract::{State, FromRef}};
175///
176/// // the application state
177/// #[derive(Clone)]
178/// struct AppState {
179/// // that holds some api specific state
180/// api_state: ApiState,
181/// }
182///
183/// // the api specific state
184/// #[derive(Clone)]
185/// struct ApiState {}
186///
187/// // support converting an `AppState` in an `ApiState`
188/// impl FromRef<AppState> for ApiState {
189/// fn from_ref(app_state: &AppState) -> ApiState {
190/// app_state.api_state.clone()
191/// }
192/// }
193///
194/// let state = AppState {
195/// api_state: ApiState {},
196/// };
197///
198/// let app = Router::new()
199/// .route("/", get(handler))
200/// .route("/api/users", get(api_users))
201/// .with_state(state);
202///
203/// async fn api_users(
204/// // access the api specific state
205/// State(api_state): State<ApiState>,
206/// ) {
207/// }
208///
209/// async fn handler(
210/// // we can still access to top level state
211/// State(state): State<AppState>,
212/// ) {
213/// }
214/// # let _: axum::Router = app;
215/// ```
216///
217/// For convenience `FromRef` can also be derived using `#[derive(FromRef)]`.
218///
219/// # For library authors
220///
221/// If you're writing a library that has an extractor that needs state, this is the recommended way
222/// to do it:
223///
224/// ```rust
225/// use axum_core::extract::{FromRequestParts, FromRef};
226/// use http::request::Parts;
227/// use std::convert::Infallible;
228///
229/// // the extractor your library provides
230/// struct MyLibraryExtractor;
231///
232/// impl<S> FromRequestParts<S> for MyLibraryExtractor
233/// where
234/// // keep `S` generic but require that it can produce a `MyLibraryState`
235/// // this means users will have to implement `FromRef<UserState> for MyLibraryState`
236/// MyLibraryState: FromRef<S>,
237/// S: Send + Sync,
238/// {
239/// type Rejection = Infallible;
240///
241/// async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
242/// // get a `MyLibraryState` from a reference to the state
243/// let state = MyLibraryState::from_ref(state);
244///
245/// // ...
246/// # todo!()
247/// }
248/// }
249///
250/// // the state your library needs
251/// struct MyLibraryState {
252/// // ...
253/// }
254/// ```
255///
256/// # Shared mutable state
257///
258/// [As state is global within a `Router`][global] you can't directly get a mutable reference to
259/// the state.
260///
261/// The most basic solution is to use an `Arc<Mutex<_>>`. Which kind of mutex you need depends on
262/// your use case. See [the tokio docs] for more details.
263///
264/// Note that holding a locked `std::sync::Mutex` across `.await` points will result in `!Send`
265/// futures which are incompatible with axum. If you need to hold a mutex across `.await` points,
266/// consider using a `tokio::sync::Mutex` instead.
267///
268/// ## Example
269///
270/// ```
271/// use axum::{Router, routing::get, extract::State};
272/// use std::sync::{Arc, Mutex};
273///
274/// #[derive(Clone)]
275/// struct AppState {
276/// data: Arc<Mutex<String>>,
277/// }
278///
279/// async fn handler(State(state): State<AppState>) {
280/// {
281/// let mut data = state.data.lock().expect("mutex was poisoned");
282/// *data = "updated foo".to_owned();
283/// }
284///
285/// // ...
286/// }
287///
288/// let state = AppState {
289/// data: Arc::new(Mutex::new("foo".to_owned())),
290/// };
291///
292/// let app = Router::new()
293/// .route("/", get(handler))
294/// .with_state(state);
295/// # let _: Router = app;
296/// ```
297///
298/// [global]: crate::Router::with_state
299/// [the tokio docs]: https://docs.rs/tokio/1.25.0/tokio/sync/struct.Mutex.html#which-kind-of-mutex-should-you-use
300#[derive(Debug, Default, Clone, Copy)]
301pub struct State<S>(pub S);
302
303impl<OuterState, InnerState> FromRequestParts<OuterState> for State<InnerState>
304where
305 InnerState: FromRef<OuterState>,
306 OuterState: Send + Sync,
307{
308 type Rejection = Infallible;
309
310 async fn from_request_parts(
311 _parts: &mut Parts,
312 state: &OuterState,
313 ) -> Result<Self, Self::Rejection> {
314 let inner_state = InnerState::from_ref(state);
315 Ok(Self(inner_state))
316 }
317}
318
319impl<S> Deref for State<S> {
320 type Target = S;
321
322 fn deref(&self) -> &Self::Target {
323 &self.0
324 }
325}
326
327impl<S> DerefMut for State<S> {
328 fn deref_mut(&mut self) -> &mut Self::Target {
329 &mut self.0
330 }
331}