Skip to content

Commit 549c046

Browse files
committed
feat(webapi): 添加 dotenvy 依赖并优化静态资源处理
- 引入 dotenvy 库用于环境变量管理 - 重构静态资源查找逻辑,使用 Path 替代 PathBuf 提升性能 - 移除冗余的静态文件服务处理器注释 - 完善日志初始化功能,支持终端和文件双输出 - 增强 CORS 配置,支持从环境变量读取设置 - 删除重复的源文件 originfilewebapi.rs
1 parent b80a580 commit 549c046

4 files changed

Lines changed: 106 additions & 398 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

file_classification_webapi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ actix-files = "0.6.8"
2424
rust-embed = "8.8.0"
2525
mime_guess = "2.0.5"
2626
fern = "0.6"
27+
dotenvy = "0.15"
2728

2829
[[bin]]
2930
name = "file_classification_webapi"

file_classification_webapi/src/bin/file_classification_webapi.rs

Lines changed: 104 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,23 @@ mod handlers;
33
mod utils;
44

55
use actix_cors::Cors;
6-
use actix_files::NamedFile;
6+
use fern;
77
use log;
8+
use rust_embed::RustEmbed;
89
use std::env;
10+
use std::path::Path;
911
use std::path::PathBuf;
10-
// 引入嵌入资源模块
11-
use crate::utils::embedded::{Assets};
12+
use crate::utils::database::establish_connection_pool;
13+
14+
// 嵌入静态资源
15+
#[derive(RustEmbed)]
16+
#[folder = "static/"]
17+
struct Assets;
1218

1319
// 引入数据库连接相关类型
1420
use file_classification_core::utils::database::{establish_connection, run_pending_migrations};
15-
use crate::utils::database::establish_connection_pool;
16-
// 引入环境变量加载工具
1721
use file_classification_common::env_loader::load_env_file;
1822

19-
// 创建 CORS 中间件
20-
fn create_cors() -> Cors {
21-
Cors::default()
22-
.allow_any_origin()
23-
.allow_any_method()
24-
.allow_any_header()
25-
.supports_credentials()
26-
}
27-
2823
// 处理嵌入的文件资源
2924
fn handle_embedded_file(path: &str) -> HttpResponse {
3025
match Assets::get(path) {
@@ -35,7 +30,7 @@ fn handle_embedded_file(path: &str) -> HttpResponse {
3530
.body(content.data)
3631
}
3732
None => {
38-
// 避免递归调用,直接获取 index.html
33+
// Avoid recursive call by directly getting index.html
3934
if path == "index.html" {
4035
return HttpResponse::NotFound().body("404 Not Found");
4136
}
@@ -50,7 +45,7 @@ fn find_static_directory() -> std::io::Result<PathBuf> {
5045
if let Ok(exe_path) = std::env::current_exe() {
5146
if let Some(exe_dir) = exe_path.parent() {
5247
let static_dir = exe_dir.join("static");
53-
if PathBuf::from(&static_dir).exists() {
48+
if Path::new(&static_dir).exists() {
5449
log::info!("找到静态资源目录: {:?}", static_dir);
5550
return Ok(static_dir);
5651
}
@@ -60,14 +55,14 @@ fn find_static_directory() -> std::io::Result<PathBuf> {
6055
// 然后尝试从当前工作目录查找
6156
if let Ok(current_dir) = std::env::current_dir() {
6257
let static_dir = current_dir.join("static");
63-
if PathBuf::from(&static_dir).exists() {
58+
if Path::new(&static_dir).exists() {
6459
log::info!("找到静态资源目录: {:?}", static_dir);
6560
return Ok(static_dir);
6661
}
6762

6863
// 尝试从当前工作目录的子目录 file_classification_webapi 中查找
6964
let static_dir = current_dir.join("file_classification_webapi").join("static");
70-
if PathBuf::from(&static_dir).exists() {
65+
if Path::new(&static_dir).exists() {
7166
log::info!("找到静态资源目录: {:?}", static_dir);
7267
return Ok(static_dir);
7368
}
@@ -84,7 +79,6 @@ fn find_static_directory() -> std::io::Result<PathBuf> {
8479
}
8580
}
8681

87-
// 静态文件服务处理器
8882
async fn index_handler() -> HttpResponse {
8983
// 首先尝试从物理目录提供文件
9084
match find_static_directory() {
@@ -108,7 +102,6 @@ async fn index_handler() -> HttpResponse {
108102
handle_embedded_file("index.html")
109103
}
110104

111-
// 静态资源处理器
112105
async fn static_handler(path: web::Path<String>) -> HttpResponse {
113106
let path = path.into_inner();
114107

@@ -154,10 +147,99 @@ async fn static_handler(path: web::Path<String>) -> HttpResponse {
154147
handle_embedded_file(&path)
155148
}
156149

150+
/// 初始化日志系统,同时输出到终端和文件
151+
fn setup_logger() -> Result<(), fern::InitError> {
152+
// 加载环境变量文件
153+
if let Err(e) = load_env_file() {
154+
log::error!("加载环境变量文件失败: {}", e);
155+
}
156+
157+
// 创建 logs 目录(如果不存在)
158+
std::fs::create_dir_all("logs")?;
159+
160+
// 获取当前日期时间作为日志文件名
161+
let local_time = chrono::Local::now();
162+
let date_str = local_time.format("%Y-%m-%d").to_string();
163+
let log_file_path = format!("logs/{}.log", date_str);
164+
165+
// 获取终端日志等级
166+
let console_log_level = env::var("RUST_LOG")
167+
.ok()
168+
.and_then(|s| s.parse().ok())
169+
.unwrap_or(log::LevelFilter::Info);
170+
171+
// 文件日志等级默认为 Debug
172+
let file_log_level = env::var("RUST_LOG_FILE")
173+
.ok()
174+
.and_then(|s| s.parse().ok())
175+
.unwrap_or(log::LevelFilter::Debug);
176+
177+
// 创建日志分发器
178+
let dispatch = fern::Dispatch::new()
179+
.format(|out, message, record| {
180+
out.finish(format_args!(
181+
"[{}][{}][{}] {}",
182+
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
183+
record.level(),
184+
record.target(),
185+
message
186+
))
187+
});
188+
189+
// 添加控制台输出
190+
let dispatch = dispatch.chain(
191+
fern::Dispatch::new()
192+
.level(console_log_level)
193+
.chain(std::io::stdout())
194+
);
195+
196+
// 添加文件输出
197+
let dispatch = dispatch.chain(
198+
fern::Dispatch::new()
199+
.level(file_log_level)
200+
.chain(fern::log_file(log_file_path)?)
201+
);
202+
203+
dispatch.apply()?;
204+
205+
Ok(())
206+
}
207+
208+
/// 创建 CORS 配置
209+
fn create_cors() -> Cors {
210+
// 从环境变量获取 CORS 配置
211+
let cors_enabled = env::var("CORS_ENABLED")
212+
.ok()
213+
.and_then(|s| s.parse::<bool>().ok())
214+
.unwrap_or(true); // 默认启用 CORS
215+
216+
let cors_origin = env::var("CORS_ORIGIN")
217+
.ok()
218+
.unwrap_or_else(|| "http://localhost:8082".to_string());
219+
220+
if cors_enabled {
221+
log::info!("CORS 已启用,允许来源: {}", cors_origin);
222+
Cors::default()
223+
.allowed_origin(&cors_origin)
224+
.allowed_origin("http://127.0.0.1:8082")
225+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
226+
.allowed_headers(vec![
227+
actix_web::http::header::AUTHORIZATION,
228+
actix_web::http::header::ACCEPT,
229+
actix_web::http::header::CONTENT_TYPE,
230+
])
231+
.supports_credentials()
232+
.max_age(3600)
233+
} else {
234+
log::info!("CORS 已禁用");
235+
Cors::default()
236+
}
237+
}
238+
157239
#[actix_web::main]
158240
async fn main() -> std::io::Result<()> {
159-
// 初始化日志系统
160-
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
241+
// 初始化日志记录器
242+
setup_logger().expect("日志系统初始化失败");
161243

162244
// 输出日志等级信息
163245
let console_log_level = env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string());

0 commit comments

Comments
 (0)