2026-06-17 20:49:17 +08:00
|
|
|
|
//! InternetProject 后端入口。
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! 启动一个后台采样任务持续刷新系统指标,并对外提供 HTTP 接口:
|
|
|
|
|
|
//! - `GET /api/web/stats` 给 React 前端(挂 CORS)
|
|
|
|
|
|
//! - `GET /api/client/health` 给未来 .NET 客户端(不挂 CORS)
|
|
|
|
|
|
|
2026-06-18 00:00:38 +08:00
|
|
|
|
mod auth;
|
2026-06-24 22:19:29 +08:00
|
|
|
|
mod folders;
|
2026-06-17 20:49:17 +08:00
|
|
|
|
mod monitor;
|
2026-06-24 21:03:04 +08:00
|
|
|
|
mod photos;
|
2026-06-17 20:49:17 +08:00
|
|
|
|
mod routes;
|
|
|
|
|
|
mod state;
|
2026-06-18 20:13:18 +08:00
|
|
|
|
mod weather;
|
|
|
|
|
|
|
|
|
|
|
|
use std::net::SocketAddr;
|
2026-06-17 20:49:17 +08:00
|
|
|
|
|
|
|
|
|
|
use state::AppState;
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
|
|
async fn main() {
|
|
|
|
|
|
let state = AppState::new();
|
|
|
|
|
|
|
|
|
|
|
|
// 后台每秒采样系统指标,写入共享快照。
|
|
|
|
|
|
tokio::spawn(monitor::run_sampler(state.clone()));
|
|
|
|
|
|
|
|
|
|
|
|
let app = routes::build_router(state);
|
|
|
|
|
|
|
2026-06-18 17:08:03 +08:00
|
|
|
|
let port = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string());
|
|
|
|
|
|
let addr = format!("0.0.0.0:{port}");
|
|
|
|
|
|
let listener = tokio::net::TcpListener::bind(&addr)
|
2026-06-17 20:49:17 +08:00
|
|
|
|
.await
|
2026-06-18 17:08:03 +08:00
|
|
|
|
.unwrap_or_else(|_| panic!("无法绑定 {addr}"));
|
2026-06-17 20:49:17 +08:00
|
|
|
|
println!("backend listening on http://{addr}");
|
|
|
|
|
|
|
2026-06-18 20:13:18 +08:00
|
|
|
|
// 用 connect-info 让 handler 能拿到对端 socket 地址(天气接口要按访问者 IP 定位/限流)。
|
|
|
|
|
|
axum::serve(listener, app.into_make_service_with_connect_info::<SocketAddr>())
|
|
|
|
|
|
.await
|
|
|
|
|
|
.expect("server error");
|
2026-06-17 20:49:17 +08:00
|
|
|
|
}
|