Skip to main content
Axum is built on top of Tower, a library of modular and reusable components for building robust networking clients and servers. This deep integration gives you access to a rich ecosystem of middleware.

Understanding Tower

Tower provides three core abstractions:
  • Service: An asynchronous function from a request to a response
  • Layer: Middleware that wraps a service to modify its behavior
  • ServiceBuilder: A utility for composing layers
Axum’s Router implements tower::Service, so it works seamlessly with all Tower middleware.

Adding middleware with layers

Use the .layer() method to add Tower middleware:

Middleware execution order

Middleware executes in reverse order of how it’s added:
Execution flow:
  1. Request → TraceLayer → CorsLayer → CompressionLayer → Handler
  2. Handler → CompressionLayer → CorsLayer → TraceLayer → Response

tower-http middleware

The tower-http crate provides HTTP-specific middleware:

CORS

Handle Cross-Origin Resource Sharing:

Compression

Compress response bodies:
Supported algorithms: gzip, deflate, br (brotli), zstd

Tracing and logging

Log requests and responses:

Request timeouts

Set timeouts for requests:
With custom error status:

Request/response size limits

Static file serving

Serve static files:
With directory listings and index files:

ServiceBuilder for composing middleware

Use ServiceBuilder to organize multiple layers:
ServiceBuilder applies layers in the order they appear (unlike .layer() which applies them in reverse).

Per-route middleware

Apply middleware to specific routes:

Sharing state with middleware

Use extensions to share data:

Custom Tower middleware

Create your own middleware:

Common middleware patterns

Testing with Tower

Be careful with middleware ordering. Request processing flows from outer to inner layers, while response processing flows from inner to outer layers.
Use ServiceBuilder when composing many middleware layers - it’s more ergonomic and the layer order matches the execution order.