rust 60 lines · 8 steps

Passing per-request context through Axum middleware

An Axum middleware layer builds a per-request context and hands it to a handler via request extensions.

Explained by highlit
1use std::sync::Arc;
2use axum::{
3 body::Body,
4 extract::{Extension, State},
5 http::{Request, StatusCode},
6 middleware::Next,
7 response::{IntoResponse, Response},
8 Json,
9};
10use serde_json::json;
11use uuid::Uuid;
12 
13#[derive(Clone)]
14struct AppState {
15 db: Arc<PgPool>,
16 feature_flags: Arc<FeatureFlags>,
17}
18 
19#[derive(Clone)]
20struct RequestContext {
21 request_id: Uuid,
22 tenant: String,
23}
24 
25async fn attach_context(mut req: Request<Body>, next: Next) -> Result<Response, StatusCode> {
26 let tenant = req
27 .headers()
28 .get("x-tenant-id")
29 .and_then(|v| v.to_str().ok())
30 .ok_or(StatusCode::BAD_REQUEST)?
31 .to_owned();
32 
33 let ctx = RequestContext {
34 request_id: Uuid::new_v4(),
35 tenant,
36 };
37 
38 req.extensions_mut().insert(ctx);
39 Ok(next.run(req).await)
40}
41 
42async fn current_usage(
43 State(state): State<AppState>,
44 Extension(ctx): Extension<RequestContext>,
45) -> impl IntoResponse {
46 let quota = sqlx::query_scalar!(
47 "SELECT quota FROM tenants WHERE id = $1",
48 ctx.tenant
49 )
50 .fetch_one(&*state.db)
51 .await
52 .unwrap_or(0);
53 
54 Json(json!({
55 "request_id": ctx.request_id,
56 "tenant": ctx.tenant,
57 "quota": quota,
58 "metering_enabled": state.feature_flags.is_enabled("metering"),
59 }))
60}
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1Request extensions let middleware attach typed data that downstream handlers pull out with the Extension extractor.
  2. 2Separating shared app state from per-request context keeps long-lived resources distinct from data that changes each call.
  3. 3Failing fast in middleware with a StatusCode error rejects malformed requests before any handler runs.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Passing per-request context through Axum middleware — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code