mirror of
https://github.com/tokio-rs/axum.git
synced 2025-01-01 00:50:32 +01:00
Document sharing state between handler and middleware (#783)
* Fix heading levels * Document passing state from middleware to handlers
This commit is contained in:
parent
49d8fc5093
commit
113a15a713
2 changed files with 64 additions and 2 deletions
|
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- **added:** `middleware::from_fn` for creating middleware from async functions.
|
||||
This previously lived in axum-extra but has been moved to axum ([#719])
|
||||
- **added:** Document sharing state between handler and middleware (#783])
|
||||
- **breaking:** `sse::Event` now accepts types implementing `AsRef<str>` instead of `Into<String>`
|
||||
as field values.
|
||||
- **breaking:** `sse::Event` now panics if a setter method is called twice instead of silently
|
||||
|
@ -65,6 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
[#733]: https://github.com/tokio-rs/axum/pull/733
|
||||
[#734]: https://github.com/tokio-rs/axum/pull/734
|
||||
[#755]: https://github.com/tokio-rs/axum/pull/755
|
||||
[#783]: https://github.com/tokio-rs/axum/pull/783
|
||||
|
||||
# 0.4.4 (13. January, 2022)
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ You should use these when
|
|||
- You want to perform a small ad hoc operation, such as adding a header.
|
||||
- You don't intend to publish your middleware as a crate for others to use.
|
||||
|
||||
# `tower::Service` and `Pin<Box<dyn Future>>`
|
||||
## `tower::Service` and `Pin<Box<dyn Future>>`
|
||||
|
||||
For maximum control (and a more low level API) you can write you own middleware
|
||||
by implementing [`tower::Service`]:
|
||||
|
@ -254,7 +254,7 @@ where
|
|||
}
|
||||
```
|
||||
|
||||
# `tower::Service` and custom futures
|
||||
## `tower::Service` and custom futures
|
||||
|
||||
If you're comfortable implementing your own futures (or want to learn it) and
|
||||
need as much control as possible then using `tower::Service` without boxed
|
||||
|
@ -374,6 +374,64 @@ Also note that handlers created from async functions don't care about
|
|||
backpressure and are always ready. So if you're not using any Tower
|
||||
middleware you don't have to worry about any of this.
|
||||
|
||||
# Sharing state between handlers and middleware
|
||||
|
||||
State can be shared between middleware and handlers using [request extensions]:
|
||||
|
||||
```rust
|
||||
use axum::{
|
||||
Router,
|
||||
http::{Request, StatusCode},
|
||||
routing::get,
|
||||
response::IntoResponse,
|
||||
middleware::{self, Next},
|
||||
extract::Extension,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct CurrentUser { /* ... */ }
|
||||
|
||||
async fn auth<B>(mut req: Request<B>, next: Next<B>) -> impl IntoResponse {
|
||||
let auth_header = req.headers()
|
||||
.get(http::header::AUTHORIZATION)
|
||||
.and_then(|header| header.to_str().ok());
|
||||
|
||||
let auth_header = if let Some(auth_header) = auth_header {
|
||||
auth_header
|
||||
} else {
|
||||
return Err(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
if let Some(current_user) = authorize_current_user(auth_header).await {
|
||||
req.extensions_mut().insert(current_user);
|
||||
Ok(next.run(req).await)
|
||||
} else {
|
||||
Err(StatusCode::UNAUTHORIZED)
|
||||
}
|
||||
}
|
||||
|
||||
async fn authorize_current_user(auth_token: &str) -> Option<CurrentUser> {
|
||||
// ...
|
||||
# unimplemented!()
|
||||
}
|
||||
|
||||
async fn handler(
|
||||
// extract the current user, set by the middleware
|
||||
Extension(current_user): Extension<CurrentUser>,
|
||||
) {
|
||||
// ...
|
||||
}
|
||||
|
||||
let app = Router::new()
|
||||
.route("/", get(handler))
|
||||
.route_layer(middleware::from_fn(auth));
|
||||
# let app: Router = app;
|
||||
```
|
||||
|
||||
[Response extensions] can also be used but note that request extensions are not
|
||||
automatically moved to response extensions. You need to manually do that for the
|
||||
extensions you need.
|
||||
|
||||
[`tower`]: https://crates.io/crates/tower
|
||||
[`tower-http`]: https://crates.io/crates/tower-http
|
||||
[tower-guides]: https://github.com/tower-rs/tower/tree/master/guides
|
||||
|
@ -390,3 +448,5 @@ middleware you don't have to worry about any of this.
|
|||
[`MethodRouter::layer`]: crate::routing::MethodRouter::layer
|
||||
[`Router::route_layer`]: crate::routing::Router::route_layer
|
||||
[`MethodRouter::route_layer`]: crate::routing::MethodRouter::route_layer
|
||||
[request extensions]: https://docs.rs/http/latest/http/request/struct.Request.html#method.extensions
|
||||
[Response extensions]: https://docs.rs/http/latest/http/response/struct.Response.html#method.extensions
|
||||
|
|
Loading…
Reference in a new issue