kerniq_server/lib.rs
1//! # Kerniq Server
2//!
3//! A lightweight, asynchronous web framework for Rust: the approachability
4//! of Flask on top of Axum, Tower, Hyper and Tokio.
5//!
6//! ```no_run
7//! use kerniq_server::prelude::*;
8//!
9//! #[tokio::main]
10//! async fn main() -> Result<()> {
11//! App::new()
12//! .get("/", || async { "Hello from Kerniq" })
13//! .run("127.0.0.1:3000")
14//! .await
15//! }
16//! ```
17//!
18//! ## What Kerniq adds, and what it reuses
19//!
20//! Kerniq is a thin ergonomic layer. Routing, extraction and HTTP are
21//! Axum's; middleware is Tower's; the protocol is Hyper's; execution is
22//! Tokio's. Kerniq contributes:
23//!
24//! * the [`App`] builder: Flask-style route registration, typed state,
25//! configuration, lifecycle (graceful shutdown, background tasks,
26//! connection and concurrency limits) in one place,
27//! * [`Router`](routing::Router) with prefixes, groups and mounting,
28//! * middleware that applies to every route regardless of declaration order,
29//! with first-declared-is-outermost ordering,
30//! * one JSON error envelope for application errors, malformed input,
31//! 404/405, timeouts, rate limiting and authentication failures,
32//! * production middleware (logging, request IDs, CORS, compression,
33//! timeouts, rate limiting, auth extension points, metrics),
34//! * optional OpenAPI, validation and WebSocket support.
35//!
36//! Handlers are plain Axum handlers, and the app converts to an
37//! [`axum::Router`] with [`App::into_axum_router`], so the Axum and Tower
38//! ecosystems stay fully available.
39//!
40//! ## Crate features
41//!
42//! | Feature | Default | Enables |
43//! |---|---|---|
44//! | `json` | ✓ | `Json<T>`, `Created<T>` |
45//! | `tracing` | ✓ | `Logger` middleware |
46//! | `cors` | | `Cors` middleware |
47//! | `compression` | | `Compression` middleware |
48//! | `websocket` | | [`extract::ws`] |
49//! | `openapi` | | `openapi` module (Utoipa + Swagger UI) |
50//! | `validation` | | `ValidatedJson`, `ValidatedQuery` |
51//! | `config-file` | | `ServerConfig::from_file` (TOML) |
52//! | `macros` | | [`authorize`] attribute for role/permission checks |
53//! | `full` | | all of the above |
54//! | `observability` | | [`App::observability`], `observability` module |
55//! | `observability-metrics` | | OpenTelemetry metrics, HTTP metrics |
56//! | `observability-logs` | | JSON / pretty console logs, log export |
57//! | `observability-tracing` | | distributed tracing, W3C propagation |
58//! | `otlp` / `otlp-tls` | | OTLP export to a Collector or backend |
59//! | `prometheus` | | Prometheus scrape endpoint |
60//! | `runtime-metrics` | | Tokio and process metrics |
61//! | `full-observability` | | all observability features except `otlp-tls` |
62
63#![warn(missing_docs)]
64#![cfg_attr(docsrs, feature(doc_cfg))]
65
66mod builder;
67pub mod prelude;
68
69pub use builder::App;
70pub use kerniq_core::{Error, Result};
71
72#[cfg(feature = "macros")]
73pub use kerniq_macros::authorize;
74
75/// Re-export of Axum, for interoperability with Axum handlers, routers and
76/// extractors at a guaranteed-compatible version.
77pub use axum;
78/// Re-export of `http`.
79pub use http;
80/// Re-export of Tower.
81pub use tower;
82
83/// The error model. See [`Error`].
84pub mod error {
85 pub use kerniq_core::error::*;
86}
87
88/// Server configuration. See [`ServerConfig`](config::ServerConfig).
89pub mod config {
90 pub use kerniq_core::config::*;
91}
92
93/// Request extractors.
94pub mod extract {
95 pub use kerniq_http::extractors::*;
96 #[cfg(feature = "websocket")]
97 pub use kerniq_http::ws;
98 pub use kerniq_http::{
99 Body, Bytes, ConnectInfo, Extension, HeaderMap, MatchedPath, OriginalUri, Request, State,
100 };
101 #[cfg(feature = "validation")]
102 pub use kerniq_http::{ValidatedJson, ValidatedQuery, validation_error};
103}
104
105/// Response types.
106pub mod response {
107 pub use kerniq_http::response::*;
108}
109
110/// Routers, groups and method routers.
111pub mod routing {
112 pub use kerniq_routing::path;
113 pub use kerniq_routing::{Group, RouteInfo, Router, methods};
114}
115
116/// Middleware: the composition traits and the built-in middleware.
117pub mod middleware {
118 pub use kerniq_middleware::*;
119 pub use kerniq_routing::{Middleware, MiddlewareStack, TowerLayer};
120}
121
122/// Server lifecycle: shutdown handles, background tasks and runtime helpers.
123pub mod runtime {
124 pub use kerniq_runtime::runtime::in_runtime;
125 pub use kerniq_runtime::{BackgroundTasks, ServeOptions, Shutdown, os_signal};
126}
127
128/// Kerniq Observe: metrics, logs and traces (feature `observability`).
129/// See [`App::observability`].
130#[cfg(feature = "observability")]
131pub mod observability {
132 pub use kerniq_observability::*;
133}
134
135/// OpenAPI documents and Swagger UI (feature `openapi`).
136#[cfg(feature = "openapi")]
137pub mod openapi {
138 pub use kerniq_openapi::*;
139}
140
141/// Compiles every Rust snippet in the README and the guides in `docs/`, so
142/// documentation cannot drift from the API. Pages that need optional
143/// features are only checked when those features are enabled.
144#[cfg(doctest)]
145mod documentation {
146 macro_rules! doc_page {
147 ($name:ident, $path:literal) => {
148 #[doc = include_str!(concat!("../../../", $path))]
149 struct $name;
150 };
151 ($name:ident, $path:literal, $($feature:literal),+) => {
152 #[cfg(all($(feature = $feature),+))]
153 #[doc = include_str!(concat!("../../../", $path))]
154 struct $name;
155 };
156 }
157
158 doc_page!(Readme, "README.md", "json", "tracing");
159 doc_page!(GettingStarted, "docs/getting-started.md", "json");
160 doc_page!(Routing, "docs/routing.md");
161 doc_page!(Handlers, "docs/handlers.md", "json");
162 doc_page!(Extractors, "docs/extractors.md", "json", "validation");
163 doc_page!(StateManagement, "docs/state-management.md", "json");
164 doc_page!(Middleware, "docs/middleware.md", "tracing", "cors");
165 doc_page!(Authorization, "docs/authorization.md", "macros", "json");
166 doc_page!(AxumInterop, "docs/axum-interop.md", "json");
167 doc_page!(Runtime, "docs/runtime.md");
168 doc_page!(Websockets, "docs/websockets.md", "websocket");
169 doc_page!(Configuration, "docs/configuration.md", "config-file");
170 doc_page!(Integrations, "docs/integrations.md");
171 doc_page!(OpenApi, "docs/openapi.md", "openapi", "json");
172 doc_page!(Performance, "docs/performance.md");
173 doc_page!(Architecture, "docs/architecture.md");
174 doc_page!(
175 ObsOverview,
176 "docs/observability/overview.md",
177 "full-observability"
178 );
179 doc_page!(
180 ObsArchitecture,
181 "docs/observability/architecture.md",
182 "full-observability"
183 );
184 doc_page!(
185 ObsPrometheus,
186 "docs/observability/prometheus.md",
187 "full-observability"
188 );
189 doc_page!(ObsOtlp, "docs/observability/otlp.md", "full-observability");
190 doc_page!(
191 ObsLogging,
192 "docs/observability/logging.md",
193 "full-observability"
194 );
195 doc_page!(
196 ObsTracing,
197 "docs/observability/tracing.md",
198 "full-observability"
199 );
200 doc_page!(
201 ObsCustomMetrics,
202 "docs/observability/custom-metrics.md",
203 "full-observability"
204 );
205 doc_page!(
206 ObsGrafana,
207 "docs/observability/grafana.md",
208 "full-observability"
209 );
210 doc_page!(
211 ObsVendors,
212 "docs/observability/vendor-integrations.md",
213 "full-observability"
214 );
215 doc_page!(
216 ObsPerformance,
217 "docs/observability/performance.md",
218 "full-observability"
219 );
220 doc_page!(
221 ObsConfiguration,
222 "docs/observability/configuration.md",
223 "full-observability"
224 );
225 doc_page!(
226 ObsTroubleshooting,
227 "docs/observability/troubleshooting.md",
228 "full-observability"
229 );
230}