use axum::{
body::Body,
http::{StatusCode, Uri, header},
response::{IntoResponse, Response},
};
use rust_embed::Embed;
use std::sync::OnceLock;
#[derive(Embed)]
#[folder = "ui/dist/"]
struct Assets;
static STATIC_TOKEN: OnceLock<String> = OnceLock::new();
static STATIC_BASE: OnceLock<String> = OnceLock::new();
const TOKEN_PLACEHOLDER: &str = "__PF_TOKEN_PLACEHOLDER__";
const BASE_PLACEHOLDER: &str = "__PF_BASE_PLACEHOLDER__";
pub fn set_static_token(token: String) {
let _ = STATIC_TOKEN.set(token);
}
pub fn set_static_base(base: String) {
let _ = STATIC_BASE.set(base);
}
fn inject_into_index_html(data: &[u8]) -> Body {
let html = String::from_utf8_lossy(data);
let replaced = STATIC_TOKEN
.get()
.filter(|t| !t.is_empty())
.map(|token| html.replace(TOKEN_PLACEHOLDER, token))
.unwrap_or_else(|| html.into_owned());
let replaced = STATIC_BASE
.get()
.map(|base| replaced.replace(BASE_PLACEHOLDER, base))
.unwrap_or(replaced);
Body::from(replaced.into_bytes())
}
pub async fn static_handler(uri: Uri) -> impl IntoResponse {
let mut path = uri.path().trim_start_matches('/');
if path.is_empty() {
path = "index.html";
}
match Assets::get(path) {
Some(content) => {
let mime = mime_guess::from_path(path).first_or_octet_stream();
let data = content.data.to_vec();
let body = if path == "index.html" {
inject_into_index_html(&data)
} else {
Body::from(data)
};
let is_index = path == "index.html";
let mut builder = Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, mime.as_ref());
if is_index {
builder =
builder.header(header::CACHE_CONTROL, "no-store, no-cache, must-revalidate");
}
builder.body(body).unwrap()
}
None => {
match Assets::get("index.html") {
Some(content) => {
let data = content.data.to_vec();
let body = inject_into_index_html(&data);
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "text/html")
.header(header::CACHE_CONTROL, "no-store, no-cache, must-revalidate")
.body(body)
.unwrap()
}
None => Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from("404 Not Found"))
.unwrap(),
}
}
}
}