auto_route 0.1.0

Spring-style automatic Axum routing for auto-di managed controllers
Documentation

auto_route

auto_route adds Spring-style route attributes to Axum and integrates controller construction with auto-di.

You write #[controller], #[get], and #[post]; the crate generates ordinary Axum routes and discovers them automatically at startup.

Installation

[dependencies]
auto-di = "0.6"
auto_route = "0.1"
axum = "0.8"
tokio = { version = "1", features = ["full"] }

DI-managed controller

use std::sync::Arc;

use auto_di::singleton;
use auto_route::controller;
use axum::{extract::Path, response::IntoResponse};

struct UserService;

#[singleton]
impl UserService {
    fn new() -> Self {
        Self
    }
}

struct UserController {
    service: Arc<UserService>,
}

#[singleton]
#[controller("/users")]
impl UserController {
    fn new(service: Arc<UserService>) -> Self {
        Self { service }
    }

    #[get("/:id")]
    async fn get_user(&self, Path(id): Path<u64>) -> impl IntoResponse {
        let _ = &self.service;
        format!("User {id}")
    }

    #[post]
    async fn create_user(&self) -> impl IntoResponse {
        "created"
    }
}

/:id is accepted for convenience and converted to Axum 0.8's /{id} syntax.

Standalone route

No controller is required for a normal function:

use auto_route::get;

#[get("/health")]
async fn health() -> &'static str {
    "ok"
}

Module route group

An inline module can provide a shared base path without a controller object:

use auto_route::controller;

#[controller("/admin")]
mod admin_routes {
    #[get("/health")]
    async fn health() -> &'static str {
        "ok"
    }
}

Only inline modules are supported. #[controller] mod routes; cannot be inspected by a procedural macro.

Start the server

Call auto_route::routes() once while constructing the application:

use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
    let app = auto_route::routes().await.expect("failed to build routes");
    let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Every controller and standalone route submits a small factory to a compile-time inventory registry. At startup, auto_route resolves controller singletons through auto-di, builds their Axum routers, and merges them into one application router. Macros do not run for each request.

Supported method attributes: get, post, put, delete, patch, options, and head.

License

MIT