Skip to main content

tuitbot_server/
dashboard.rs

1//! Serves the embedded Svelte dashboard as static files with SPA fallback.
2
3use axum::http::{header, StatusCode};
4use axum::response::{IntoResponse, Response};
5use rust_embed::Embed;
6
7#[derive(Embed)]
8#[folder = "dashboard-dist/"]
9struct DashboardAssets;
10
11pub async fn serve_dashboard(uri: axum::http::Uri) -> Response {
12    let path = uri.path().trim_start_matches('/');
13
14    // Try exact file match first.
15    if let Some(file) = DashboardAssets::get(path) {
16        return file_response(path, &file);
17    }
18
19    // SPA fallback: serve index.html for unmatched routes.
20    match DashboardAssets::get("index.html") {
21        Some(file) => file_response("index.html", &file),
22        None => (StatusCode::NOT_FOUND, "Dashboard not available").into_response(),
23    }
24}
25
26fn file_response(path: &str, file: &rust_embed::EmbeddedFile) -> Response {
27    let mime = mime_guess::from_path(path).first_or_octet_stream();
28
29    let cache = if path.contains("_app/immutable") {
30        "public, max-age=31536000, immutable"
31    } else if path == "index.html" {
32        "no-cache"
33    } else {
34        "public, max-age=3600"
35    };
36
37    (
38        StatusCode::OK,
39        [
40            (header::CONTENT_TYPE, mime.as_ref()),
41            (header::CACHE_CONTROL, cache),
42        ],
43        file.data.clone(),
44    )
45        .into_response()
46}