Skip to main content

o_sfu/runtime/http_server/
mod.rs

1//! HTTP control-plane families and WebSocket listener composition.
2//!
3//! [`rooms`] owns authenticated room operations and request limits.
4//! [`operator`] owns protected stats, metrics and diagnostics routes.
5//! Each family exposes its assembled router and keeps handlers private.
6//!
7//! [`server`] binds the listener and owns graceful shutdown. [`request_metrics`]
8//! counts control requests, including rejections, while excluding diagnostics
9//! and WebSocket upgrades. [`contract`] preserves public paths and payloads.
10
11use std::{net::SocketAddr, sync::Arc};
12
13use axum::{Router, middleware, response::IntoResponse, routing::get};
14use tracing::Instrument;
15
16use self::contract::{NoopResponse, route};
17use super::{RuntimeState, telemetry, websocket_server};
18
19#[cfg(test)]
20#[expect(non_snake_case, reason = "test modules map to local TESTS directories")]
21mod TESTS;
22mod access;
23pub(crate) mod contract;
24mod operator;
25mod request_metrics;
26mod rooms;
27mod server;
28
29pub(crate) use self::server::{serve_http, serve_http_on};
30
31/// Composes public liveness, authenticated HTTP families and WebSocket upgrades.
32///
33/// Operator authorization uses the actual listener address. WebSocket
34/// authentication runs after the upgrade. Control request tracking wraps
35/// authorization and input extraction so rejected requests remain counted.
36pub(super) fn app(state: RuntimeState, listener_address: SocketAddr) -> Router {
37    Router::new()
38        .route(route::v1::NOOP, get(noop))
39        .merge(rooms::routes())
40        .merge(operator::routes(&state, listener_address))
41        .route_layer(middleware::from_fn_with_state(
42            Arc::clone(&state.metrics),
43            request_metrics::track_request,
44        ))
45        .route(route::WEBSOCKET, get(websocket_server::upgrade))
46        .with_state(state)
47}
48
49/// Liveness endpoint for a cheap control-plane round trip.
50async fn noop() -> impl IntoResponse {
51    async { axum::Json(NoopResponse::ok()) }
52        .instrument(telemetry::http_request_span("noop"))
53        .await
54}