hyper & tower: The HTTP and Middleware Under axum
Underneath axum — and a lot of the Rust networking world — sit two libraries
most people never learn directly: hyper, a fast, correct, low-level HTTP implementation, and tower,
an abstraction for "an async function from a request to a response" that makes middleware composable across
the whole ecosystem. This is the deepest roots guide in the Rust set. You'll rarely write hyper or
tower by hand, but understanding them demystifies a stack of things at once: what a Service is, why axum
middleware is a tower::Layer, how tower-http gives you tracing/CORS/timeouts for free, and what
axum::serve is really doing.
The mental model is one trait and one wrapper. tower::Service is the universal shape: given a
request, asynchronously produce a response (plus a readiness check for backpressure). Everything — a
whole axum app, a single endpoint, a database client, a rate limiter — can be a Service. A Layer
is a function that wraps one Service to make another (that's middleware). hyper, meanwhile, is what
actually speaks HTTP on the socket and calls your top-level Service for each request. Hold "a Service
turns a request into a response, a Layer wraps a Service, and hyper drives the whole thing over the
network," and the Rust web stack lays itself out flat.
📝 This is the deepest roots guide — it assumes Rust (traits, generics,
async— Rust From Zero) and the runtime beneath it (Tokio). It's most rewarding after you've used axum, so the pieces have somewhere to land. Examples run as plain Rust programs.
How to read this
Read in order — it builds from hyper's HTTP server up through the Service trait, Layers, and
tower-http, then maps the whole thing back onto axum. Phases carry difficulty badges.
The phases
- What hyper & tower Are 🟢 — the HTTP library and the
Serviceabstraction, and where they sit in the stack. - hyper: The HTTP Library 🟡 —
Request/Response, a bare hyper server, and what it hands your code. - The Service Trait 🔴 —
poll_ready+call, the universal "async request → response," and why it's everywhere. - Layers & Middleware 🔴 —
tower::Layer,ServiceBuilder, and composing middleware as wrapped services. - The tower-http Toolbox 🟡 — tracing, CORS, compression, and timeouts as reusable layers.
- How axum Uses Them 🟢 — axum's
Routeras aServiceover hyper, with your layers wrapped around it. - Where to Go Next 🟢 — applying this to gRPC (tonic), clients, and the rest of the tower ecosystem.
The throughline: a
Serviceturns a request into a response, aLayerwraps aService(that's middleware), and hyper drives it over the socket. axum is aServiceyou assembled.