Skip to content

Commit 1feb879

Browse files
kazeyanns
andcommitted
docs: consolidate state management docs in crate root (#3683)
Co-authored-by: Yann Simon <yann.simon.fr@gmail.com>
1 parent ba6e0d3 commit 1feb879

4 files changed

Lines changed: 61 additions & 1 deletion

File tree

axum-core/src/extract/from_ref.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/// Used to do reference-to-value conversions thus not consuming the input value.
22
///
33
/// This is mainly used with [`State`] to extract "substates" from a reference to main application
4-
/// state.
4+
/// state. See ["Sharing state with handlers"][sharing-state] for a worked example.
55
///
66
/// See [`State`] for more details on how library authors should use this trait.
77
///
88
/// This trait can be derived using `#[derive(FromRef)]`.
99
///
1010
/// [`State`]: https://docs.rs/axum/0.8/axum/extract/struct.State.html
11+
/// [sharing-state]: https://docs.rs/axum/0.8/axum/index.html#sharing-state-with-handlers
1112
// NOTE: This trait is defined in axum-core, even though it is mainly used with `State` which is
1213
// defined in axum. That allows crate authors to use it when implementing extractors.
1314
pub trait FromRef<T> {

axum/src/docs/routing/with_state.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Provide the state for the router. State passed to this method is global and will be used
22
for all requests this router receives. That means it is not suitable for holding state derived from a request, such as authorization data extracted in a middleware. Use [`Extension`] instead for such data.
33

4+
See ["Sharing state with handlers"][sharing-state] for an overview of state patterns,
5+
including when to use `Arc`, how to extract substates with [`FromRef`], and what the
6+
`Router<S>` type parameter means.
7+
8+
[sharing-state]: crate#sharing-state-with-handlers
9+
[`FromRef`]: crate::extract::FromRef
10+
411
```rust
512
use axum::{Router, routing::get, extract::State};
613

axum/src/extract/state.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ use std::{
77

88
/// Extractor for state.
99
///
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+
///
1014
/// See ["Accessing state in middleware"][state-from-middleware] for how to
1115
/// access state in middleware.
1216
///
1317
/// State is global and used in every request a router with state receives.
1418
/// For accessing data derived from requests, such as authorization data, see [`Extension`].
1519
///
20+
/// [sharing-state]: crate#sharing-state-with-handlers
1621
/// [state-from-middleware]: crate::middleware#accessing-state-in-middleware
1722
/// [`Extension`]: crate::Extension
1823
///

axum/src/lib.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,51 @@
183183
//! # let _: Router = app;
184184
//! ```
185185
//!
186+
//! State is cloned for every request. Wrapping your state in `Arc` makes those
187+
//! clones cheap. If all fields are already cheap to clone (for example, each field
188+
//! is itself an `Arc` or a copy type), you can `#[derive(Clone)]` directly on the
189+
//! struct instead.
190+
//!
191+
//! ### Substates with `FromRef`
192+
//!
193+
//! When a handler only needs part of the application state, use [`FromRef`] to extract
194+
//! a substate. Implement the trait manually, or derive it with `#[derive(FromRef)]`
195+
//! (requires the `macros` feature):
196+
//!
197+
//! ```rust
198+
//! use axum::{Router, routing::get, extract::{State, FromRef}};
199+
//!
200+
//! #[derive(Clone)]
201+
//! struct AppState {
202+
//! api_state: ApiState,
203+
//! }
204+
//!
205+
//! #[derive(Clone)]
206+
//! struct ApiState {}
207+
//!
208+
//! // Teach axum how to produce an `ApiState` from a reference to `AppState`.
209+
//! impl FromRef<AppState> for ApiState {
210+
//! fn from_ref(app_state: &AppState) -> ApiState {
211+
//! app_state.api_state.clone()
212+
//! }
213+
//! }
214+
//!
215+
//! let app = Router::new()
216+
//! .route("/", get(handler))
217+
//! .with_state(AppState { api_state: ApiState {} });
218+
//!
219+
//! // This handler receives only the `ApiState` slice; it never sees `AppState`.
220+
//! async fn handler(State(api_state): State<ApiState>) {}
221+
//! # let _: Router = app;
222+
//! ```
223+
//!
224+
//! ### The `Router<S>` type parameter
225+
//!
226+
//! `Router<S>` when `S` is not `()` means a router that is _missing_ a state of type `S`. Calling
227+
//! [`.with_state(s)`][Router::with_state] provides that state and typically produces a
228+
//! `Router<()>`, which is the only form that can be passed to [`serve()`]. See
229+
//! [`Router::with_state`] for a full explanation.
230+
//!
186231
//! You should prefer using [`State`] if possible since it's more type safe. The downside is that
187232
//! it's less dynamic than task-local variables and request extensions.
188233
//!
@@ -426,6 +471,8 @@
426471
//! [load shed]: tower::load_shed
427472
//! [`axum-core`]: http://crates.io/crates/axum-core
428473
//! [`State`]: crate::extract::State
474+
//! [`FromRef`]: crate::extract::FromRef
475+
//! [`Router::with_state`]: crate::routing::Router::with_state
429476
430477
#![cfg_attr(docsrs, feature(doc_cfg))]
431478
#![cfg_attr(test, allow(clippy::float_cmp))]

0 commit comments

Comments
 (0)