lilydocs
HTTP APIWebSocketConsumer
Running the application3 min read

TLS, proxies, and heartbeats

Configure a WSS listener, resolve client IPs through trusted proxy chains, and bound connection liveness.

The WebSocket server uses HTTP/1.1 Upgrade. TLS, client IP, and heartbeat policies belong to the listener; they are not derived from a message DTO or a client-claimed header.

WSS listener#

The following file combines WSS, external-container, and health-registration examples. It requires tokio-util = "0.7" and the DI dependencies. The configuration-backed wss function also requires [websocket].enabled = true and an Origin policy.

application.rs
use std::{path::Path, sync::Arc};
use lilyrs::websocket::ApplicationContainer;
use lilyrs::websocket::{RustlsConfig, WsApp, WsAppBuilder};
use tokio_util::sync::CancellationToken;

pub async fn wss(cert: &Path, key: &Path) -> Result<WsApp, Box<dyn std::error::Error>> {
    let tls = RustlsConfig::from_pem_file(cert, key).await?;
    Ok(WsAppBuilder::default().rustls_config(tls).build().await?)
}
pub async fn external_container(container: &Arc<ApplicationContainer>)
    -> Result<(), Box<dyn std::error::Error>>
{
    let app = WsAppBuilder::new("127.0.0.1:8081")
        .container(Arc::clone(container)).build().await?;
    app.close().await?; // An app that has not started also closes; any error returns to the caller here.
    container.close().await?; // The caller closes the external container after success.
    Ok(())
}
pub async fn run(app: WsApp, shutdown: CancellationToken)
    -> Result<(), Box<dyn std::error::Error>>
{
    let dependencies = app.required_dependency_health();
    dependencies.register_required("orders.store")?;
    // Call mark_healthy / mark_unhealthy when an actual probe result arrives.
    let _initial_health = app.health_snapshot()?;
    let _initial_metrics = app.metrics_snapshot();
    app.start_with_cancellation(shutdown).await?;
    Ok(())
}

Download the complete example.

The caller supplies the certificate and private-key files. wss builds the app; complete either the start or close path on the returned app. Adding PEM fields under [websocket] does not automatically configure TLS; in this version, .rustls_config(...) is authoritative.

TLS boundary#

The Rustls listener selects ALPN for HTTP/1.1. Shared RustlsConfig can use a client CA for TLS client authentication; this does not automatically produce an application Principal. Identity middleware is still required.

Do not assume HTTP/2 extended CONNECT/RFC 8441, HTTP/3, or compression-extension support. is_secure() reports TLS directly at the Lily listener. If a proxy terminates TLS and uses plaintext internally, neither X-Forwarded-Proto nor an HTTPS Origin makes this value true.

Trusted proxies#

ServerConfig.trusted_proxy_cidrs takes a typed TrustedProxyNetwork list, while central configuration takes CIDR strings. Define only proxy networks you actually manage. The default list is empty.

If the direct socket peer is untrusted, client IP is not derived from forwarding metadata. For a trusted peer, X-Forwarded-For is resolved from right to left up to the first untrusted hop. Malformed or overly long trusted chains are rejected with 400 before identity processing. The hop cap defaults to 16 and accepts 1..=64.

Use normalized client_ip, peer_addr, and via_trusted_proxy information. Do not treat raw forwarding or reserved edge-identity headers as verified user identity. Handshake rate limiting depends on choosing trusted keys.

Heartbeats and idle time#

Defaults are a 30-second Ping interval, a 10-second Pong wait, and a 60-second application idle duration. The reader continues processing control frames during a long action. Ping/Pong traffic is separate from the application message queue.

Application idle, connection uptime, and message age are different measurements. Consider proxy idle timeouts together with heartbeat settings. Single-frame, reassembled-message, and outbound-write limits are on the backpressure page.

Sources for this page v0.1.0

This guide is based on the reviewed framework commit.

QUICK START
Documentation
Source code