PicoBot/src/gateway/static_files.rs
ooodc 9b6cae0803 feat: 前端静态文件嵌入二进制
- 添加 rust-embed 依赖
- 创建 static_files.rs 模块,编译时嵌入 static/ 目录
- 修改 gateway 路由,默认使用嵌入文件
- 支持 STATIC_DIR 环境变量切换到磁盘文件(开发模式)
- 更新 README 说明 Web UI 和构建流程
2026-05-30 17:43:17 +08:00

57 lines
1.8 KiB
Rust

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<Body> {
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()
}
}
}