mirror of
https://github.com/tokio-rs/axum.git
synced 2025-09-30 14:31:16 +00:00
Expand middleware docs (#239)
Adds docs on - Commonly used middleware - Writing your own middleware - Links to tower's guides
This commit is contained in:
parent
2322d39800
commit
dbab5a84b4
120
src/lib.rs
120
src/lib.rs
@ -17,6 +17,9 @@
|
|||||||
//! - [To individual handlers](#to-individual-handlers)
|
//! - [To individual handlers](#to-individual-handlers)
|
||||||
//! - [To groups of routes](#to-groups-of-routes)
|
//! - [To groups of routes](#to-groups-of-routes)
|
||||||
//! - [Error handling](#error-handling)
|
//! - [Error handling](#error-handling)
|
||||||
|
//! - [Applying multiple middleware](#applying-multiple-middleware)
|
||||||
|
//! - [Commonly used middleware](#commonly-used-middleware)
|
||||||
|
//! - [Writing your own middleware](#writing-your-own-middleware)
|
||||||
//! - [Sharing state with handlers](#sharing-state-with-handlers)
|
//! - [Sharing state with handlers](#sharing-state-with-handlers)
|
||||||
//! - [Required dependencies](#required-dependencies)
|
//! - [Required dependencies](#required-dependencies)
|
||||||
//! - [Examples](#examples)
|
//! - [Examples](#examples)
|
||||||
@ -605,7 +608,10 @@
|
|||||||
//! # Applying middleware
|
//! # Applying middleware
|
||||||
//!
|
//!
|
||||||
//! axum is designed to take full advantage of the tower and tower-http
|
//! axum is designed to take full advantage of the tower and tower-http
|
||||||
//! ecosystem of middleware:
|
//! ecosystem of middleware.
|
||||||
|
//!
|
||||||
|
//! If you're new to tower we recommend you read its [guides][tower-guides] for
|
||||||
|
//! a general introduction to tower and its concepts.
|
||||||
//!
|
//!
|
||||||
//! ## To individual handlers
|
//! ## To individual handlers
|
||||||
//!
|
//!
|
||||||
@ -751,6 +757,116 @@
|
|||||||
//! # };
|
//! # };
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! ## Commonly used middleware
|
||||||
|
//!
|
||||||
|
//! [`tower::util`] and [`tower_http`] have a large collection of middleware that are compatible
|
||||||
|
//! with axum. Some commonly used are:
|
||||||
|
//!
|
||||||
|
//! ```rust,no_run
|
||||||
|
//! use axum::{
|
||||||
|
//! body::{Body, BoxBody},
|
||||||
|
//! handler::get,
|
||||||
|
//! http::{Request, Response},
|
||||||
|
//! Router,
|
||||||
|
//! };
|
||||||
|
//! use tower::{
|
||||||
|
//! filter::AsyncFilterLayer,
|
||||||
|
//! util::AndThenLayer,
|
||||||
|
//! ServiceBuilder,
|
||||||
|
//! };
|
||||||
|
//! use std::convert::Infallible;
|
||||||
|
//! use tower_http::trace::TraceLayer;
|
||||||
|
//!
|
||||||
|
//! let middleware_stack = ServiceBuilder::new()
|
||||||
|
//! // `TraceLayer` adds high level tracing and logging
|
||||||
|
//! .layer(TraceLayer::new_for_http())
|
||||||
|
//! // `AsyncFilterLayer` lets you asynchronously transform the request
|
||||||
|
//! .layer(AsyncFilterLayer::new(map_request))
|
||||||
|
//! // `AndThenLayer` lets you asynchronously transform the response
|
||||||
|
//! .layer(AndThenLayer::new(map_response))
|
||||||
|
//! .into_inner();
|
||||||
|
//!
|
||||||
|
//! async fn map_request(req: Request<Body>) -> Result<Request<Body>, Infallible> {
|
||||||
|
//! Ok(req)
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! async fn map_response(res: Response<BoxBody>) -> Result<Response<BoxBody>, Infallible> {
|
||||||
|
//! Ok(res)
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! let app = Router::new()
|
||||||
|
//! .route("/", get(|| async { /* ... */ }))
|
||||||
|
//! .layer(middleware_stack);
|
||||||
|
//! # async {
|
||||||
|
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||||
|
//! # };
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Additionally axum provides [`extract::extractor_middleware()`] for converting any extractor into
|
||||||
|
//! a middleware. Among other things, this can be useful for doing authorization. See
|
||||||
|
//! [`extract::extractor_middleware()`] for more details.
|
||||||
|
//!
|
||||||
|
//! ## Writing your own middleware
|
||||||
|
//!
|
||||||
|
//! You can also write you own middleware by implementing [`tower::Service`]:
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! use axum::{
|
||||||
|
//! body::{Body, BoxBody},
|
||||||
|
//! handler::get,
|
||||||
|
//! http::{Request, Response},
|
||||||
|
//! Router,
|
||||||
|
//! };
|
||||||
|
//! use futures::future::BoxFuture;
|
||||||
|
//! use tower::{Service, layer::layer_fn};
|
||||||
|
//! use std::task::{Context, Poll};
|
||||||
|
//!
|
||||||
|
//! #[derive(Clone)]
|
||||||
|
//! struct MyMiddleware<S> {
|
||||||
|
//! inner: S,
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! impl<S, ReqBody, ResBody> Service<Request<ReqBody>> for MyMiddleware<S>
|
||||||
|
//! where
|
||||||
|
//! S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||||
|
//! S::Future: Send + 'static,
|
||||||
|
//! ReqBody: Send + 'static,
|
||||||
|
//! ResBody: Send + 'static,
|
||||||
|
//! {
|
||||||
|
//! type Response = S::Response;
|
||||||
|
//! type Error = S::Error;
|
||||||
|
//! type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||||
|
//!
|
||||||
|
//! fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
//! self.inner.poll_ready(cx)
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn call(&mut self, mut req: Request<ReqBody>) -> Self::Future {
|
||||||
|
//! println!("`MyMiddleware` called!");
|
||||||
|
//!
|
||||||
|
//! // best practice is to clone the inner service like this
|
||||||
|
//! // see https://github.com/tower-rs/tower/issues/547 for details
|
||||||
|
//! let clone = self.inner.clone();
|
||||||
|
//! let mut inner = std::mem::replace(&mut self.inner, clone);
|
||||||
|
//!
|
||||||
|
//! Box::pin(async move {
|
||||||
|
//! let res: Response<ResBody> = inner.call(req).await?;
|
||||||
|
//!
|
||||||
|
//! println!("`MyMiddleware` received the response");
|
||||||
|
//!
|
||||||
|
//! Ok(res)
|
||||||
|
//! })
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! let app = Router::new()
|
||||||
|
//! .route("/", get(|| async { /* ... */ }))
|
||||||
|
//! .layer(layer_fn(|inner| MyMiddleware { inner }));
|
||||||
|
//! # async {
|
||||||
|
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||||
|
//! # };
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
//! # Sharing state with handlers
|
//! # Sharing state with handlers
|
||||||
//!
|
//!
|
||||||
//! It is common to share some state between handlers for example to share a
|
//! It is common to share some state between handlers for example to share a
|
||||||
@ -840,7 +956,9 @@
|
|||||||
//! [`OriginalUri`]: crate::extract::OriginalUri
|
//! [`OriginalUri`]: crate::extract::OriginalUri
|
||||||
//! [`Service`]: tower::Service
|
//! [`Service`]: tower::Service
|
||||||
//! [`Service::poll_ready`]: tower::Service::poll_ready
|
//! [`Service::poll_ready`]: tower::Service::poll_ready
|
||||||
|
//! [`tower::Service`]: tower::Service
|
||||||
//! [`handle_error`]: routing::Router::handle_error
|
//! [`handle_error`]: routing::Router::handle_error
|
||||||
|
//! [tower-guides]: https://github.com/tower-rs/tower/tree/master/guides
|
||||||
|
|
||||||
#![warn(
|
#![warn(
|
||||||
clippy::all,
|
clippy::all,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user