postrust_proxy/lib.rs
1//! # Postrust Proxy
2//!
3//! High-performance reverse proxy module for Postrust with:
4//! - HTTP/1.1 and HTTP/2 support
5//! - Load balancing (round-robin, random, least-connections, weighted, sticky)
6//! - Active health checking
7//! - Rate limiting
8//! - Automatic TLS via Let's Encrypt (ACME)
9//! - Zero-downtime configuration updates
10//!
11//! ## Architecture
12//!
13//! The proxy is built on vendored code from [rust-rpxy](https://github.com/junkurihara/rust-rpxy),
14//! with additional features for database-backed configuration, health checking, and rate limiting.
15//!
16//! ```text
17//! ┌─────────────────────────────────────────────────────────────┐
18//! │ Postrust Proxy │
19//! ├─────────────────────────────────────────────────────────────┤
20//! │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
21//! │ │ Config │ │ Health │ │ Rate Limit │ │
22//! │ │ TOML + DB │ │ Checker │ │ Token Bucket │ │
23//! │ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
24//! │ │ │ │ │
25//! │ └────────────────┼────────────────────┘ │
26//! │ │ │
27//! │ ┌───────────▼───────────┐ │
28//! │ │ Vendored Core │ │
29//! │ │ (from rust-rpxy) │ │
30//! │ │ - Proxy handler │ │
31//! │ │ - Load balancer │ │
32//! │ │ - HTTP forwarding │ │
33//! │ └───────────────────────┘ │
34//! └─────────────────────────────────────────────────────────────┘
35//! ```
36
37#![warn(clippy::all)]
38#![warn(missing_docs)]
39// `result_large_err` and `large_enum_variant` are both rooted in the rich
40// `ProxyError` enum, which is deliberate: an error that says which upstream and
41// why is worth more than a small one. `type_complexity` covers a few internal
42// signatures waiting to become type aliases.
43#![allow(clippy::result_large_err)]
44#![allow(clippy::large_enum_variant)]
45#![allow(clippy::type_complexity)]
46
47pub mod admin;
48pub mod config;
49pub mod health;
50pub mod ratelimit;
51pub mod saas;
52pub mod tls;
53pub mod vendored;
54
55mod error;
56
57pub use error::{ProxyError, ProxyResult};
58
59// Re-export key types for convenience
60pub use config::{Backend, ProxyConfig, Route, Upstream};
61pub use health::HealthChecker;
62pub use ratelimit::RateLimiter;
63
64/// Proxy server state shared across handlers.
65pub struct ProxyState {
66 /// Database connection pool
67 pub pool: sqlx::PgPool,
68 /// Current proxy configuration
69 pub config: std::sync::Arc<tokio::sync::RwLock<ProxyConfig>>,
70 /// Health checker instance
71 pub health_checker: std::sync::Arc<HealthChecker>,
72 /// Rate limiter instance.
73 ///
74 /// Its cleanup task is not started here. [`vendored::ProxyService`]
75 /// starts it for the limiter it is given when it begins serving; a limiter
76 /// used anywhere else needs [`RateLimiter::start_cleanup`] spawned, or
77 /// the clients it has seen are never forgotten.
78 pub rate_limiter: std::sync::Arc<RateLimiter>,
79}
80
81impl ProxyState {
82 /// Create a new proxy state.
83 pub async fn new(pool: sqlx::PgPool, config: ProxyConfig) -> ProxyResult<Self> {
84 let rate_limit_defaults = config.rate_limit.clone();
85 let config = std::sync::Arc::new(tokio::sync::RwLock::new(config));
86 let health_checker = std::sync::Arc::new(HealthChecker::new());
87 let rate_limiter = std::sync::Arc::new(RateLimiter::new(rate_limit_defaults));
88
89 Ok(Self {
90 pool,
91 config,
92 health_checker,
93 rate_limiter,
94 })
95 }
96}