Middleware layers in Rust
A layer wraps every route below it: logging, timeouts, compression.
use std::time::Instant;
use axum::extract::Request;
use axum::middleware::{self, Next};
use axum::response::Response;
use axum::{routing::get, Router};
async fn timing(request: Request, next: Next) -> Response {
let method = request.method().clone();
let path = request.uri().path().to_string();
let started = Instant::now();
let response = next.run(request).await;
println!("{method} {path} -> {} in {:?}", response.status(),
started.elapsed());
response
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(|| async { "ok" }))
.layer(middleware::from_fn(timing));
let listener = tokio::net::TcpListener::bind("127.0.0.1:8080")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
How it works
layerapplies a tower service to the whole router.middleware::from_fnturns an async fn into a layer.- Layers run outermost first, in reverse of the order added.
Keywords and builtins used here
NextRequestResponseasyncawaitfnletmainselftiminguse
The run, in numbers
- Lines
- 30
- Characters to type
- 719
- Tokens
- 217
- Three-star pace
- 110 tpm
At the three-star pace of 110 tokens a minute, this run takes about 118 seconds.
Step 3 of 3 in Responses & middleware, step 8 of 9 in Web services with axum.