use axum::{
Json,
body::Body,
extract::State,
http::{StatusCode, Uri, header},
response::IntoResponse,
};
use rust_embed::RustEmbed;
use serde::Serialize;
#[derive(RustEmbed)]
#[folder = "assets/webui"]
struct Assets;
#[derive(Serialize)]
pub struct RuntimeConfig {
#[serde(rename = "backendUrl")]
pub backend_url: String,
}
pub async fn serve_runtime_config(State(config): State<crate::ServerConfig>) -> impl IntoResponse {
let backend_url = config.backend_url.unwrap_or_else(|| "/api".to_string());
Json(RuntimeConfig { backend_url })
}
pub async fn serve_ui_assets(uri: Uri) -> impl IntoResponse {
let mut path = uri.path().trim_start_matches("/ui/").to_string();
if path.is_empty() {
path = "index.html".to_string();
}
match Assets::get(&path) {
Some(content) => {
let mime = mime_guess::from_path(&path).first_or_octet_stream();
let mime_header = header::HeaderValue::from_str(mime.as_ref())
.unwrap_or_else(|_| header::HeaderValue::from_static("application/octet-stream"));
([(header::CONTENT_TYPE, mime_header)], Body::from(content.data)).into_response()
}
None => {
if path.contains('.') {
StatusCode::NOT_FOUND.into_response()
} else {
match Assets::get("index.html") {
Some(content) => {
let mime = mime_guess::from_path("index.html").first_or_octet_stream();
let mime_header = header::HeaderValue::from_str(mime.as_ref())
.unwrap_or_else(|_| header::HeaderValue::from_static("text/html"));
([(header::CONTENT_TYPE, mime_header)], Body::from(content.data))
.into_response()
}
None => StatusCode::NOT_FOUND.into_response(),
}
}
}
}
}
pub async fn root_redirect() -> impl IntoResponse {
axum::response::Redirect::to("/ui/")
}
pub async fn serve_ui_index() -> impl IntoResponse {
match Assets::get("index.html") {
Some(content) => {
let mime_header = header::HeaderValue::from_static("text/html; charset=utf-8");
([(header::CONTENT_TYPE, mime_header)], Body::from(content.data)).into_response()
}
None => StatusCode::NOT_FOUND.into_response(),
}
}