Skip to main content

mildly_basic_auth/
lib.rs

1//! Transparent password-wall reverse proxy.
2//!
3//! [`build_app`] assembles the whole service: a reverse proxy to the
4//! configured upstream, wrapped by the authentication gate. The binary
5//! (`main.rs`) and the integration tests both build on this single seam.
6
7// The only duplicate crate versions come from transitive dependencies we
8// don't control (WebSocket libs pulled by the proxy, `windows-sys`), so
9// `multiple_crate_versions` here is pure noise under the `clippy::cargo`
10// gate.
11#![allow(clippy::multiple_crate_versions)]
12
13mod config;
14mod gate;
15
16pub use config::{Config, ConfigError};
17
18use axum::Router;
19use axum::middleware::from_fn_with_state;
20use axum_reverse_proxy::{ReverseProxy, Rfc9110Layer};
21
22/// Build the application: the reverse proxy wrapped by the gate.
23///
24/// The proxy is mounted at `/` so every path is forwarded. `Rfc9110Layer`
25/// strips hop-by-hop headers (the base proxy does not) while preserving
26/// the WebSocket upgrade handshake. The gate is the outermost layer, so it
27/// decides passthrough-vs-wall before the proxy ever sees a request.
28pub fn build_app(config: Config) -> Router {
29    // `config.upstream()` is borrowed only for this statement; `config`
30    // is then moved into the gate's state below.
31    let proxy: Router = ReverseProxy::new("/", config.upstream()).into();
32    proxy
33        .layer(Rfc9110Layer::new())
34        .layer(from_fn_with_state(config, gate::gate))
35}