Skip to main content

rust_web_server/
lib.rs

1//! # rust-web-server
2//!
3//! An HTTP/1.1, HTTP/2, and HTTP/3 (QUIC) server, reverse proxy, and
4//! application framework in one crate. HTTP/1.1 parsing, routing, middleware,
5//! JSON, WebSocket, and SSE are implemented in-crate; HTTP/2 and HTTP/3
6//! framing use the `h2` and `quinn`/`h3` crates, and TLS uses `rustls`.
7//!
8//! ## Use as a library
9//!
10//! Add to `Cargo.toml`:
11//!
12//! ```toml
13//! [dependencies]
14//! rust-web-server = "17"
15//! ```
16//!
17//! ## Quick start
18//!
19//! ```rust,no_run
20//! use rust_web_server::prelude::*;
21//!
22//! fn hello(_: &Request, _: &PathParams, _: &ConnectionInfo, _: &()) -> Response {
23//!     Response::text(STATUS_CODE_REASON_PHRASE.n200_ok, "Hello, world!")
24//! }
25//!
26//! fn main() {
27//!     let app = App::with_state(()).get("/hello", hello);
28//!     let (listener, pool) = Server::setup().unwrap();
29//!     Server::run(listener, pool, app);
30//! }
31//! ```
32//!
33//! See [DEVELOPER.md](https://github.com/bohdaq/rust-web-server/blob/main/DEVELOPER.md)
34//! for the full building blocks reference and use case examples.
35
36// Allows `::rust_web_server::…` paths to resolve from within this crate's own
37// tests, which is required by proc-macro derive output that uses that prefix.
38extern crate self as rust_web_server;
39
40pub mod app;
41#[cfg(feature = "auth")]
42pub mod auth;
43
44#[cfg(feature = "macros")]
45pub use rws_macros::{delete, get, patch, post, put, route, Config, FromRequest, Validate};
46#[cfg(all(feature = "macros", any(feature = "model-sqlite", feature = "model-postgres", feature = "model-mysql")))]
47pub use rws_macros::Model;
48#[cfg(feature = "http2")]
49pub mod async_state;
50#[cfg(feature = "http2")]
51pub(crate) mod async_bridge;
52pub mod session;
53// Socket-coupled — see spec/WASM_SHIM.md for what a wasm32-wasip2 build
54// excludes and why (no OS threads, no raw TCP/TLS in a WASI guest).
55#[cfg(not(target_arch = "wasm32"))]
56pub(crate) mod redis_protocol;
57pub mod sse;
58pub mod compression;
59pub mod cookie;
60pub mod error;
61pub mod extract;
62pub mod ip_filter;
63pub mod macros;
64pub mod blocklist;
65pub mod cache;
66pub mod config_reload;
67pub mod server_config;
68pub mod feature;
69pub mod maintenance;
70pub mod metrics;
71pub mod mcp;
72pub mod request_log;
73pub mod request_id;
74#[cfg(not(target_arch = "wasm32"))]
75pub mod otel;
76#[cfg(feature = "acme")]
77pub mod acme;
78pub mod middleware;
79pub mod rate_limit;
80pub mod router;
81pub mod state;
82pub mod test_client;
83pub mod application;
84pub mod body;
85pub mod client_hint;
86pub mod controller;
87pub mod core;
88pub mod cors;
89pub mod entry_point;
90pub mod ext;
91pub mod header;
92pub mod http;
93pub mod json;
94pub mod language;
95#[cfg(not(target_arch = "wasm32"))]
96pub mod log;
97pub mod mime_type;
98pub mod null;
99pub mod range;
100pub mod request;
101pub mod response;
102pub mod server;
103pub mod symbol;
104#[cfg(not(target_arch = "wasm32"))]
105pub mod thread_pool;
106pub mod url;
107pub mod pagination;
108#[cfg(not(target_arch = "wasm32"))]
109pub mod proxy;
110pub mod rewrite;
111pub mod scheduler;
112#[cfg(not(target_arch = "wasm32"))]
113pub mod tcp_proxy;
114#[cfg(not(target_arch = "wasm32"))]
115pub mod udp_proxy;
116#[cfg(not(target_arch = "wasm32"))]
117pub mod ws_proxy;
118#[cfg(not(target_arch = "wasm32"))]
119pub mod canary;
120#[cfg(not(target_arch = "wasm32"))]
121pub mod circuit_breaker;
122// `BackendPool`/`DiscoverySource` (DNS/etcd/Consul/Docker) are native-only —
123// gated internally in service_discovery/mod.rs, not at this declaration —
124// because `json_lite` (a plain JSON parser, no sockets) must stay available
125// for `secrets`'s Vault/AWS-SM/Key-Vault backends on every target.
126pub mod service_discovery;
127pub mod config_binding;
128pub mod di;
129#[cfg(not(target_arch = "wasm32"))]
130pub mod proxy_config;
131#[cfg(not(target_arch = "wasm32"))]
132pub mod ingress;
133#[cfg(feature = "tera")]
134pub mod template;
135pub mod validate;
136pub mod virtual_host;
137#[cfg(any(feature = "model-sqlite", feature = "model-postgres", feature = "model-mysql"))]
138pub mod model;
139#[cfg(not(target_arch = "wasm32"))]
140pub mod websocket;
141// Has both a native (TcpStream/rustls) and a wasm32 (wasi:http outgoing-handler)
142// backend behind Client::send() — see the #[cfg(target_arch = "wasm32")]
143// `send_once` in this module. spec/WASM_SHIM.md Phase 2 item 7.
144pub mod http_client;
145#[cfg(feature = "crypto")]
146pub mod crypto;
147#[cfg(feature = "csrf")]
148pub mod csrf;
149#[cfg(feature = "sso")]
150pub mod sso;
151// SMTP is a raw-TCP protocol with no wasi:http equivalent (unlike
152// http_client, which the host can proxy via outgoing-handler) — genuinely
153// can't work in a wasi:http guest, not just ungated. spec/WASM_SHIM.md.
154#[cfg(all(feature = "mailer", not(target_arch = "wasm32")))]
155pub mod mailer;
156#[cfg(feature = "jobs")]
157pub mod jobs;
158// Also compiled under `secrets` — `secrets::aws_secrets_manager`/`azure_key_vault`
159// reuse `StorageError` and the SigV4/Managed-Identity credential helpers from here.
160#[cfg(any(feature = "storage-local", feature = "storage-s3", feature = "storage-azure", feature = "secrets"))]
161pub mod storage;
162#[cfg(feature = "openapi")]
163pub mod openapi;
164#[cfg(feature = "webhook")]
165pub mod webhook;
166#[cfg(feature = "secrets")]
167pub mod secrets;
168// Runs wrapped work on a background OS thread to bound wait time — needs
169// `std::thread::spawn`, unavailable on wasm32-wasip2. See spec/WASM_SHIM.md.
170#[cfg(not(target_arch = "wasm32"))]
171pub mod timeout;
172pub mod prelude;
173
174#[cfg(feature = "http2")]
175#[doc(hidden)]
176pub mod tls;
177
178#[cfg(feature = "http2")]
179#[doc(hidden)]
180pub mod h2_handler;
181
182#[cfg(feature = "http3")]
183#[doc(hidden)]
184pub mod h3_handler;
185
186/// Shared infrastructure for tests that write process-wide environment variables.
187///
188/// Tests that call `override_environment_variables_from_config` or
189/// `CommandLineArgument::set_environment_variable` must hold this lock for
190/// their entire duration so they don't race with other tests reading the
191/// same variables.
192#[cfg(test)]
193pub mod test_env {
194    use std::sync::{Mutex, OnceLock};
195    static LOCK: OnceLock<Mutex<()>> = OnceLock::new();
196    pub fn lock() -> std::sync::MutexGuard<'static, ()> {
197        LOCK.get_or_init(|| Mutex::new(()))
198            .lock()
199            .unwrap_or_else(|e| e.into_inner())
200    }
201}