72 lines
2.1 KiB
Rust
72 lines
2.1 KiB
Rust
use axum::{
|
|
Router,
|
|
body::Bytes,
|
|
extract::Path,
|
|
http::{StatusCode, header},
|
|
response::IntoResponse,
|
|
routing::{MethodRouter, get},
|
|
};
|
|
use include_dir::{Dir, include_dir};
|
|
use mime_guess::from_path;
|
|
|
|
static DIST_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/../frontend/build/client");
|
|
const INDEX_HTML_PATH: &str = "index.html";
|
|
const INDEX_FILE_NOT_FOUND_HTML: &str = r#"
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>404 Not Found</title>
|
|
</head>
|
|
<body>
|
|
<h1>404 Not Found</h1>
|
|
<p>The requested resource was not found on this server. Possibly the frontend build is missing or corrupted.</p>
|
|
</body>
|
|
</html>
|
|
"#;
|
|
|
|
pub fn get_view_router() -> Router {
|
|
Router::new()
|
|
// Serve the root index.html
|
|
.route("/", get(root_view_handler))
|
|
.route(
|
|
"/{*wildcard}",
|
|
MethodRouter::new()
|
|
.get(|Path(path): Path<String>| async move { view_handler(Some(path)).await }),
|
|
)
|
|
}
|
|
|
|
async fn root_view_handler() -> impl IntoResponse {
|
|
view_handler(None).await
|
|
}
|
|
|
|
async fn view_handler(path: Option<String>) -> impl IntoResponse {
|
|
// If path is empty, serve index.html
|
|
let incoming_path = if let Some(p) = path {
|
|
p.trim_start_matches('/').to_string()
|
|
} else {
|
|
INDEX_HTML_PATH.to_string()
|
|
};
|
|
|
|
let path = match DIST_DIR.get_file(&incoming_path) {
|
|
Some(_) => incoming_path,
|
|
None => INDEX_HTML_PATH.to_string(),
|
|
};
|
|
|
|
match DIST_DIR.get_file(&path) {
|
|
Some(file) => {
|
|
let mime = from_path(&path).first_or_octet_stream();
|
|
let body: Bytes = Bytes::copy_from_slice(file.contents());
|
|
([(header::CONTENT_TYPE, mime.as_ref())], body).into_response()
|
|
}
|
|
// This should never happen, but just in case...
|
|
None => (
|
|
StatusCode::NOT_FOUND,
|
|
[(header::CONTENT_TYPE, "text/plain")],
|
|
Bytes::from(INDEX_FILE_NOT_FOUND_HTML),
|
|
)
|
|
.into_response(),
|
|
}
|
|
}
|