elif_http/server/
server.rs

1//! # Elif HTTP Server
2//! 
3//! A NestJS-like HTTP server that provides a clean, intuitive API while using Axum under the hood.
4//! Users interact only with framework types - Axum is completely abstracted away.
5
6use crate::{
7    config::HttpConfig, 
8    errors::{HttpError, HttpResult},
9    routing::ElifRouter, 
10    middleware::v2::{MiddlewarePipelineV2, Middleware},
11};
12use super::lifecycle::{build_internal_router, start_server};
13use elif_core::container::IocContainer;
14use std::net::SocketAddr;
15use std::sync::Arc;
16use tracing::info;
17
18/// The main HTTP server - NestJS-like experience
19/// 
20/// # Example
21/// 
22/// ```rust,no_run
23/// use elif_http::{Server, HttpConfig};
24/// use elif_core::container::{IocContainer, ServiceBinder};
25/// use std::sync::Arc;
26/// 
27/// #[tokio::main]
28/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
29///     let mut container = IocContainer::new();
30///     container.build().unwrap();
31///     let server = Server::new(container, HttpConfig::default())?;
32///     server.listen("0.0.0.0:3000").await?;
33///     Ok(())
34/// }
35/// ```
36pub struct Server {
37    container: Arc<IocContainer>,
38    config: HttpConfig,
39    router: Option<ElifRouter>,
40    middleware: MiddlewarePipelineV2,
41}
42
43impl Server {
44    /// Create a new server instance
45    pub fn new(container: IocContainer, config: HttpConfig) -> HttpResult<Self> {
46        Ok(Self {
47            container: Arc::new(container),
48            config,
49            router: None,
50            middleware: MiddlewarePipelineV2::new(),
51        })
52    }
53
54    /// Create a new server with existing Arc<IocContainer>
55    pub fn with_container(container: Arc<IocContainer>, config: HttpConfig) -> HttpResult<Self> {
56        Ok(Self {
57            container,
58            config,
59            router: None,
60            middleware: MiddlewarePipelineV2::new(),
61        })
62    }
63
64    /// Set custom routes using framework router
65    /// 
66    /// # Example
67    /// 
68    /// ```rust,no_run
69    /// use elif_http::{Server, ElifRouter, HttpConfig, ElifRequest, HttpResult};
70    /// use elif_core::container::{IocContainer, ServiceBinder};
71    /// use std::sync::Arc;
72    /// 
73    /// # async fn get_users(_req: ElifRequest) -> HttpResult<&'static str> { Ok("users") }
74    /// # async fn create_user(_req: ElifRequest) -> HttpResult<&'static str> { Ok("created") }
75    /// 
76    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
77    /// let mut container = IocContainer::new();
78    /// container.build().unwrap();
79    /// let mut server = Server::new(container, HttpConfig::default())?;
80    /// 
81    /// let router = ElifRouter::new()
82    ///     .get("/users", get_users)
83    ///     .post("/users", create_user);
84    /// 
85    /// server.use_router(router);
86    /// # Ok(())
87    /// # }
88    /// ```
89    pub fn use_router(&mut self, router: ElifRouter) -> &mut Self {
90        self.router = Some(router);
91        self
92    }
93
94    /// Add middleware to the server
95    /// 
96    /// # Example
97    /// 
98    /// ```rust,no_run
99    /// use elif_http::{Server, HttpConfig};
100    /// use elif_core::container::{IocContainer, ServiceBinder};
101    /// use std::sync::Arc;
102    /// 
103    /// # #[derive(Debug)]
104    /// # struct LoggingMiddleware;
105    /// # impl LoggingMiddleware { 
106    /// #     fn default() -> Self { LoggingMiddleware } 
107    /// # }
108    /// # impl elif_http::Middleware for LoggingMiddleware {
109    /// #     fn handle(&self, request: elif_http::ElifRequest, next: elif_http::Next) -> std::pin::Pin<Box<dyn std::future::Future<Output = elif_http::ElifResponse> + Send + 'static>> {
110    /// #         next.call(request)
111    /// #     }
112    /// # }
113    /// 
114    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
115    /// let mut container = IocContainer::new();
116    /// container.build().unwrap();
117    /// let mut server = Server::new(container, HttpConfig::default())?;
118    /// server.use_middleware(LoggingMiddleware::default());
119    /// # Ok(())
120    /// # }
121    /// ```
122    pub fn use_middleware<M>(&mut self, middleware: M) -> &mut Self 
123    where 
124        M: Middleware + 'static,
125    {
126        self.middleware.add_mut(middleware);
127        self
128    }
129
130    /// Enable debug mode for detailed middleware execution logs
131    /// 
132    /// # Example
133    /// 
134    /// ```rust,no_run
135    /// use elif_http::{Server, HttpConfig};
136    /// use elif_core::container::{IocContainer, ServiceBinder};
137    /// 
138    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
139    /// let mut container = IocContainer::new();
140    /// container.build().unwrap();
141    /// let mut server = Server::new(container, HttpConfig::default())?;
142    /// server.debug_middleware(true);
143    /// # Ok(())
144    /// # }
145    /// ```
146    pub fn debug_middleware(&mut self, enable: bool) -> &mut Self {
147        if enable {
148            // Convert current pipeline to debug pipeline (for future use)
149            let _debug_pipeline = self.middleware.clone().with_debug();
150            println!("šŸ› Middleware debug mode enabled");
151            println!("   Middleware chain: {:?}", self.middleware.names());
152        } else {
153            println!("šŸ”‡ Middleware debug mode disabled");
154        }
155        self
156    }
157
158    /// Inspect all registered middleware and show execution order
159    /// 
160    /// # Example
161    /// 
162    /// ```rust,no_run
163    /// use elif_http::{Server, HttpConfig};
164    /// use elif_core::container::{IocContainer, ServiceBinder};
165    /// 
166    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
167    /// let mut container = IocContainer::new();
168    /// container.build().unwrap();
169    /// let server = Server::new(container, HttpConfig::default())?;
170    /// server.inspect_middleware();
171    /// # Ok(())
172    /// # }
173    /// ```
174    pub fn inspect_middleware(&self) {        
175        let info = self.middleware.debug_info();
176        
177        println!("šŸ” Middleware Pipeline Inspection");
178        println!("   Total middleware: {}", info.middleware_count);
179        
180        if info.middleware_count == 0 {
181            println!("   No middleware registered");
182            return;
183        }
184        
185        println!("   Execution order:");
186        for (index, name) in info.middleware_names.iter().enumerate() {
187            println!("     {}. {}", index + 1, name);
188        }
189        
190        println!("\nšŸ’” Tip: Use debug_middleware(true) for runtime execution logs");
191    }
192    
193    /// Add profiler middleware to log timing for each request
194    /// 
195    /// # Example
196    /// 
197    /// ```rust,no_run
198    /// use elif_http::{Server, HttpConfig};
199    /// use elif_core::container::{IocContainer, ServiceBinder};
200    /// 
201    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
202    /// let mut container = IocContainer::new();
203    /// container.build().unwrap();
204    /// let mut server = Server::new(container, HttpConfig::default())?;
205    /// server.use_profiler();
206    /// # Ok(())
207    /// # }
208    /// ```
209    pub fn use_profiler(&mut self) -> &mut Self {
210        use crate::middleware::v2::ProfilerMiddleware;
211        self.use_middleware(ProfilerMiddleware::new());
212        println!("šŸ“Š Profiler middleware enabled - request timings will be logged");
213        self
214    }
215
216    /// Start the server on the specified address
217    /// 
218    /// # Example
219    /// 
220    /// ```rust,no_run
221    /// # use elif_http::{Server, HttpConfig};
222    /// # use elif_core::container::IocContainer;
223    /// # use std::sync::Arc;
224    /// # 
225    /// # #[tokio::main]
226    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
227    /// #     let mut container = IocContainer::new();
228    /// #     container.build().unwrap();
229    /// #     let server = Server::new(container, HttpConfig::default())?;
230    /// server.listen("0.0.0.0:3000").await?;
231    /// #     Ok(())
232    /// # }
233    /// ```
234    pub async fn listen<A: Into<String>>(self, addr: A) -> HttpResult<()> {
235        let addr_str = addr.into();
236        let socket_addr: SocketAddr = addr_str.parse()
237            .map_err(|e| HttpError::config(format!("Invalid address '{}': {}", addr_str, e)))?;
238
239        self.listen_on(socket_addr).await
240    }
241
242    /// Start the server on the specified SocketAddr
243    pub async fn listen_on(self, addr: SocketAddr) -> HttpResult<()> {
244        info!("šŸš€ Starting Elif server on {}", addr);
245        info!("šŸ“‹ Health check endpoint: {}", self.config.health_check_path);
246        
247        // Build the internal router
248        let axum_router = build_internal_router(self.container.clone(), self.config.clone(), self.router, self.middleware).await?;
249        
250        // Start the server
251        start_server(addr, axum_router).await?;
252
253        info!("šŸ›‘ Server shut down gracefully");
254        Ok(())
255    }
256
257    // Getter methods for testing and inspection
258    pub fn container(&self) -> &Arc<IocContainer> {
259        &self.container
260    }
261
262    pub fn config(&self) -> &HttpConfig {
263        &self.config
264    }
265
266    pub fn router(&self) -> Option<&ElifRouter> {
267        self.router.as_ref()
268    }
269
270    pub fn middleware(&self) -> &MiddlewarePipelineV2 {
271        &self.middleware
272    }
273}
274
275#[cfg(test)]
276mod tests {
277    use super::*;
278    use crate::testing::create_test_container;
279
280    #[test]
281    fn test_server_creation() {
282        let container = create_test_container();
283        let config = HttpConfig::default();
284        
285        let server = Server::with_container(container, config);
286        assert!(server.is_ok());
287    }
288
289    #[test]
290    fn test_server_with_arc_container() {
291        let container = create_test_container();
292        let config = HttpConfig::default();
293        
294        let server = Server::with_container(container, config);
295        assert!(server.is_ok());
296    }
297
298    #[test]
299    fn test_server_configuration() {
300        let container = create_test_container();
301        let config = HttpConfig::default();
302        let server = Server::with_container(container, config).unwrap();
303        
304        assert_eq!(server.config().health_check_path, "/health");
305    }
306
307    #[test]
308    fn test_middleware_debugging_tools() {
309        let container = create_test_container();
310        let config = HttpConfig::default();
311        let mut server = Server::with_container(container, config).unwrap();
312        
313        // Add some middleware
314        server
315            .use_middleware(crate::middleware::v2::LoggingMiddleware)
316            .use_middleware(crate::middleware::v2::factories::cors())
317            .use_profiler();
318        
319        // Test inspect_middleware - should not panic
320        server.inspect_middleware();
321        
322        // Test debug_middleware - should not panic
323        server.debug_middleware(true);
324        server.debug_middleware(false);
325        
326        // Verify middleware count
327        assert_eq!(server.middleware().len(), 3); // LoggingMiddleware + CorsMiddleware + ProfilerMiddleware
328    }
329}