Skip to main content

tty_web/web/
mod.rs

1//! HTTP and WebSocket server built on [Axum](https://docs.rs/axum).
2//!
3//! Routes:
4//! - `GET /ws` — WebSocket endpoint (terminal I/O)
5//! - `GET /api/v1/ping` — health check
6//! - `GET /` and `GET /*path` — embedded static frontend
7
8pub mod health;
9pub mod static_files;
10pub mod ws;
11
12use std::path::PathBuf;
13use std::sync::Arc;
14
15use axum::Router;
16use axum::routing::get;
17
18use crate::session::SessionStore;
19
20/// Shared state passed to all request handlers.
21#[derive(Clone)]
22#[non_exhaustive]
23pub struct AppState {
24    /// Shell binary path (e.g. `/bin/bash`).
25    pub shell: String,
26    /// Working directory for new shell sessions.
27    pub pwd: Option<PathBuf>,
28    /// Scrollback buffer size in bytes.
29    pub scrollback_limit: usize,
30    /// Global session registry.
31    pub sessions: Arc<SessionStore>,
32    /// Time without clients before a session is reaped.
33    pub orphan_timeout: std::time::Duration,
34}
35
36/// Build the Axum router with all routes and shared state.
37pub fn router(
38    shell: String,
39    pwd: Option<PathBuf>,
40    scrollback_limit: usize,
41    sessions: Arc<SessionStore>,
42    orphan_timeout: std::time::Duration,
43) -> Router {
44    let state = AppState {
45        shell,
46        pwd,
47        scrollback_limit,
48        sessions,
49        orphan_timeout,
50    };
51    Router::new()
52        .route("/ws", get(ws::ws_handler))
53        .route("/api/v1/ping", get(health::ping))
54        .route("/", get(static_files::index))
55        .route("/{*path}", get(static_files::static_file))
56        .with_state(state)
57}