Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tutorial 08: Controllers, Routing & Middleware 🚦

Rullst’s Router wraps Axum’s router while preserving explicit Tower middleware composition. This example uses the Axum 0.8 request and Next types.


Step 1: Create a custom middleware

In src/middlewares/logger.rs:

#![allow(unused)]
fn main() {
use rullst::web::axum::{
    extract::Request,
    middleware::Next,
    response::Response,
};

pub async fn log_request(req: Request, next: Next) -> Response {
    let method = req.method().clone();
    let path = req.uri().path().to_owned();
    let response = next.run(req).await;

    // Prefer structured tracing in production; do not log query strings,
    // cookies, authorization headers, or request bodies by default.
    println!("[HTTP] {method} {path} -> {}", response.status());
    response
}
}

Step 2: Organize sub-routers

use rullst::{Router, Server, ServerError};
use rullst::routing::{get, post};
use rullst::web::axum::middleware;

async fn list_users() -> &'static str { "users" }
async fn create_user() -> &'static str { "created" }
async fn login() -> &'static str { "login" }

async fn log_request(
    request: rullst::web::axum::extract::Request,
    next: rullst::web::axum::middleware::Next,
) -> rullst::web::axum::response::Response {
    next.run(request).await
}

#[tokio::main]
async fn main() -> Result<(), ServerError> {
    let api = Router::new()
        .route("/users", get(list_users).post(create_user))
        .layer(middleware::from_fn(log_request));

    let auth = Router::new().route("/login", post(login));
    let app = Router::new()
        .nest("/api/v1", api)
        .nest("/auth", auth);

    Server::new(app).run(3000).await
}

Use nest_axum or merge_axum when integrating a third-party raw axum::Router.


Key takeaways

  • Middleware order is security-sensitive. Use the canonical production baseline for secure headers, CSRF, CORS, and WAF rather than assembling those controls ad hoc.
  • Authentication middleware establishes identity; handlers/repositories must still enforce resource ownership or role authorization.
  • Apply request-body and concurrency limits before handlers that parse expensive or attacker-controlled input.