rust-web-server 18.15.0

Single-binary web server and reverse proxy: automatic HTTPS (Let's Encrypt), HTTP/1.1, HTTP/2 and HTTP/3, load balancing, auth and rate limiting, configured in one TOML file. Also a Rust library: routing, middleware, MCP server, ORM, background jobs. No hyper, no Tower; HTTP/2 and HTTP/3 framing via h2 and quinn.
Documentation
//! `[traffic]` settings (`RWS_CONFIG_TRAFFIC_*`).

use std::path::PathBuf;

pub const RWS_CONFIG_TRAFFIC_ENABLED: &str = "RWS_CONFIG_TRAFFIC_ENABLED";
pub const RWS_CONFIG_TRAFFIC_RETENTION_DAYS: &str = "RWS_CONFIG_TRAFFIC_RETENTION_DAYS";
pub const RWS_CONFIG_TRAFFIC_PERSIST: &str = "RWS_CONFIG_TRAFFIC_PERSIST";
pub const RWS_CONFIG_TRAFFIC_EXCLUDE: &str = "RWS_CONFIG_TRAFFIC_EXCLUDE";

fn read(key: &str) -> String {
    std::env::var(key).unwrap_or_default().trim().to_string()
}

/// `enabled`: `Some(false)` turns counting off even with the admin API on;
/// `None` when unset.
pub fn enabled_setting() -> Option<bool> {
    match read(RWS_CONFIG_TRAFFIC_ENABLED).to_ascii_lowercase().as_str() {
        "" => None,
        "false" | "0" | "no" | "off" => Some(false),
        _ => Some(true),
    }
}

/// `retention_days`: 1–90, default 30.
pub fn retention_days() -> u64 {
    read(RWS_CONFIG_TRAFFIC_RETENTION_DAYS).parse::<u64>().ok().filter(|d| *d >= 1).map_or(30, |d| d.min(90))
}

/// `exclude`: exact paths not counted (comma-separated); default the
/// health, readiness and metrics endpoints.
pub fn exclude() -> Vec<String> {
    let value = std::env::var(RWS_CONFIG_TRAFFIC_EXCLUDE);
    match value {
        Ok(v) => v.split(',').map(str::trim).filter(|p| !p.is_empty()).map(str::to_string).collect(),
        Err(_) => ["/healthz", "/readyz", "/metrics"].iter().map(|p| p.to_string()).collect(),
    }
}

/// `persist`: the file the counts are saved to. Unset: `traffic.json` next
/// to the certificate (the ACME certificate's directory, else the TLS
/// certificate's) — the state directory; without either, nothing is
/// saved. `"off"`: not saved.
pub fn persist_path() -> Option<PathBuf> {
    let value = read(RWS_CONFIG_TRAFFIC_PERSIST);
    if value.eq_ignore_ascii_case("off") {
        return None;
    }
    if !value.is_empty() {
        return Some(PathBuf::from(value));
    }
    [crate::entry_point::Config::RWS_CONFIG_ACME_CERT_PATH, crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE]
        .iter()
        .map(|key| read(key))
        .find(|path| !path.is_empty())
        .and_then(|cert| PathBuf::from(cert).parent().map(|dir| dir.join("traffic.json")))
}