trillium_tokio/lib.rs
1#![forbid(unsafe_code)]
2#![deny(
3 clippy::dbg_macro,
4 missing_copy_implementations,
5 rustdoc::missing_crate_level_docs,
6 missing_debug_implementations,
7 missing_docs,
8 nonstandard_style,
9 unused_qualifications
10)]
11//! # Trillium server adapter for tokio
12//!
13//! ```rust,no_run
14//! # #[allow(clippy::needless_doctest_main)]
15//! fn main() {
16//! trillium_tokio::run(|conn: trillium::Conn| async move { conn.ok("hello tokio") });
17//! }
18//! ```
19//!
20//! ```rust,no_run
21//! # #[allow(clippy::needless_doctest_main)]
22//! #[tokio::main]
23//! async fn main() {
24//! trillium_tokio::run_async(|conn: trillium::Conn| async move { conn.ok("hello tokio") })
25//! .await;
26//! }
27//! ```
28//!
29//! For advanced binding — several listeners on one server, fallible binds you
30//! can recover from, or adopting an already-bound socket — call
31//! [`.listeners()`](trillium_server_common::Config::listeners)
32//! on a [`config()`](trillium_server_common::Config) to get a [`ListenerConfig`].
33//!
34//! ## Thread-per-core with `SO_REUSEPORT` on Linux
35//!
36//! `SO_REUSEPORT` is a socket option that lets several sockets bind the same
37//! address and port at once, with the kernel distributing incoming connections
38//! across them. Enable the `reuseport` cargo feature on Linux to use it for
39//! thread-per-core fan-out:
40//!
41//! ```rust,ignore
42//! use trillium::Conn;
43//!
44//! fn main() -> std::io::Result<()> {
45//! trillium_tokio::config()
46//! .listeners()
47//! .bind_reuseport_tcp(8080)?
48//! .run(|conn: Conn| async move { conn.ok("hello") });
49//! Ok(())
50//! }
51//! ```
52//!
53//! Each worker thread runs its own single-threaded runtime, pinned to a core,
54//! driving that worker's accept loop — one `SO_REUSEPORT` listener per worker.
55//! The standard multi-threaded work-stealing runtime is still present alongside
56//! them, hosting HTTP/3, signal handling, and the application tasks you spawn,
57//! so QUIC is never fanned out this way. Set the worker count with
58//! `.with_reuseport_workers(n)`; it defaults to the `WORKERS` environment
59//! variable, or if that's not set, to available parallelism.
60//!
61//! This trades the work-stealing runtime's load balancing for per-core
62//! locality, which can improve throughput for short, CPU-cheap requests served
63//! over many connections. It is gated off on platforms where plain
64//! `SO_REUSEPORT` does not distribute connections (including macOS), where it
65//! would offer no benefit.
66
67#[cfg(test)]
68#[doc = include_str!("../README.md")]
69mod readme {}
70
71use trillium::Handler;
72pub use trillium_server_common::{Binding, IntoListenAddr, ListenerConfig, Swansong};
73
74mod client;
75pub use client::ClientConfig;
76
77mod server;
78pub use async_compat;
79use server::Config;
80pub use tokio;
81pub use tokio_stream;
82
83mod transport;
84pub use transport::TokioTransport;
85
86/// # Runs a trillium handler in a sync context with default config
87///
88/// Runs a trillium handler on the tokio runtime with
89/// default configuration. See [`crate::config`] for what the defaults are
90/// and how to override them
91///
92///
93/// This function will block the current thread until the server shuts
94/// down
95pub fn run(handler: impl Handler) {
96 config().run(handler)
97}
98
99/// # Runs a trillium handler in an async context with default config
100///
101/// Run the provided trillium handler on an already-running tokio runtime
102/// with default settings. The defaults are the same as [`crate::run`]. To
103/// customize these settings, see [`crate::config`].
104///
105/// This function will poll pending until the server shuts down.
106pub async fn run_async(handler: impl Handler) {
107 config().run_async(handler).await
108}
109
110/// # Configures a server before running it
111///
112/// ## Defaults
113///
114/// The default configuration is as follows:
115///
116/// port: the contents of the `PORT` env var or else 8080
117/// host: the contents of the `HOST` env var or else "localhost"
118/// signals handling and graceful shutdown: enabled on cfg(unix) systems
119/// tcp nodelay: disabled
120/// tls acceptor: none
121///
122/// ## Usage
123///
124/// ```rust
125/// let swansong = trillium_tokio::Swansong::new();
126/// # swansong.shut_down(); // stoppping the server immediately for the test
127/// trillium_tokio::config()
128/// .with_port(0)
129/// .with_host("127.0.0.1")
130/// .without_signals()
131/// .with_nodelay()
132/// .with_acceptor(()) // see [`trillium_rustls`], [`trillium_native_tls`], and [`trillium_openssl`]
133/// .with_swansong(swansong)
134/// .run(|conn: trillium::Conn| async move { conn.ok("hello tokio") });
135/// ```
136///
137/// See [`trillium_server_common::Config`] for more details
138pub fn config() -> Config<()> {
139 Config::new()
140}
141
142mod runtime;
143pub use runtime::TokioRuntime;
144
145#[cfg(all(
146 feature = "reuseport",
147 unix,
148 not(target_os = "solaris"),
149 not(target_os = "illumos"),
150 not(target_os = "cygwin"),
151 not(target_vendor = "apple")
152))]
153mod reuseport;
154
155mod udp;
156pub use udp::TokioUdpSocket;