actus 1.0.1

The ergonomic web framework for Rust.
Documentation
//! # Actus
//!
//! The pragmatic web framework for Rust: auditable controllers, persistent
//! services, real HTTP — out of the box. Built directly on [hyper] and
//! [tokio]; there is no separate server to run it on.
//!
//! Actus gives you a clear two-tier structure — a top-level routing blueprint
//! and self-contained controllers — while letting you mix REST, RPC-style
//! actions, and legacy URL migrations in the same codebase. A reviewer can
//! answer *what endpoints exist, what they require, and who can call them* by
//! reading two macros, without grepping for attribute decorators across files.
//!
//! # Philosophy
//!
//! Most Rust web frameworks are either unopinionated (you invent the structure)
//! or rigidly opinionated (you bend to their paradigm). Actus picks a middle:
//!
//! - **A clear hierarchy.** The whole URL layout is declared once, in
//!   `app_routes! { ... }` — the entire backend is visible at a glance.
//! - **A clear unit of code.** Each controller owns a URL prefix and declares
//!   its routes, access points, and parameters in one `routes! { ... }` block.
//! - **Pragmatism inside that structure.** REST verbs (`GET`/`POST`/`PUT`/
//!   `DELETE`), RPC-style action names (`/charge`, `/refund`), path parameters
//!   (`{id}`), and legacy URLs (`login.php`) all coexist in the same block.
//!
//! # Design principles
//!
//! - **Two kinds of cross-cutting concern get two shapes.** HTTP-protocol
//!   concerns (CORS, body limits, compression) are named `Server::with_X(...)`
//!   methods with their lifecycle position built in; application concerns
//!   (logging, auth gates, request IDs, rate-limit policy) are `Middleware`.
//!   You never have to position CORS in a stack.
//! - **Auditability over uniformity.** "What does this server do?" and "what
//!   endpoints exist?" are answerable from `Server::new(...)` and the two
//!   macros — without walking a chain of layers.
//! - **Explicit over magic.** No DI container, no extractors reaching into thin
//!   air: the `app_routes!` `deps` block is constructor injection, and routes
//!   are declared, not discovered.
//! - **HTTP correctness out of the box.** You shouldn't need to know that
//!   compression goes outermost, or that the body cap gates the body parse —
//!   that is framework knowledge, not application knowledge.
//! - **Policy-agnostic.** No roles, no `Access` enum, no built-in RBAC.
//!   Authorization lives in your policy layer, called from a controller's
//!   `prepare` hook or a handler.
//!
//! This crate is the façade you depend on. It re-exports the public API of the
//! implementation crates ([`actus-server`], [`actus-controller`],
//! [`actus-reply`]) and the two macros that declare your application's URL
//! surface. Add it with:
//!
//! ```toml
//! [dependencies]
//! actus = "1.0"
//! tokio = { version = "1", features = ["full"] }
//! serde_json = "1"
//! ```
//!
//! Optional features: `compression` (gzip/brotli responses), `websocket`
//! ([`ws::upgrade`]), and `openapi` (OpenAPI 3.x generation).
//!
//! # Quick start
//!
//! Two macros declare everything: `routes!` (one controller's API surface) and
//! `app_routes!` (the whole application's URL blueprint). A reviewer can see
//! every endpoint by reading just those two places.
//!
//! ```no_run
//! use actus::prelude::*;
//! use serde_json::json;
//!
//! // A controller owns a URL prefix and declares its routes in one block.
//! struct Greeter;
//!
//! #[controller]
//! impl Greeter {
//!     routes! {
//!         GET ""       => index(),
//!         GET "{name}" => greet(name: String),
//!     }
//!
//!     pub async fn index(&self) -> Reply {
//!         reply!(json!({ "hello": "world" }))
//!     }
//!
//!     pub async fn greet(&self, name: String) -> Reply {
//!         reply!(json!({ "hello": name }))
//!     }
//! }
//!
//! // The application's URL blueprint, declared in one place. (The `deps`
//! // block — for injected services — is optional and omitted here.)
//! app_routes! {
//!     routes {
//!         "greet" => Greeter,
//!     }
//! }
//!
//! // `init()` is generated by `app_routes!`; it builds the router.
//! #[tokio::main]
//! async fn main() -> actus::InitResult<()> {
//!     let router = init().await?;
//!     Server::new(router).run(3000).await?;
//!     Ok(())
//! }
//! ```
//!
//! # What's in the box
//!
//! - **Hyper-based HTTP server** — `Server::run(port)` binds `127.0.0.1`;
//!   `Server::run_on(addr)` binds anywhere (e.g. `0.0.0.0:port`). Graceful
//!   shutdown on SIGTERM / SIGINT with a configurable drain deadline.
//! - **Two-macro routing** — `app_routes!` (the app's URL blueprint, with a
//!   `deps` block for injected services) and `#[controller]` + `routes!`
//!   (per-controller verbs, path patterns, typed query/body extraction, a
//!   `prepare` hook, and per-controller `max_body_bytes` / `rate_limit`).
//! - **Longest-prefix routing** at arbitrary depth, with a trailing
//!   `{...rest}` catch-all and distinct `404` vs `405` (carrying `Allow`).
//! - **Typed extraction & state** — query as a multimap, form-urlencoded
//!   bodies, and typed path/query/body params; `prepare` hooks stash typed
//!   values via `params.insert::<T>(...)` that handlers read back.
//! - **Replies** — `reply!` for JSON, chunked streams, and Server-Sent
//!   Events; `WebError` for structured RFC 7807 `application/problem+json`.
//! - **HTTP-protocol features** — `Server::with_cors`, `with_compression`
//!   (gzip/brotli, `compression` feature), a per-request timeout, and three
//!   DoS guards (max connections, in-flight body budget, header-read timeout).
//! - **WebSocket** (`websocket` feature) — `ws::upgrade(...)` from a handler.
//! - **OpenAPI 3.x** (`openapi` feature) — `openapi::generate(...)` walks the
//!   route tree and emits a spec.
//! - **Middleware** — `before` / `after` hooks via `Server::with_middleware`;
//!   ships a `RequestLogger`.
//!
//! See the [`prelude`] for the common imports, and the [repository] for the
//! full guide — philosophy, framework comparisons, and the `examples/`
//! directory with auth, typed bodies, CORS, compression, WebSockets, SSE, and
//! middleware in working code.
//!
//! [hyper]: https://hyper.rs/
//! [tokio]: https://tokio.rs/
//! [`actus-server`]: https://docs.rs/actus-server
//! [`actus-controller`]: https://docs.rs/actus-controller
//! [`actus-reply`]: https://docs.rs/actus-reply
//! [repository]: https://github.com/uniweb/actus

pub use actus_reply::Finalizer;

// Re-exported at the crate root so the `app_routes!` macro can resolve
// `::actus::Router` / `::actus::RouterBuilder` from generated code without
// requiring downstream crates to depend on `actus-server` directly.
pub use actus_server::{GIB, KIB, MIB, RateLimitClass, Router, RouterBuilder, Server};

/// WebSocket support — [`ws::upgrade`], [`ws::WebSocket`], [`ws::Message`].
/// Available with the `websocket` feature.
#[cfg(feature = "websocket")]
pub use actus_server::websocket as ws;

/// OpenAPI 3.x doc generation — [`openapi::generate`], [`openapi::Options`].
/// Available with the `openapi` feature.
#[cfg(feature = "openapi")]
pub use actus_server::openapi;

/// Error type used by `app_routes!`'s generated `init()` for startup-time
/// failures (DB connection refused, env var missing, migrations failing,
/// etc.). Aliased to `anyhow::Error` so any error implementing
/// `std::error::Error + Send + Sync + 'static` converts via `?`, and the
/// generated `init()` slots cleanly into an `anyhow::Result<()>` `main`.
pub type InitError = anyhow::Error;

/// `Result<T, actus::InitError>`. The macro-generated `init()` returns this.
pub type InitResult<T> = ::std::result::Result<T, InitError>;

/// Implementation re-exports used by the procedural macros.
///
/// This module exists so generated code can refer to types from the
/// implementation crates (`actus-controller`, etc.) via stable absolute paths
/// like `::actus::__internal::Verb`. End users should not import from here —
/// use [`prelude`] instead.
#[doc(hidden)]
pub mod __internal {
    pub use actus_controller::*;
    pub use anyhow;
}

/// Common imports for Actus applications.
pub mod prelude {
    pub use actus_controller::{
        Controller, ExtractedParams, Params, RouteDef, Verb, app_routes, controller, routes,
    };
    // Needed to `impl Middleware` (the trait is `#[async_trait]`).
    pub use actus_controller::async_trait;
    pub use actus_reply::prelude::*;
    #[cfg(feature = "compression")]
    pub use actus_server::CompressionLayer;
    #[cfg(feature = "websocket")]
    pub use actus_server::{Message, WebSocket};
    // The `ws` module itself, so `ws::upgrade(...)` works after a glob import.
    #[cfg(feature = "websocket")]
    pub use crate::ws;
    pub use actus_server::{
        CorsLayer, GIB, KIB, MIB, Middleware, Outcome, RateLimitClass, Request, RequestLogger,
        Router, RouterBuilder, Server, ServerError,
    };
    // Re-exported so handlers can declare `body: Bytes` in `routes!`
    // without an extra `use bytes::Bytes;` line. There is one canonical
    // zero-copy bytes type in the Rust HTTP ecosystem; pinning it here
    // means generated extraction code and the handler signature
    // resolve to the same `bytes::Bytes`.
    pub use bytes::Bytes;
}