use std::borrow::Cow;
use axum::body::Body;
use axum::http::{Response, StatusCode, Uri, header};
use bytes::Bytes;
use include_dir::{Dir, include_dir};
use mime_guess::from_path;
use tracing::warn;
static STATIC_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/static");
fn cache_control_for_path(path: &str) -> &'static str {
if path.ends_with("index.html") || path == "index.html" {
"no-cache"
} else {
"public, max-age=31536000, immutable"
}
}
fn serve_embedded_asset(path: &str) -> Response<Body> {
let normalized = path.trim_start_matches('/');
if let Some(file) = STATIC_DIR.get_file(normalized) {
let mime = from_path(normalized).first_or_octet_stream();
let body = Body::from(Bytes::copy_from_slice(file.contents()));
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, mime.as_ref())
.header(header::CACHE_CONTROL, cache_control_for_path(normalized))
.body(body)
.unwrap()
} else {
warn!(path = normalized, "embedded ui asset not found");
Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from(Cow::Borrowed("404 Not Found")))
.unwrap()
}
}
#[allow(clippy::unused_async)]
pub async fn embedded_static_handler(uri: Uri) -> Response<Body> {
let path = uri.path();
let candidate = path.trim_start_matches('/');
if STATIC_DIR.get_file(candidate).is_some() {
return serve_embedded_asset(candidate);
}
let looks_like_asset = candidate.contains('.')
|| candidate.starts_with("assets/")
|| candidate.starts_with("img/");
if looks_like_asset {
return Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from(Cow::Borrowed("404 Not Found")))
.unwrap();
}
serve_embedded_asset("index.html")
}
#[allow(clippy::unused_async)]
pub async fn embedded_static_root_handler() -> Response<Body> {
serve_embedded_asset("index.html")
}