Key changes: - **src/config.rs** – `LiveVueConfig` (server host/port, brotli quality + window size), loaded from `livevue.toml`. A notify-based file watcher reloads the config on any file change; a SIGHUP handler does the same on demand. Falls back to compiled-in defaults when the file is absent. - **src/brotli_layer.rs** – `BrotliBody`, a custom `http_body::Body` wrapper that streams brotli-compressed data through a single persistent `brotli::CompressorWriter`. The encoder survives across SSE event flushes, so its sliding window accumulates context from all prior events — progressively better compression as the stream grows. Both quality (0–11) and window size (lgwin 10–24, i.e. 1 KB – 16 MB) are taken from config. `brotli_compression` is an axum `from_fn_with_state` middleware that activates only when the client sends `Accept-Encoding: br`. - **src/server.rs** – `AppState` gains a `config: SharedConfig` field. `AppState::new` takes the config; `AppState::new_default` is a zero-config convenience constructor. - **livevue.toml** – documented example config with inline comments explaining each field and the brotli window-size tradeoff table. - **examples/todo** – loads config via `load_and_watch_config`, derives the bind address from `config.server`, and applies `brotli_compression` as a router layer. https://claude.ai/code/session_01UnQQkkwts64FPUsSzFfdQb
69 lines
2.6 KiB
TOML
69 lines
2.6 KiB
TOML
# livevue.toml — livevue-rs server configuration
|
||
#
|
||
# This file is optional. The server starts with compiled-in defaults when it
|
||
# is absent. When present, it is loaded on startup and then watched for
|
||
# changes automatically (inotify on Linux, kqueue on macOS, FSEvents on macOS).
|
||
#
|
||
# To force a reload without restarting: kill -HUP <pid>
|
||
#
|
||
# Note: [server] changes (host / port) require a full restart because the TCP
|
||
# listener is bound once at startup. All brotli settings apply to new
|
||
# connections immediately after a reload.
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# HTTP server
|
||
# ---------------------------------------------------------------------------
|
||
|
||
[server]
|
||
|
||
# Address to bind. "0.0.0.0" listens on all interfaces.
|
||
host = "0.0.0.0"
|
||
|
||
# TCP port.
|
||
port = 3000
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Brotli streaming compression
|
||
# ---------------------------------------------------------------------------
|
||
#
|
||
# Brotli is the compression algorithm of choice for Datastar SSE streams.
|
||
# Unlike gzip (which compresses each HTTP response independently), brotli
|
||
# maintains a *sliding window* across the entire SSE byte stream. All events
|
||
# on a connection share a single encoder context, so later events — which
|
||
# often contain similar HTML structure — get compressed with reference to
|
||
# everything that was sent earlier. Compression ratios improve progressively
|
||
# over the lifetime of a long-lived connection.
|
||
#
|
||
# The browser sends "Accept-Encoding: br" if it supports brotli. The
|
||
# middleware checks this and only activates compression for those clients.
|
||
|
||
[brotli]
|
||
|
||
# Set to false to disable brotli and send SSE events uncompressed.
|
||
enabled = true
|
||
|
||
# Encoder quality: 0 (fastest, worst ratio) … 11 (slowest, best ratio).
|
||
#
|
||
# For real-time SSE, 4–6 gives a good latency/ratio tradeoff. Values above 9
|
||
# incur significant CPU cost with diminishing returns for typical HTML
|
||
# payloads. Default: 5.
|
||
quality = 5
|
||
|
||
# Sliding window size as log₂ of bytes (brotli's `lgwin` parameter).
|
||
#
|
||
# The window is how much previously compressed data the encoder can
|
||
# reference. Larger ⇒ better compression, more memory per connection.
|
||
#
|
||
# lgwin │ Window size
|
||
# ──────┼────────────
|
||
# 10 │ 1 KB
|
||
# 16 │ 64 KB
|
||
# 20 │ 1 MB
|
||
# 22 │ 4 MB ← default
|
||
# 24 │ 16 MB
|
||
#
|
||
# For a server with many concurrent SSE connections, consider whether the
|
||
# memory cost (window_size bytes × number of connections) is acceptable.
|
||
# Reduce to 20 or 16 under memory pressure.
|
||
window_size = 22
|