Axum Code Review
by @anderskev
Reviews axum web framework code for routing patterns, extractor usage, middleware, state management, and error handling. Use when reviewing Rust code that us...
clawhub install axum-code-reviewπ About This Skill
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
1. 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.
2. Check routing β Route organization, method routing, nested routers
3. Check extractors β Order matters (body extractors must be last), correct types
4. Check state β Shared state via State, not global mutable state
5. Check error handling β IntoResponse implementations, error types
Gates (before reporting findings)
Run in order. Do not write a finding until the step that applies has passed.
1. Version and edition on disk β Pass when: You have read the relevant Cargo.toml (crate or workspace root) and can state axum (and related tower/tower-http) versions and Rust edition. Then apply 0.6 vs 0.7+ or Edition 2024βspecific checklist items only when that file supports them.
2. Per-finding evidence β Pass when: Each issue cites [FILE:LINE] from the current tree for the handler, router, layer, or type under review (not from memory, docs-only, or another branch).
3. Category check vs protocol β Pass when: For the finding type (routing conflict, extractor order, error leak, middleware order, etc.), you ran the matching checks from beagle-rust:review-verification-protocol (e.g. full handler signature for extractor order; surrounding error mapping before βraw error to clientβ). Then add the finding.
4. Output shape β Pass when: The report lines match Output Format below (severity + description).
Output Format
Report findings as:
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.
Quick Reference
| Issue Type | Reference | |------------|-----------| | Route definitions, nesting, method routing | references/routing.md | | State, Path, Query, Json, body extractors | references/extractors.md | | Tower middleware, layers, error handling | references/middleware.md |
Review Checklist
Routing
/api/users, /api/orders).get(), .post(), not .route() with manual method matching)Extractors
Json, Form, Bytes) are the LAST parameterState requires T: Clone β typically Arc or direct Clone derivePath parameter types match the route definitionQuery fields are Option for optional query params with #[serde(default)]FromRequestParts (not body) or FromRequest (body)async fn in trait impls (no #[async_trait] needed for FromRequest/FromRequestParts)State Management
State, not global mutable staticsClone derived or manually implemented on state typeLazyLock from std (not once_cell::sync::Lazy or lazy_static!)Error Handling
IntoResponse for proper HTTP error codesResult pattern used for handlers-> impl IntoResponse capture all in-scope lifetimes by default; use + use<> to opt out of capturing request lifetimes when returning owned dataMiddleware
tower-http used for common concerns (CORS, compression, tracing, timeout)#[async_trait] can migrate to native async fn in trait implsSeverity Calibration
Critical
Major
State (race conditions)sqlx::Error returned to client)async-trait still used for FromRequest/FromRequestParts when native async fn worksMinor
.get(), .post()tower-http::trace for request loggingonce_cell::sync::Lazy or lazy_static! used where std::sync::LazyLock worksInformational
tower-http layers for common concernsutoipa or aideValid Patterns (Do NOT Flag)
#[axum::debug_handler] on handlers β Debugging aid that improves compile error messagesExtension for middleware-injected data β Valid pattern for request-scoped valuesimpl IntoResponse from handlers β More flexible than concrete typesRouter::new() per module, merged in main β Standard organization patternServiceBuilder for layer composition β Tower pattern, not over-engineeringaxum::serve with TcpListener β Standard axum 0.7+ server setupasync 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 RPITstd::sync::LazyLock for shared static state β Replaces once_cell/lazy_static (stable since Rust 1.80)Before Submitting Findings
Complete Gates (before reporting findings) and load beagle-rust:review-verification-protocol for category-specific checks before any issue is final.