use axum::{ body::Body, http::{header, Response, StatusCode, Uri}, }; use rust_embed::RustEmbed; /// 嵌入的静态文件资源 /// 在编译时将 static 目录下的所有文件打包进二进制文件 #[derive(RustEmbed)] #[folder = "static/"] pub struct StaticAssets; /// 处理静态文件请求 /// 从嵌入的资源中读取文件并返回 HTTP 响应 pub async fn static_handler(uri: Uri) -> Response { let path = uri.path().trim_start_matches('/'); // 处理根路径,返回 index.html let path = if path.is_empty() { "index.html" } else { path }; match StaticAssets::get(path) { Some(content) => { let mime_type = mime_guess::from_path(path) .first_or_octet_stream() .as_ref() .to_string(); Response::builder() .status(StatusCode::OK) .header(header::CONTENT_TYPE, mime_type) .body(Body::from(content.data.into_owned())) .unwrap() } None => { // 对于 SPA 应用,如果请求的是页面路由(不是静态资源),返回 index.html // 静态资源通常包含 . (如 .js, .css, .png) if !path.contains('.') { if let Some(index) = StaticAssets::get("index.html") { return Response::builder() .status(StatusCode::OK) .header(header::CONTENT_TYPE, "text/html") .body(Body::from(index.data.into_owned())) .unwrap(); } } Response::builder() .status(StatusCode::NOT_FOUND) .body(Body::from("404 Not Found")) .unwrap() } } }