rust 41 lines · 7 steps

An admin route guard in Axum middleware

A middleware that only enforces admin access on /admin routes and passes everything else straight through.

Explained by highlit
1use axum::{
2 body::Body,
3 extract::MatchedPath,
4 http::{Request, StatusCode},
5 middleware::Next,
6 response::Response,
7};
8 
9use crate::auth::CurrentUser;
10 
11pub async fn admin_guard(req: Request<Body>, next: Next) -> Result<Response, StatusCode> {
12 let matched = req
13 .extensions()
14 .get::<MatchedPath>()
15 .map(|m| m.as_str().to_owned());
16 
17 let requires_admin = matched
18 .as_deref()
19 .map(|path| path.starts_with("/admin"))
20 .unwrap_or(false);
21 
22 if !requires_admin {
23 return Ok(next.run(req).await);
24 }
25 
26 let user = req
27 .extensions()
28 .get::<CurrentUser>()
29 .ok_or(StatusCode::UNAUTHORIZED)?;
30 
31 if !user.is_admin {
32 tracing::warn!(
33 user_id = %user.id,
34 path = matched.as_deref().unwrap_or("<unknown>"),
35 "blocked non-admin access to admin route"
36 );
37 return Err(StatusCode::FORBIDDEN);
38 }
39 
40 Ok(next.run(req).await)
41}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Reading MatchedPath lets middleware branch on the route pattern instead of the raw URL.
  2. 2Guarding only the paths that need it keeps unrelated requests fast and untouched.
  3. 3Returning a StatusCode as the error type turns authorization failures into clean HTTP responses.

Related explainers

Share this explainer

Here's the card — post it anywhere.

An admin route guard in Axum middleware — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code