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