nidus-http 1.0.2

Axum and Tower HTTP integration, controllers, middleware, health, metrics, and server defaults for Nidus.
Documentation

Nidus

Nidus is a modular Rust backend framework for building explicit, production-ready services with typed dependency injection, module graphs, Axum routes, Tower middleware, validation, OpenAPI, observability, testing, and separately installable adapters. It composes Axum, Tower, Tokio, serde, tracing, garde, utoipa, SQLx adapters, cache adapters, and normal Cargo workflows instead of replacing them.

Install

Install the Nidus CLI from crates.io:

cargo install cargo-nidus
cargo nidus new hello-nidus
cd hello-nidus
cargo run

During local framework development, install the CLI from this checkout:

cargo install --path crates/cargo-nidus
cargo nidus new hello-nidus

Application dependencies stay explicit:

[dependencies]
nidus = { package = "nidus-rs", version = "1.0.2", features = ["http", "config", "openapi", "validation"] }

For production observability through the facade:

nidus = { package = "nidus-rs", version = "1.0.2", features = ["observability", "events", "jobs", "otel"] }

Official integrations are separate crates:

nidus-sqlx = { version = "1.0.2", features = ["sqlite"] }
nidus-cache = { version = "1.0.2", features = ["moka"] }

Which Crate Do I Install?

  • Use cargo-nidus for cargo nidus new, route inspection, graph inspection, and OpenAPI generation.
  • Use nidus-rs as the application facade. Import it as nidus in Cargo.toml.
  • Enable facade features such as http, config, openapi, validation, auth, events, jobs, observability, and otel only when the app needs them.
  • Add nidus-sqlx or nidus-cache when choosing those official adapters.
  • Depend on lower-level crates such as nidus-core or nidus-http only when building framework extensions.

Common Imports And Extension Traits

Use the prelude at application entrypoints:

use nidus::prelude::*;

The prelude is the recommended import because it keeps the extension traits that power common app composition methods in scope:

  • ApplicationHttpExt enables .with_router(...).
  • NidusApplicationExt enables Nidus::create::<AppModule>(), .listen(...), and .into_router().
  • ApiDefaultsObservabilityExt enables .observability(&observability) and observability-aware API defaults when the observability feature is enabled.

Common Compile Errors

  • no method named with_router: import ApplicationHttpExt or nidus::prelude::*.
  • no method named listen or no method named into_router: import NidusApplicationExt or nidus::prelude::*.
  • no method named observability: import ApiDefaultsObservabilityExt or nidus::prelude::*.

Learning Path

  1. Run cargo nidus new hello-nidus and start the generated server.
  2. Inspect the generated module, controller, and service with cargo nidus routes and cargo nidus graph.
  3. Add one feature controller or service with cargo nidus generate.
  4. Add config, validation, or openapi when the first real route needs it.
  5. Add nidus-sqlx or nidus-cache only after the application has a real persistence or cache boundary.

Quickstart

use nidus::prelude::*;

#[controller("/users")]
struct UsersController;

#[routes]
impl UsersController {
    #[get("/:id")]
    async fn find_one(&self, Path(id): Path<i64>) -> String {
        format!("user {id}")
    }
}

#[module]
struct AppModule {
    controllers: (UsersController,),
}

#[nidus::main]
async fn main() -> nidus::Result<()> {
    let app = Nidus::bootstrap::<AppModule>()?
        .with_router(UsersController.into_router());

    app.listen("127.0.0.1:3000").await?;
    Ok(())
}

Core Concepts

  • Modules: explicit imports, providers, controllers, and exports.
  • Providers: Rust types registered by type, with singleton, transient, request-scoped, lazy, optional, and factory patterns.
  • Controllers: Axum-backed route composition with Nidus route metadata.
  • Guards and pipes: explicit authorization and validation boundaries.
  • Config: typed configuration from JSON, files, pairs, and environment variables.
  • OpenAPI: route metadata, schemas, and generated documents.
  • Observability: additive production setup for HTTP metrics, traces, events, jobs, lifecycle validation, and official adapter operations.
  • Events and jobs: in-process event buses, sync/async queues, and observed runners.
  • Testing: nidus_testing::TestApp for in-memory request tests and provider overrides.

Production Defaults

nidus-http provides opt-in production API defaults for request IDs, request context, health, readiness checks, metrics, CORS, body limits, timeout responses, security headers, structured logging, error envelopes, and OpenTelemetry trace-context helpers. The defaults return normal Axum routers and Tower layers, so applications can replace or reorder the boundary.

Recommended production observability is additive:

use nidus::prelude::*;

let observability = Observability::production("users-api")
    .version(env!("CARGO_PKG_VERSION"))
    .environment("prod")
    .prometheus()
    .tracing()
    .otel_from_env();

let app = Nidus::create::<AppModule>()
    .with_observability(observability.clone())
    .build()
    .await?;

Automatic instrumentation applies where Nidus owns the integration point: HTTP middleware, ObservedEventBus, ObservedJobRunner, module validation, and official adapter builders. Raw SQLx queries, raw cache clients, ORMs, queues, and HTTP clients remain explicit application instrumentation.

Adapter Story

The nidus facade stays lean. SQLx and cache integration live in nidus-sqlx and nidus-cache, with direct access to the underlying ecosystem clients. This keeps vendor dependencies out of core applications until they are explicitly installed.

Examples

  • examples/hello-world: minimal server.
  • examples/openapi: OpenAPI JSON and docs routes.
  • examples/production-api: production middleware defaults.
  • examples/realworld-api: team tasks API with modules, SQLite, validation, OpenAPI, health, observability, request IDs, guards, CORS, limits, timeouts, events, and jobs.
  • examples/sqlx-app and examples/cache-app: official adapter wiring.
  • examples/external-support-desk: copyable external-user support desk API using crates.io-style dependencies, DI, ticket lifecycle routes, API-key auth, request IDs, validation errors, not-found behavior, and nidus-testing.
  • examples/external-commerce: copyable external-user commerce API using crates.io-style dependencies, nidus-sqlx SQLite wiring, nidus-cache, products, carts, inventory, idempotent checkout, health/readiness, metrics, and nidus-testing.

Run an example:

cargo run -p nidus-example-realworld-api

The external-* examples are standalone Cargo packages with their own [workspace] tables. Verify them from their folders or with bash scripts/verify-external-examples.sh; they intentionally do not use local workspace path dependencies. Before 1.0.2 is published to crates.io, verify the same examples against temporary local patches:

NIDUS_EXTERNAL_EXAMPLES_LOCAL_PATCH=1 bash scripts/verify-external-examples.sh

That mode copies the external examples to a temp directory and appends temporary [patch.crates-io] entries there only. The checked-in examples stay copyable crates.io-style manifests.

Documentation

  • Local Markdown docs: docs/
  • Generated website source: website/
  • GitHub Pages build: .github/workflows/pages.yml

Build and check the static website locally:

cd website
npm run verify

Release Status

Nidus 1.0.0 established the public crate set. The current release track is 1.0.2, focused on launch hygiene, documentation, starter project depth, example proof, and package verification across every publishable crate. Publishing still requires crates.io credentials and should be reported with exact evidence when it is not performed.

Contributing

Read CONTRIBUTING.md. Changes should be small, tested, documented, and aligned with Rust ecosystem expectations.

License

Licensed under either MIT or Apache-2.0.