| name | axum-code-review |
| description | Reviews axum web framework code for routing patterns, extractor usage, middleware, state management, and error handling. Use when reviewing Rust code that uses axum, tower, or hyper for HTTP services. Covers axum 0.7+ patterns including State, Path, Query, Json extractors. |
Axum Code Review
Review Workflow
- Check Cargo.toml — Note axum version (0.6 vs 0.7+ have different patterns), Rust edition (2021 vs 2024), tower, tower-http features. Edition 2024 changes RPIT lifetime capture in handler return types and removes the need for
async-trait in custom extractors.
- Check routing — Route organization, method routing, nested routers
- Check extractors — Order matters (body extractors must be last), correct types
- Check state — Shared state via
State<T>, not global mutable state
- Check error handling —
IntoResponse implementations, error types
Output Format
Report findings as:
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.
Quick Reference
Review Checklist
Routing
Extractors
State Management
Error Handling
Middleware
Severity Calibration
Critical
- Body extractor not last in handler parameters (silently consumes body, later extractors fail)
- SQL injection via path/query parameters passed directly to queries
- Internal error details leaked to clients (stack traces, database errors)
- Missing authentication middleware on protected routes
Major
- Global mutable state instead of
State<T> (race conditions)
- Missing error type conversion (raw
sqlx::Error returned to client)
- Missing request timeout (handlers can hang indefinitely)
- Route conflicts causing unexpected 405s
- Edition 2024:
async-trait still used for FromRequest/FromRequestParts when native async fn works
Minor
- Manual route method matching instead of
.get(), .post()
- Missing fallback handler (default 404 is plain text, not JSON)
- Middleware applied per-route when it should be global (or vice versa)
- Missing
tower-http::trace for request logging
- Edition 2024:
once_cell::sync::Lazy or lazy_static! used where std::sync::LazyLock works
Informational
- Suggestions to use
tower-http layers for common concerns
- Router organization improvements
- Suggestions to add OpenAPI documentation via
utoipa or aide
Valid Patterns (Do NOT Flag)
#[axum::debug_handler] on handlers — Debugging aid that improves compile error messages
Extension<T> for middleware-injected data — Valid pattern for request-scoped values
- Returning
impl IntoResponse from handlers — More flexible than concrete types
Router::new() per module, merged in main — Standard organization pattern
ServiceBuilder for layer composition — Tower pattern, not over-engineering
axum::serve with TcpListener — Standard axum 0.7+ server setup
- Native
async fn in FromRequest/FromRequestParts impls — async-trait crate no longer needed (stable since Rust 1.75)
+ use<'a> on handler return types — Edition 2024 precise capture syntax for RPIT
std::sync::LazyLock for shared static state — Replaces once_cell/lazy_static (stable since Rust 1.80)
Before Submitting Findings
Load and follow beagle-rust:review-verification-protocol before reporting any issue.