use poem::{ Response, handler, http::{StatusCode, header}, web::Path, }; use rust_embed::RustEmbed; #[derive(RustEmbed)] #[folder = "../frontend/dist"] struct EmbeddedAssets; fn serve_embedded(path: &str) -> Response { let normalized = if path.is_empty() { "index.html" } else { path.trim_start_matches('/') }; let is_asset_request = normalized.starts_with("assets/"); let asset = if is_asset_request { EmbeddedAssets::get(normalized) } else { EmbeddedAssets::get(normalized).or_else(|| { if normalized == "index.html" { None } else { EmbeddedAssets::get("index.html") } }) }; match asset { Some(content) => { let body = content.data.into_owned(); let mime = mime_guess::from_path(normalized) .first_or_octet_stream() .to_string(); Response::builder() .status(StatusCode::OK) .header(header::CONTENT_TYPE, mime) .body(body) } None => Response::builder() .status(StatusCode::NOT_FOUND) .body("Not Found"), } } /// Serve a single embedded asset from the `assets/` folder. #[handler] pub fn embedded_asset(Path(path): Path) -> Response { let asset_path = format!("assets/{path}"); serve_embedded(&asset_path) } /// Serve an embedded file by path (falls back to `index.html` for SPA routing). #[handler] pub fn embedded_file(Path(path): Path) -> Response { serve_embedded(&path) } /// Serve the embedded SPA entrypoint. #[handler] pub fn embedded_index() -> Response { serve_embedded("index.html") }