use axum::{
body::Body,
http::{header, StatusCode, Uri},
response::{IntoResponse, Response},
};
use rust_embed::Embed;
#[derive(Embed)]
#[folder = "$CARGO_MANIFEST_DIR/../../web/dist"]
struct WebAssets;
const PLACEHOLDER_HTML: &str = include_str!("../placeholder.html");
pub(super) async fn static_handler(uri: Uri) -> Response {
let path = uri.path().trim_start_matches('/').to_string();
if !path.is_empty() {
if let Some(file) = WebAssets::get(&path) {
return file_response(file, &path);
}
}
if !path.is_empty() && !path.contains('.') {
let html_path = format!("{}.html", path);
if let Some(file) = WebAssets::get(&html_path) {
return file_response(file, &html_path);
}
}
if let Some(file) = WebAssets::get("index.html") {
return file_response(file, "index.html");
}
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "text/html; charset=utf-8")
.body(Body::from(PLACEHOLDER_HTML))
.unwrap_or_else(|_| StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
fn file_response(file: rust_embed::EmbeddedFile, path: &str) -> Response {
let mime = mime_guess::from_path(path).first_or_octet_stream();
let cache_control = if path.starts_with("_app/immutable/") {
"public, max-age=31536000, immutable"
} else {
"public, max-age=300"
};
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, mime.as_ref())
.header(header::CACHE_CONTROL, cache_control)
.body(Body::from(file.data.into_owned()))
.unwrap_or_else(|_| StatusCode::INTERNAL_SERVER_ERROR.into_response())
}