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