use crate::state::AppState; use axum::{ extract::{Path, State}, http::{HeaderMap, HeaderValue, StatusCode, header}, response::{Html, IntoResponse, Response}, }; use std::sync::Arc; const INDEX: &str = include_str!("web/index.html"); const ICONS: &str = include_str!("web/icons.svg"); const EN: &str = include_str!("web/i18n/en.json"); const PL: &str = include_str!("web/i18n/pl.json"); const CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/postfixadmin-rs.css")); const JS: &str = include_str!(concat!(env!("OUT_DIR"), "/postfixadmin-rs.js")); const ASSET_ID: &str = env!("POSTFIXADMIN_RS_ASSET_ID"); pub async fn index(State(state): State>) -> Html { let base = state.config.normalized_base_path(); let base = if base == "/" { "/".into() } else { format!("{base}/") }; Html( INDEX .replace("__BASE_PATH__", &base) .replace("__ASSET_ID__", ASSET_ID) .replace("__VERSION__", env!("CARGO_PKG_VERSION")) .replace("__LANG__", &state.config.default_language), ) } pub async fn asset(Path(path): Path) -> Response { let path = path.trim_start_matches('/'); let (body, ctype, immutable) = match path { p if p == format!("app.{ASSET_ID}.css") => (CSS, "text/css; charset=utf-8", true), p if p == format!("app.{ASSET_ID}.js") => { (JS, "application/javascript; charset=utf-8", true) } p if p == format!("icons.{ASSET_ID}.svg") => (ICONS, "image/svg+xml", true), "icons.svg" => (ICONS, "image/svg+xml", false), "i18n/en.json" => (EN, "application/json; charset=utf-8", false), "i18n/pl.json" => (PL, "application/json; charset=utf-8", false), _ => ("", "text/plain", false), }; if body.is_empty() { return StatusCode::NOT_FOUND.into_response(); } let mut h = HeaderMap::new(); h.insert(header::CONTENT_TYPE, HeaderValue::from_static(ctype)); h.insert( header::CACHE_CONTROL, HeaderValue::from_static(if immutable { "public, max-age=31536000, immutable" } else { "no-cache" }), ); (h, body).into_response() }