Aurora-Print/Core/web_server/mod.rs
2025-10-24 13:01:16 +02:00

102 lines
2.7 KiB
Rust

use std::{
env, fs,
net::SocketAddr,
path::{Path, PathBuf},
};
use axum::{
routing::{get, post},
extract::Json,
Router,
response::Html,
};
use tower_http::services::ServeDir;
use serde::Deserialize;
mod assets;
use assets::{DEFAULT_INDEX_HTML, DEFAULT_APP_JS, DEFAULT_STYLES_CSS};
use crate::{state::SharedState, headless};
const WEB_DIR: &str = "web";
fn exe_dir() -> PathBuf {
env::current_exe()
.ok()
.and_then(|p| p.parent().map(|p| p.to_path_buf()))
.unwrap_or_else(|| PathBuf::from("."))
}
fn rebuild_web_assets(dir: &Path) -> std::io::Result<()> {
let web = dir.join(WEB_DIR);
if web.exists() {
fs::remove_dir_all(&web)?;
}
fs::create_dir_all(&web)?;
fs::write(web.join("index.html"), DEFAULT_INDEX_HTML.trim_start())?;
fs::write(web.join("app.js"), DEFAULT_APP_JS.trim_start())?;
fs::write(web.join("styles.css"), DEFAULT_STYLES_CSS.trim_start())?;
Ok(())
}
#[derive(Deserialize)]
struct StartRequest {
ip: String,
}
async fn start_job(Json(req): Json<StartRequest>) -> String {
let ip = req.ip.trim().to_string();
println!("[WebServer] Starte Headless-Test für {}", ip);
// Klon für den Task
let ip_for_task = ip.clone();
tokio::spawn(async move {
if let Err(e) = headless::run_test(&ip_for_task).await {
eprintln!("[Headless Error] {}", e);
}
});
format!("Starte Setup für {}", ip)
}
// Port wird jetzt von außen übergeben
pub async fn start(state: SharedState, port: u16)
-> Result<tokio::task::JoinHandle<()>, Box<dyn std::error::Error>>
{
let dir = exe_dir();
rebuild_web_assets(&dir)?;
let web_root = dir.join(WEB_DIR);
let static_root = web_root.clone();
let index_path = web_root.join("index.html");
let app = Router::new()
.route("/", get({
let index_path = index_path.clone();
move || {
let index_path = index_path.clone();
async move {
let html = fs::read_to_string(&index_path)
.unwrap_or_else(|_| "<h1>index.html fehlt</h1>".to_string());
Html(html)
}
}
}))
.route("/api/start", post(start_job)) // 👈 Neue Route
.nest_service("/static", ServeDir::new(static_root))
.route("/healthz", get(|| async { "ok" }));
{
let mut s = state.lock().unwrap();
s.web_server_active = true;
}
let addr: SocketAddr = format!("0.0.0.0:{}", port).parse()?;
let listener = tokio::net::TcpListener::bind(addr).await?;
let handle = tokio::spawn(async move {
let _ = axum::serve(listener, app).await;
});
Ok(handle)
}