Skip to main content

serve

serve(port: u16) -> std::io::Result<()> is the one-call entry point: load config, build the DI container, wire up every auto-registered route, and run the server.

use axumstart::router::get;

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

#[tokio::main]
async fn main() -> std::io::Result<()> {
axumstart::serve(3000).await
}

What it does, in order​

  1. Loads .env from the current working directory (dotenvy::dotenv().ok() — silently does nothing if there isn't one). This runs before components are built, so #[derive(ComponentConfig)]'s #[env_var(...)] fields see values from it, not just pre-existing process environment variables.
  2. Registers components via ComponentProvider::register_all() (every #[component]/#[derive(Component)]/#[derive(ComponentConfig)] type).
  3. Builds the registered blueprints into a Components snapshot.
  4. Folds every auto-registered route (every #[get]/#[post]/etc. handler — see HTTP methods) onto a fresh axum::Router, with that Components value available to any #[layer(...)] factory that wants it.
  5. Attaches Components as the router's state and binds a TcpListener on 0.0.0.0:{port}, then runs axum::serve.

Feature gating​

serve requires the router feature (which implies components) — both are default features, so most consumers get it for free:

axumstart = { version = "..." }

If you've opted out with default-features = false, add it back explicitly:

axumstart = { version = "...", default-features = false, features = ["router"] }

When you need more than serve gives you​

serve only serves auto-registered routes, with no hook for a manually-built Router, global middleware, .merge()-ing in another router, or custom listener configuration. If you need any of that, skip serve and call the pieces it wraps yourself:

use axumstart::components::ComponentProvider;
use axumstart::router::register_routes;

#[tokio::main]
async fn main() -> std::io::Result<()> {
dotenvy::dotenv().ok();

let provider = ComponentProvider::default();
provider.register_all();
let state = provider.build().await;

let app = register_routes(axum::Router::new(), &state)
.merge(my_manual_router())
.layer(tower_http::trace::TraceLayer::new_for_http()) // global middleware
.with_state(state);

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
axum::serve(listener, app).await
}
# fn my_manual_router() -> axum::Router<axumstart::router::Components> { axum::Router::new() }