diff --git a/src/interface.rs b/src/interface.rs index 302a2a1..8e7c97a 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,11 +1,46 @@ use axum::{ routing::{get, post}, - response::Html, + response::{Html, IntoResponse}, Router, extract::Form, + http::header, }; use serde::Deserialize; use crate::logger::get_logger; +use std::sync::OnceLock; + +/// Cache del hostname del sistema (se calcula una sola vez) +static HOSTNAME: OnceLock = OnceLock::new(); + +/// Obtiene el hostname del sistema (cached) +fn get_hostname() -> &'static str { + HOSTNAME.get_or_init(|| { + use std::process::Command; + + // Intentar con comando hostname + if let Ok(output) = Command::new("hostname").output() { + if output.status.success() { + if let Ok(hostname) = String::from_utf8(output.stdout) { + let hostname = hostname.trim(); + if !hostname.is_empty() { + return hostname.to_string(); + } + } + } + } + + // Fallback: leer /etc/hostname + if let Ok(hostname) = std::fs::read_to_string("/etc/hostname") { + let hostname = hostname.trim(); + if !hostname.is_empty() { + return hostname.to_string(); + } + } + + // Último fallback + "siax-agent".to_string() + }) +} #[derive(Deserialize)] struct ProcessForm { @@ -22,12 +57,19 @@ pub fn create_web_router() -> Router { .route("/add-process", post(add_process_handler)) .route("/logs", get(logs_handler)) .route("/clear-logs", post(clear_logs_handler)) + .route("/health", get(health_handler)) .route("/api-docs", get(api_docs_handler)) + .route("/install.sh", get(install_script_handler)) + // Archivos estáticos embebidos + .route("/static/icon/logo_telco128.png", get(logo_telco_handler)) + .route("/static/icon/logo.png", get(logo_handler)) + .route("/static/icon/favicon.svg", get(favicon_svg_handler)) + .route("/static/icon/favicon.ico", get(favicon_ico_handler)) } async fn index_handler() -> Html { let template = include_str!("../web/index.html"); - let html = template.replace("{{SERVER_NAME}}", "siax-intel"); + let html = template.replace("{{SERVER_NAME}}", get_hostname()); Html(html) } @@ -84,3 +126,40 @@ async fn api_docs_handler() -> Html { let template = include_str!("../web/api-docs.html"); Html(template.to_string()) } + +async fn health_handler() -> Html { + let template = include_str!("../web/health.html"); + Html(template.to_string()) +} + +async fn install_script_handler() -> ([(String, String); 2], String) { + let script = include_str!("../install-remote.sh"); + ( + [ + ("Content-Type".to_string(), "text/plain; charset=utf-8".to_string()), + ("Content-Disposition".to_string(), "inline; filename=\"install.sh\"".to_string()), + ], + script.to_string(), + ) +} + +// Handlers para archivos estáticos embebidos +async fn logo_telco_handler() -> impl IntoResponse { + let image = include_bytes!("../web/static/icon/logo_telco128.png"); + ([(header::CONTENT_TYPE, "image/png")], image.as_ref()) +} + +async fn logo_handler() -> impl IntoResponse { + let image = include_bytes!("../web/static/icon/logo.png"); + ([(header::CONTENT_TYPE, "image/png")], image.as_ref()) +} + +async fn favicon_svg_handler() -> impl IntoResponse { + let image = include_bytes!("../web/static/icon/favicon.svg"); + ([(header::CONTENT_TYPE, "image/svg+xml")], image.as_ref()) +} + +async fn favicon_ico_handler() -> impl IntoResponse { + let image = include_bytes!("../web/static/icon/favicon.ico"); + ([(header::CONTENT_TYPE, "image/x-icon")], image.as_ref()) +} diff --git a/src/main.rs b/src/main.rs index 2e98abc..52d59c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,7 +29,10 @@ async fn main() { let apps = config_manager.get_apps(); println!("📋 Apps a monitorear: {:?}", apps); - let server_name = "siax-intel".to_string(); + // Detectar hostname del sistema automáticamente + let server_name = get_hostname(); + logger.info("Sistema", &format!("Servidor detectado: {}", server_name)); + let api_key = "ak_VVeNzGxK2mCq8s7YpFtHjL3b9dR4TuZ6".to_string(); let cloud_url = "https://api.siax-system.net/api/apps_servcs/apps".to_string(); @@ -54,6 +57,7 @@ async fn main() { let web_api_handle = tokio::spawn(async move { // Router para la API REST let api_router = Router::new() + .route("/api/health", get(api::health_handler)) .route("/api/apps", get(api::list_apps_handler).post(api::register_app_handler)) .route("/api/apps/:name", delete(api::unregister_app_handler)) .route("/api/apps/:name/status", get(api::get_app_status_handler)) @@ -93,3 +97,31 @@ async fn main() { // Esperamos a ambos let _ = tokio::join!(monitor_handle, web_api_handle); } + +/// Obtiene el hostname del sistema +fn get_hostname() -> String { + use std::process::Command; + + // Intentar obtener hostname con el comando 'hostname' + if let Ok(output) = Command::new("hostname").output() { + if output.status.success() { + if let Ok(hostname) = String::from_utf8(output.stdout) { + let hostname = hostname.trim(); + if !hostname.is_empty() { + return hostname.to_string(); + } + } + } + } + + // Fallback: leer /etc/hostname + if let Ok(hostname) = std::fs::read_to_string("/etc/hostname") { + let hostname = hostname.trim(); + if !hostname.is_empty() { + return hostname.to_string(); + } + } + + // Último fallback: nombre genérico + "siax-agent".to_string() +}