pub struct State<S>(pub S);Expand description
Extractor for state.
See “Accessing state in middleware” for how to access state in middleware.
With Router
use axum::{Router, routing::get, extract::State};
// the application state
//
// here you can put configuration, database connection pools, or whatever
// state you need
//
// see "When states need to implement `Clone`" for more details on why we need
// `#[derive(Clone)]` here.
#[derive(Clone)]
struct AppState {}
let state = AppState {};
// create a `Router` that holds our state
let app = Router::new()
.route("/", get(handler))
// provide the state so the router can access it
.with_state(state);
async fn handler(
// access the state via the `State` extractor
// extracting a state of the wrong type results in a compile error
State(state): State<AppState>,
) {
// use `state`...
}Combining stateful routers
Multiple Routers can be combined with Router::nest or Router::merge
When combining Routers with one of these methods, the Routers must have
the same state type. Generally, this can be inferred automatically:
use axum::{Router, routing::get, extract::State};
#[derive(Clone)]
struct AppState {}
let state = AppState {};
// create a `Router` that will be nested within another
let api = Router::new()
.route("/posts", get(posts_handler));
let app = Router::new()
.nest("/api", api)
.with_state(state);
async fn posts_handler(State(state): State<AppState>) {
// use `state`...
}However, if you are composing Routers that are defined in separate scopes,
you may need to annotate the State type explicitly:
use axum::{Router, routing::get, extract::State};
#[derive(Clone)]
struct AppState {}
fn make_app() -> Router {
let state = AppState {};
Router::new()
.nest("/api", make_api())
.with_state(state) // the outer Router's state is inferred
}
// the inner Router must specify its state type to compose with the
// outer router
fn make_api() -> Router<AppState> {
Router::new()
.route("/posts", get(posts_handler))
}
async fn posts_handler(State(state): State<AppState>) {
// use `state`...
}In short, a Router’s generic state type defaults to ()
(no state) unless Router::with_state is called or the value
of the generic type is given explicitly.
With MethodRouter
use axum::{routing::get, extract::State};
#[derive(Clone)]
struct AppState {}
let state = AppState {};
let method_router_with_state = get(handler)
// provide the state so the handler can access it
.with_state(state);
async fn handler(State(state): State<AppState>) {
// use `state`...
}With Handler
use axum::{routing::get, handler::Handler, extract::State};
#[derive(Clone)]
struct AppState {}
let state = AppState {};
async fn handler(State(state): State<AppState>) {
// use `state`...
}
// provide the state so the handler can access it
let handler_with_state = handler.with_state(state);
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(handler_with_state.into_make_service())
.await
.expect("server failed");Substates
State only allows a single state type but you can use FromRef to extract “substates”:
use axum::{Router, routing::get, extract::{State, FromRef}};
// the application state
#[derive(Clone)]
struct AppState {
// that holds some api specific state
api_state: ApiState,
}
// the api specific state
#[derive(Clone)]
struct ApiState {}
// support converting an `AppState` in an `ApiState`
impl FromRef<AppState> for ApiState {
fn from_ref(app_state: &AppState) -> ApiState {
app_state.api_state.clone()
}
}
let state = AppState {
api_state: ApiState {},
};
let app = Router::new()
.route("/", get(handler))
.route("/api/users", get(api_users))
.with_state(state);
async fn api_users(
// access the api specific state
State(api_state): State<ApiState>,
) {
}
async fn handler(
// we can still access to top level state
State(state): State<AppState>,
) {
}For convenience FromRef can also be derived using #[derive(FromRef)].
For library authors
If you’re writing a library that has an extractor that needs state, this is the recommended way to do it:
use axum_core::extract::{FromRequestParts, FromRef};
use http::request::Parts;
use async_trait::async_trait;
use std::convert::Infallible;
// the extractor your library provides
struct MyLibraryExtractor;
#[async_trait]
impl<S> FromRequestParts<S> for MyLibraryExtractor
where
// keep `S` generic but require that it can produce a `MyLibraryState`
// this means users will have to implement `FromRef<UserState> for MyLibraryState`
MyLibraryState: FromRef<S>,
S: Send + Sync,
{
type Rejection = Infallible;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
// get a `MyLibraryState` from a reference to the state
let state = MyLibraryState::from_ref(state);
// ...
}
}
// the state your library needs
struct MyLibraryState {
// ...
}When states need to implement Clone
Your top level state type must implement Clone to be extractable with State:
use axum::extract::State;
// no substates, so to extract to `State<AppState>` we must implement `Clone` for `AppState`
#[derive(Clone)]
struct AppState {}
async fn handler(State(state): State<AppState>) {
// ...
}This works because of impl<S> FromRef<S> for S where S: Clone.
This is also true if you’re extracting substates, unless you never extract the top level state itself:
use axum::extract::{State, FromRef};
// we never extract `State<AppState>`, just `State<InnerState>`. So `AppState` doesn't need to
// implement `Clone`
struct AppState {
inner: InnerState,
}
#[derive(Clone)]
struct InnerState {}
impl FromRef<AppState> for InnerState {
fn from_ref(app_state: &AppState) -> InnerState {
app_state.inner.clone()
}
}
async fn api_users(State(inner): State<InnerState>) {
// ...
}In general however we recommend you implement Clone for all your state types to avoid
potential type errors.
Tuple Fields§
§0: S