1# Table of contents 2 3- [Intro](#intro) 4- [Applying middleware](#applying-middleware) 5- [Commonly used middleware](#commonly-used-middleware) 6- [Ordering](#ordering) 7- [Writing middleware](#writing-middleware) 8- [Routing to services/middleware and backpressure](#routing-to-servicesmiddleware-and-backpressure) 9- [Accessing state in middleware](#accessing-state-in-middleware) 10- [Passing state from middleware to handlers](#passing-state-from-middleware-to-handlers) 11- [Rewriting request URI in middleware](#rewriting-request-uri-in-middleware) 12 13# Intro 14 15axum is unique in that it doesn't have its own bespoke middleware system and 16instead integrates with [`tower`]. This means the ecosystem of [`tower`] and 17[`tower-http`] middleware all work with axum. 18 19While its not necessary to fully understand tower to write or use middleware 20with axum, having at least a basic understanding of tower's concepts is 21recommended. See [tower's guides][tower-guides] for a general introduction. 22Reading the documentation for [`tower::ServiceBuilder`] is also recommended. 23 24# Applying middleware 25 26axum allows you to add middleware just about anywhere 27 28- To entire routers with [`Router::layer`] and [`Router::route_layer`]. 29- To method routers with [`MethodRouter::layer`] and [`MethodRouter::route_layer`]. 30- To individual handlers with [`Handler::layer`]. 31 32## Applying multiple middleware 33 34Its recommended to use [`tower::ServiceBuilder`] to apply multiple middleware at 35once, instead of calling `layer` (or `route_layer`) repeatedly: 36 37```rust 38use axum::{ 39 routing::get, 40 Extension, 41 Router, 42}; 43use tower_http::{trace::TraceLayer}; 44use tower::ServiceBuilder; 45 46async fn handler() {} 47 48#[derive(Clone)] 49struct State {} 50 51let app = Router::new() 52 .route("/", get(handler)) 53 .layer( 54 ServiceBuilder::new() 55 .layer(TraceLayer::new_for_http()) 56 .layer(Extension(State {})) 57 ); 58# async { 59# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); 60# }; 61``` 62 63# Commonly used middleware 64 65Some commonly used middleware are: 66 67- [`TraceLayer`](tower_http::trace) for high level tracing/logging. 68- [`CorsLayer`](tower_http::cors) for handling CORS. 69- [`CompressionLayer`](tower_http::compression) for automatic compression of 70 responses. 71- [`RequestIdLayer`](tower_http::request_id) and 72 [`PropagateRequestIdLayer`](tower_http::request_id) set and propagate request 73 ids. 74- [`TimeoutLayer`](tower::timeout::TimeoutLayer) for timeouts. Note this 75 requires using [`HandleErrorLayer`](crate::error_handling::HandleErrorLayer) 76 to convert timeouts to responses. 77 78# Ordering 79 80When you add middleware with [`Router::layer`] (or similar) all previously added 81routes will be wrapped in the middleware. Generally speaking, this results in 82middleware being executed from bottom to top. 83 84So if you do this: 85 86```rust 87use axum::{routing::get, Router}; 88 89async fn handler() {} 90 91# let layer_one = axum::Extension(()); 92# let layer_two = axum::Extension(()); 93# let layer_three = axum::Extension(()); 94# 95let app = Router::new() 96 .route("/", get(handler)) 97 .layer(layer_one) 98 .layer(layer_two) 99 .layer(layer_three); 100# let _: Router<(), axum::body::Body> = app; 101``` 102 103Think of the middleware as being layered like an onion where each new layer 104wraps all previous layers: 105 106```not_rust 107 requests 108 | 109 v 110+----- layer_three -----+ 111| +---- layer_two ----+ | 112| | +-- layer_one --+ | | 113| | | | | | 114| | | handler | | | 115| | | | | | 116| | +-- layer_one --+ | | 117| +---- layer_two ----+ | 118+----- layer_three -----+ 119 | 120 v 121 responses 122``` 123 124That is: 125 126- First `layer_three` receives the request 127- It then does its thing and passes the request onto `layer_two` 128- Which passes the request onto `layer_one` 129- Which passes the request onto `handler` where a response is produced 130- That response is then passed to `layer_one` 131- Then to `layer_two` 132- And finally to `layer_three` where it's returned out of your app 133 134It's a little more complicated in practice because any middleware is free to 135return early and not call the next layer, for example if a request cannot be 136authorized, but its a useful mental model to have. 137 138As previously mentioned its recommended to add multiple middleware using 139`tower::ServiceBuilder`, however this impacts ordering: 140 141```rust 142use tower::ServiceBuilder; 143use axum::{routing::get, Router}; 144 145async fn handler() {} 146 147# let layer_one = axum::Extension(()); 148# let layer_two = axum::Extension(()); 149# let layer_three = axum::Extension(()); 150# 151let app = Router::new() 152 .route("/", get(handler)) 153 .layer( 154 ServiceBuilder::new() 155 .layer(layer_one) 156 .layer(layer_two) 157 .layer(layer_three), 158 ); 159# let _: Router<(), axum::body::Body> = app; 160``` 161 162`ServiceBuilder` works by composing all layers into one such that they run top 163to bottom. So with the previous code `layer_one` would receive the request 164first, then `layer_two`, then `layer_three`, then `handler`, and then the 165response would bubble back up through `layer_three`, then `layer_two`, and 166finally `layer_one`. 167 168Executing middleware top to bottom is generally easier to understand and follow 169mentally which is one of the reasons `ServiceBuilder` is recommended. 170 171# Writing middleware 172 173axum offers many ways of writing middleware, at different levels of abstraction 174and with different pros and cons. 175 176## `axum::middleware::from_fn` 177 178Use [`axum::middleware::from_fn`] to write your middleware when: 179 180- You're not comfortable with implementing your own futures and would rather use 181 the familiar `async`/`await` syntax. 182- You don't intend to publish your middleware as a crate for others to use. 183 Middleware written like this are only compatible with axum. 184 185## `axum::middleware::from_extractor` 186 187Use [`axum::middleware::from_extractor`] to write your middleware when: 188 189- You have a type that you sometimes want to use as an extractor and sometimes 190 as a middleware. If you only need your type as a middleware prefer 191 [`middleware::from_fn`]. 192 193## tower's combinators 194 195tower has several utility combinators that can be used to perform simple 196modifications to requests or responses. The most commonly used ones are 197 198- [`ServiceBuilder::map_request`] 199- [`ServiceBuilder::map_response`] 200- [`ServiceBuilder::then`] 201- [`ServiceBuilder::and_then`] 202 203You should use these when 204 205- You want to perform a small ad hoc operation, such as adding a header. 206- You don't intend to publish your middleware as a crate for others to use. 207 208## `tower::Service` and `Pin<Box<dyn Future>>` 209 210For maximum control (and a more low level API) you can write you own middleware 211by implementing [`tower::Service`]: 212 213Use [`tower::Service`] with `Pin<Box<dyn Future>>` to write your middleware when: 214 215- Your middleware needs to be configurable for example via builder methods on 216 your [`tower::Layer`] such as [`tower_http::trace::TraceLayer`]. 217- You do intend to publish your middleware as a crate for others to use. 218- You're not comfortable with implementing your own futures. 219 220A decent template for such a middleware could be: 221 222```rust 223use axum::{ 224 response::Response, 225 body::Body, 226 http::Request, 227}; 228use futures_util::future::BoxFuture; 229use tower::{Service, Layer}; 230use std::task::{Context, Poll}; 231 232#[derive(Clone)] 233struct MyLayer; 234 235impl<S> Layer<S> for MyLayer { 236 type Service = MyMiddleware<S>; 237 238 fn layer(&self, inner: S) -> Self::Service { 239 MyMiddleware { inner } 240 } 241} 242 243#[derive(Clone)] 244struct MyMiddleware<S> { 245 inner: S, 246} 247 248impl<S> Service<Request<Body>> for MyMiddleware<S> 249where 250 S: Service<Request<Body>, Response = Response> + Send + 'static, 251 S::Future: Send + 'static, 252{ 253 type Response = S::Response; 254 type Error = S::Error; 255 // `BoxFuture` is a type alias for `Pin<Box<dyn Future + Send + 'a>>` 256 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>; 257 258 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { 259 self.inner.poll_ready(cx) 260 } 261 262 fn call(&mut self, request: Request<Body>) -> Self::Future { 263 let future = self.inner.call(request); 264 Box::pin(async move { 265 let response: Response = future.await?; 266 Ok(response) 267 }) 268 } 269} 270``` 271 272## `tower::Service` and custom futures 273 274If you're comfortable implementing your own futures (or want to learn it) and 275need as much control as possible then using `tower::Service` without boxed 276futures is the way to go. 277 278Use [`tower::Service`] with manual futures to write your middleware when: 279 280- You want your middleware to have the lowest possible overhead. 281- Your middleware needs to be configurable for example via builder methods on 282 your [`tower::Layer`] such as [`tower_http::trace::TraceLayer`]. 283- You do intend to publish your middleware as a crate for others to use, perhaps 284 as part of tower-http. 285- You're comfortable with implementing your own futures, or want to learn how 286 the lower levels of async Rust works. 287 288tower's ["Building a middleware from scratch"][tower-from-scratch-guide] 289guide is a good place to learn how to do this. 290 291# Error handling for middleware 292 293axum's error handling model requires handlers to always return a response. 294However middleware is one possible way to introduce errors into an application. 295If hyper receives an error the connection will be closed without sending a 296response. Thus axum requires those errors to be handled gracefully: 297 298```rust 299use axum::{ 300 routing::get, 301 error_handling::HandleErrorLayer, 302 http::StatusCode, 303 BoxError, 304 Router, 305}; 306use tower::{ServiceBuilder, timeout::TimeoutLayer}; 307use std::time::Duration; 308 309async fn handler() {} 310 311let app = Router::new() 312 .route("/", get(handler)) 313 .layer( 314 ServiceBuilder::new() 315 // this middleware goes above `TimeoutLayer` because it will receive 316 // errors returned by `TimeoutLayer` 317 .layer(HandleErrorLayer::new(|_: BoxError| async { 318 StatusCode::REQUEST_TIMEOUT 319 })) 320 .layer(TimeoutLayer::new(Duration::from_secs(10))) 321 ); 322# async { 323# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); 324# }; 325``` 326 327See [`error_handling`](crate::error_handling) for more details on axum's error 328handling model. 329 330# Routing to services/middleware and backpressure 331 332Generally routing to one of multiple services and backpressure doesn't mix 333well. Ideally you would want ensure a service is ready to receive a request 334before calling it. However, in order to know which service to call, you need 335the request... 336 337One approach is to not consider the router service itself ready until all 338destination services are ready. That is the approach used by 339[`tower::steer::Steer`]. 340 341Another approach is to always consider all services ready (always return 342`Poll::Ready(Ok(()))`) from `Service::poll_ready` and then actually drive 343readiness inside the response future returned by `Service::call`. This works 344well when your services don't care about backpressure and are always ready 345anyway. 346 347axum expects that all services used in your app wont care about 348backpressure and so it uses the latter strategy. However that means you 349should avoid routing to a service (or using a middleware) that _does_ care 350about backpressure. At the very least you should [load shed] so requests are 351dropped quickly and don't keep piling up. 352 353It also means that if `poll_ready` returns an error then that error will be 354returned in the response future from `call` and _not_ from `poll_ready`. In 355that case, the underlying service will _not_ be discarded and will continue 356to be used for future requests. Services that expect to be discarded if 357`poll_ready` fails should _not_ be used with axum. 358 359One possible approach is to only apply backpressure sensitive middleware 360around your entire app. This is possible because axum applications are 361themselves services: 362 363```rust 364use axum::{ 365 routing::get, 366 Router, 367}; 368use tower::ServiceBuilder; 369# let some_backpressure_sensitive_middleware = 370# tower::layer::util::Identity::new(); 371 372async fn handler() { /* ... */ } 373 374let app = Router::new().route("/", get(handler)); 375 376let app = ServiceBuilder::new() 377 .layer(some_backpressure_sensitive_middleware) 378 .service(app); 379# async { 380# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); 381# }; 382``` 383 384However when applying middleware around your whole application in this way 385you have to take care that errors are still being handled with 386appropriately. 387 388Also note that handlers created from async functions don't care about 389backpressure and are always ready. So if you're not using any Tower 390middleware you don't have to worry about any of this. 391 392# Accessing state in middleware 393 394How to make state available to middleware depends on how the middleware is 395written. 396 397## Accessing state in `axum::middleware::from_fn` 398 399Use [`axum::middleware::from_fn_with_state`](crate::middleware::from_fn_with_state). 400 401## Accessing state in custom `tower::Layer`s 402 403```rust 404use axum::{ 405 Router, 406 routing::get, 407 middleware::{self, Next}, 408 response::Response, 409 extract::State, 410 http::Request, 411}; 412use tower::{Layer, Service}; 413use std::task::{Context, Poll}; 414 415#[derive(Clone)] 416struct AppState {} 417 418#[derive(Clone)] 419struct MyLayer { 420 state: AppState, 421} 422 423impl<S> Layer<S> for MyLayer { 424 type Service = MyService<S>; 425 426 fn layer(&self, inner: S) -> Self::Service { 427 MyService { 428 inner, 429 state: self.state.clone(), 430 } 431 } 432} 433 434#[derive(Clone)] 435struct MyService<S> { 436 inner: S, 437 state: AppState, 438} 439 440impl<S, B> Service<Request<B>> for MyService<S> 441where 442 S: Service<Request<B>>, 443{ 444 type Response = S::Response; 445 type Error = S::Error; 446 type Future = S::Future; 447 448 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { 449 self.inner.poll_ready(cx) 450 } 451 452 fn call(&mut self, req: Request<B>) -> Self::Future { 453 // Do something with `self.state`. 454 // 455 // See `axum::RequestExt` for how to run extractors directly from 456 // a `Request`. 457 458 self.inner.call(req) 459 } 460} 461 462async fn handler(_: State<AppState>) {} 463 464let state = AppState {}; 465 466let app = Router::new() 467 .route("/", get(handler)) 468 .layer(MyLayer { state: state.clone() }) 469 .with_state(state); 470# let _: axum::Router = app; 471``` 472 473# Passing state from middleware to handlers 474 475State can be passed from middleware to handlers using [request extensions]: 476 477```rust 478use axum::{ 479 Router, 480 http::{Request, StatusCode}, 481 routing::get, 482 response::{IntoResponse, Response}, 483 middleware::{self, Next}, 484 extract::Extension, 485}; 486 487#[derive(Clone)] 488struct CurrentUser { /* ... */ } 489 490async fn auth<B>(mut req: Request<B>, next: Next<B>) -> Result<Response, StatusCode> { 491 let auth_header = req.headers() 492 .get(http::header::AUTHORIZATION) 493 .and_then(|header| header.to_str().ok()); 494 495 let auth_header = if let Some(auth_header) = auth_header { 496 auth_header 497 } else { 498 return Err(StatusCode::UNAUTHORIZED); 499 }; 500 501 if let Some(current_user) = authorize_current_user(auth_header).await { 502 // insert the current user into a request extension so the handler can 503 // extract it 504 req.extensions_mut().insert(current_user); 505 Ok(next.run(req).await) 506 } else { 507 Err(StatusCode::UNAUTHORIZED) 508 } 509} 510 511async fn authorize_current_user(auth_token: &str) -> Option<CurrentUser> { 512 // ... 513 # unimplemented!() 514} 515 516async fn handler( 517 // extract the current user, set by the middleware 518 Extension(current_user): Extension<CurrentUser>, 519) { 520 // ... 521} 522 523let app = Router::new() 524 .route("/", get(handler)) 525 .route_layer(middleware::from_fn(auth)); 526# let _: Router<()> = app; 527``` 528 529[Response extensions] can also be used but note that request extensions are not 530automatically moved to response extensions. You need to manually do that for the 531extensions you need. 532 533# Rewriting request URI in middleware 534 535Middleware added with [`Router::layer`] will run after routing. That means it 536cannot be used to run middleware that rewrites the request URI. By the time the 537middleware runs the routing is already done. 538 539The workaround is to wrap the middleware around the entire `Router` (this works 540because `Router` implements [`Service`]): 541 542```rust 543use tower::Layer; 544use axum::{ 545 Router, 546 ServiceExt, // for `into_make_service` 547 response::Response, 548 middleware::Next, 549 http::Request, 550}; 551 552async fn rewrite_request_uri<B>(req: Request<B>, next: Next<B>) -> Response { 553 // ... 554 # next.run(req).await 555} 556 557// this can be any `tower::Layer` 558let middleware = axum::middleware::from_fn(rewrite_request_uri); 559 560let app = Router::new(); 561 562// apply the layer around the whole `Router` 563// this way the middleware will run before `Router` receives the request 564let app_with_middleware = middleware.layer(app); 565 566# async { 567axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) 568 .serve(app_with_middleware.into_make_service()) 569 .await 570 .unwrap(); 571# }; 572``` 573 574[`tower`]: https://crates.io/crates/tower 575[`tower-http`]: https://crates.io/crates/tower-http 576[tower-guides]: https://github.com/tower-rs/tower/tree/master/guides 577[`axum::middleware::from_fn`]: fn@crate::middleware::from_fn 578[`middleware::from_fn`]: fn@crate::middleware::from_fn 579[tower-from-scratch-guide]: https://github.com/tower-rs/tower/blob/master/guides/building-a-middleware-from-scratch.md 580[`ServiceBuilder::map_request`]: tower::ServiceBuilder::map_request 581[`ServiceBuilder::map_response`]: tower::ServiceBuilder::map_response 582[`ServiceBuilder::then`]: tower::ServiceBuilder::then 583[`ServiceBuilder::and_then`]: tower::ServiceBuilder::and_then 584[`axum::middleware::from_extractor`]: fn@crate::middleware::from_extractor 585[`Handler::layer`]: crate::handler::Handler::layer 586[`Router::layer`]: crate::routing::Router::layer 587[`MethodRouter::layer`]: crate::routing::MethodRouter::layer 588[`Router::route_layer`]: crate::routing::Router::route_layer 589[`MethodRouter::route_layer`]: crate::routing::MethodRouter::route_layer 590[request extensions]: https://docs.rs/http/latest/http/request/struct.Request.html#method.extensions 591[Response extensions]: https://docs.rs/http/latest/http/response/struct.Response.html#method.extensions 592[`State`]: crate::extract::State 593[`Service`]: tower::Service 594