elif_http/
minimal_server.rs

1//! Minimal working HTTP server
2//! 
3//! This is the simplest possible implementation to test the basic concepts.
4
5use crate::{HttpConfig, HttpError, HttpResult};
6use elif_core::Container;
7use axum::{
8    Router,
9    routing::get,
10    response::Json,
11};
12use serde_json::{json, Value};
13use std::net::SocketAddr;
14use std::sync::Arc;
15use tokio::signal;
16use tracing::info;
17
18/// Minimal HTTP server that works
19pub struct MinimalHttpServer {
20    addr: SocketAddr,
21}
22
23impl MinimalHttpServer {
24    /// Create new minimal HTTP server
25    pub fn new(container: Arc<Container>, config: HttpConfig) -> HttpResult<Self> {
26        let app_config = container.config();
27        let addr = format!("{}:{}", app_config.server.host, app_config.server.port)
28            .parse::<SocketAddr>()
29            .map_err(|e| HttpError::config(format!("Invalid server address: {}", e)))?;
30
31        Ok(Self { addr })
32    }
33
34    /// Start the server
35    pub async fn run(self) -> HttpResult<()> {
36        info!("Starting minimal HTTP server on {}", self.addr);
37
38        // Create a basic router without state
39        let router = Router::new()
40            .route("/health", get(minimal_health_check));
41
42        let listener = tokio::net::TcpListener::bind(self.addr)
43            .await
44            .map_err(|e| HttpError::startup(format!("Failed to bind to {}: {}", self.addr, e)))?;
45
46        info!("Minimal HTTP server listening on {}", self.addr);
47
48        axum::serve(listener, router)
49            .with_graceful_shutdown(minimal_shutdown_signal())
50            .await
51            .map_err(|e| HttpError::startup(format!("Server failed: {}", e)))?;
52
53        info!("Minimal HTTP server stopped gracefully");
54        Ok(())
55    }
56}
57
58/// Basic health check without DI container access
59pub async fn minimal_health_check() -> Json<Value> {
60    Json(json!({
61        "status": "healthy",
62        "timestamp": chrono::Utc::now().to_rfc3339(),
63        "version": "0.1.0",
64        "server": "minimal"
65    }))
66}
67
68/// Minimal graceful shutdown signal handler
69async fn minimal_shutdown_signal() {
70    let ctrl_c = async {
71        signal::ctrl_c()
72            .await
73            .expect("failed to install Ctrl+C handler");
74    };
75
76    #[cfg(unix)]
77    let terminate = async {
78        signal::unix::signal(signal::unix::SignalKind::terminate())
79            .expect("failed to install signal handler")
80            .recv()
81            .await;
82    };
83
84    #[cfg(not(unix))]
85    let terminate = std::future::pending::<()>();
86
87    tokio::select! {
88        _ = ctrl_c => {
89            info!("Received Ctrl+C, initiating graceful shutdown");
90        },
91        _ = terminate => {
92            info!("Received terminate signal, initiating graceful shutdown");
93        },
94    }
95}