Automatic HTTPS
Built-in ACME client: Let’s Encrypt or a private CA, HTTP→HTTPS redirects, background renewal with hot reload, IPv4 and IPv6.
brew install bohdaq/tap/rws # or: cargo binstall rust-web-serverdocker run -p 7878:7878 -v "$PWD:/srv" ghcr.io/bohdaq/rwscd my-site && rwsServes the directory on http://localhost:7878 — index.html, directory
listings, ETags, gzip, byte ranges, and an optional SPA fallback for
client-side routers.
port = 443http_redirect_port = 80
[acme]domains = ["example.com", "www.example.com"]email = "you@example.com"Certificates come from Let’s Encrypt on first start and renew in the background with zero-downtime reloads; HTTP redirects to HTTPS; HTTP/2 and HTTP/3 are on. How it works →
[[upstream]]name = "app"backends = ["localhost:3000", "localhost:3001"]
[upstream.health_check] path = "/healthz"
[[route]] [route.match] path = "/api/*"
[route.action] type = "proxy" upstream = "app"
[route.middleware] rate_limit = { max_requests = 500, window_secs = 60 }Requests under /api/ are load-balanced across healthy backends; everything
else falls through to the static files. Add [acme] for HTTPS in front.
Config-driven proxy →
Automatic HTTPS
Built-in ACME client: Let’s Encrypt or a private CA, HTTP→HTTPS redirects, background renewal with hot reload, IPv4 and IPv6.
Reverse proxy & gateway
Load balancing, health checks, bearer / JWT / basic auth that fails closed, rate limits, caching, rewrites, IP filters — plus TCP, UDP, WebSocket, and gRPC proxying.
One TOML file
Every setting lives in rws.config.toml (or env vars, or flags). Unknown keys are reported at startup instead of silently ignored.
No hyper, no Tower, no OpenSSL
HTTP/1.1, routing, middleware, WebSocket, SSE, and the ACME client are implemented in-crate. HTTP/2 and HTTP/3 use h2 and quinn; TLS uses rustls.
Kubernetes-ready
/healthz, /readyz, Prometheus /metrics, graceful SIGTERM shutdown, and a Kubernetes Ingress watcher.
MCP server
Expose tools, resources, and prompts to Claude and other AI agents over MCP Streamable HTTP with a builder API.
The server above is the rust-web-server crate. Use it directly for routes,
middleware, an MCP server, an ORM, background jobs, and more:
[dependencies]rust-web-server = "17"tokio = { version = "1", features = ["rt-multi-thread", "macros"] }use rust_web_server::prelude::*;
fn hello(_: &Request, _: &PathParams, _: &ConnectionInfo, _: &()) -> Response { Response::text(STATUS_CODE_REASON_PHRASE.n200_ok, "Hello, world!")}
#[tokio::main]async fn main() { let app = routes! { App::with_state(()), GET "/hello" => hello, }; let (listener, pool) = Server::setup().unwrap(); tokio::join!( Server::run_tls(listener, pool, app.clone()), Server::run_quic(app), Server::run_redirect(), );}One middleware trait
Auth, rate limiting, caching, tracing, rewriting, and the reverse proxy itself share one handle(request, connection, next) signature.
Model layer ORM
#[derive(Model)], a type-safe QueryBuilder, migrations, and relations — SQLite, PostgreSQL, or MySQL.
Login & auth
OAuth 2.0 / OIDC (“Login with Google”), SAML 2.0, its own OAuth authorization server, sessions, CSRF.
In-process test client
TestClient::new(app) dispatches requests without opening a socket — fast, hermetic tests.
http1 |
http2 |
http3 (default) |
|
|---|---|---|---|
| Runtime | sync thread pool | tokio | tokio |
| TLS | — | rustls | rustls |
| HTTP/2 | — | ALPN | ALPN |
| QUIC | — | — | quinn |
| MSRV | 1.88 | 1.88 | 1.88 |
The prebuilt binaries are the default build plus the acme and auth features.