Skip to content
>_devvkit
$devvkit learn --librarie axum-guide

Axum Guide

[rust][web][http]
Rust
Install
cargo add axum tokio --features tokio/full
cargo add serde serde_json

Axum is the official web framework from the Tokio team. Built on Tower middleware stack.

Extractors (Path, Query, Json) type-check request data at compile time.

Shared state via Extension or State extractor. Tower middleware layers for auth, logging, CORS.

Setup

Basic routerHello world server.
use axum::{Router, routing::get};

async fn root() -> &'static str { "Hello" }

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(root));
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Extractors

Path paramsCapture URL segments.
use axum::extract::Path;

async fn user(Path(id): Path<u64>) -> String {
    format!("User {id}")
}
Query paramsParse query string.
use serde::Deserialize;
use axum::extract::Query;

#[derive(Deserialize)]
struct Pagination { page: u32, limit: u32 }

async fn list(Query(p): Query<Pagination>) -> String {
    format!("page={}, limit={}", p.page, p.limit)
}
JSON bodyParse JSON request.
use axum::extract::Json;

#[derive(Deserialize)]
struct CreateUser { name: String, email: String }

async fn create(Json(payload): Json<CreateUser>) -> Json<serde_json::Value> {
    Json(serde_json::json!({ "id": 1, "name": payload.name }))
}
Combined extractorsPath + Query + Json.
async fn update(
    Path(id): Path<u64>,
    Query(params): Query<UpdateParams>,
    Json(body): Json<UpdateBody>,
) -> impl IntoResponse { /* ... */ }

Middleware

MiddlewareTower layer.
use tower_http::trace::TraceLayer;

let app = Router::new()
    .route("/", get(root))
    .layer(TraceLayer::new_for_http());

State

Shared statePass state to handlers.
use std::sync::Arc;

struct AppState { db: DbPool }

let state = Arc::new(AppState { db });
let app = Router::new()
    .route("/", get(handler))
    .with_state(state);

async fn handler(State(state): State<Arc<AppState>>) -> String {
    // use state.db
}