mirror of
https://github.com/tokio-rs/axum.git
synced 2024-12-29 15:49:16 +01:00
Add docs on using tokio task_local to share state (#2769)
This commit is contained in:
parent
52ae7bb904
commit
35c6f11c94
1 changed files with 61 additions and 0 deletions
|
@ -293,6 +293,67 @@
|
||||||
//! The downside to this approach is that it's a little more verbose than using
|
//! The downside to this approach is that it's a little more verbose than using
|
||||||
//! [`State`] or extensions.
|
//! [`State`] or extensions.
|
||||||
//!
|
//!
|
||||||
|
//! ## Using [tokio's `task_local` macro](https://docs.rs/tokio/1/tokio/macro.task_local.html):
|
||||||
|
//!
|
||||||
|
//! This allows to share state with `IntoResponse` implementations.
|
||||||
|
//!
|
||||||
|
//! ```rust,no_run
|
||||||
|
//! use axum::{
|
||||||
|
//! extract::Request,
|
||||||
|
//! http::{header, StatusCode},
|
||||||
|
//! middleware::{self, Next},
|
||||||
|
//! response::{IntoResponse, Response},
|
||||||
|
//! routing::get,
|
||||||
|
//! Router,
|
||||||
|
//! };
|
||||||
|
//! use tokio::task_local;
|
||||||
|
//!
|
||||||
|
//! #[derive(Clone)]
|
||||||
|
//! struct CurrentUser {
|
||||||
|
//! name: String,
|
||||||
|
//! }
|
||||||
|
//! task_local! {
|
||||||
|
//! pub static USER: CurrentUser;
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! async fn auth(req: Request, next: Next) -> Result<Response, StatusCode> {
|
||||||
|
//! let auth_header = req
|
||||||
|
//! .headers()
|
||||||
|
//! .get(header::AUTHORIZATION)
|
||||||
|
//! .and_then(|header| header.to_str().ok())
|
||||||
|
//! .ok_or(StatusCode::UNAUTHORIZED)?;
|
||||||
|
//! if let Some(current_user) = authorize_current_user(auth_header).await {
|
||||||
|
//! // State is setup here in the middleware
|
||||||
|
//! Ok(USER.scope(current_user, next.run(req)).await)
|
||||||
|
//! } else {
|
||||||
|
//! Err(StatusCode::UNAUTHORIZED)
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//! async fn authorize_current_user(auth_token: &str) -> Option<CurrentUser> {
|
||||||
|
//! Some(CurrentUser {
|
||||||
|
//! name: auth_token.to_string(),
|
||||||
|
//! })
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! struct UserResponse;
|
||||||
|
//!
|
||||||
|
//! impl IntoResponse for UserResponse {
|
||||||
|
//! fn into_response(self) -> Response {
|
||||||
|
//! // State is accessed here in the IntoResponse implementation
|
||||||
|
//! let current_user = USER.with(|u| u.clone());
|
||||||
|
//! (StatusCode::OK, current_user.name).into_response()
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! async fn handler() -> UserResponse {
|
||||||
|
//! UserResponse
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! let app: Router = Router::new()
|
||||||
|
//! .route("/", get(handler))
|
||||||
|
//! .route_layer(middleware::from_fn(auth));
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
//! # Building integrations for axum
|
//! # Building integrations for axum
|
||||||
//!
|
//!
|
||||||
//! Libraries authors that want to provide [`FromRequest`], [`FromRequestParts`], or
|
//! Libraries authors that want to provide [`FromRequest`], [`FromRequestParts`], or
|
||||||
|
|
Loading…
Reference in a new issue