use super::lifecycle::{build_internal_router, start_server};
use crate::{
config::HttpConfig,
errors::{HttpError, HttpResult},
middleware::v2::{Middleware, MiddlewarePipelineV2},
routing::ElifRouter,
};
use elif_core::container::IocContainer;
use std::net::SocketAddr;
use std::sync::Arc;
use tracing::info;
pub struct Server {
container: Arc<IocContainer>,
config: HttpConfig,
router: Option<ElifRouter>,
middleware: MiddlewarePipelineV2,
}
impl Server {
pub fn new(container: IocContainer, config: HttpConfig) -> HttpResult<Self> {
Ok(Self {
container: Arc::new(container),
config,
router: None,
middleware: MiddlewarePipelineV2::new(),
})
}
pub fn with_container(container: Arc<IocContainer>, config: HttpConfig) -> HttpResult<Self> {
Ok(Self {
container,
config,
router: None,
middleware: MiddlewarePipelineV2::new(),
})
}
pub fn use_router(&mut self, router: ElifRouter) -> &mut Self {
self.router = Some(router);
self
}
pub fn use_middleware<M>(&mut self, middleware: M) -> &mut Self
where
M: Middleware + 'static,
{
self.middleware.add_mut(middleware);
self
}
pub fn debug_middleware(&mut self, enable: bool) -> &mut Self {
if enable {
let _debug_pipeline = self.middleware.clone().with_debug();
println!("🐛 Middleware debug mode enabled");
println!(" Middleware chain: {:?}", self.middleware.names());
} else {
println!("🔇 Middleware debug mode disabled");
}
self
}
pub fn inspect_middleware(&self) {
let info = self.middleware.debug_info();
println!("🔍 Middleware Pipeline Inspection");
println!(" Total middleware: {}", info.middleware_count);
if info.middleware_count == 0 {
println!(" No middleware registered");
return;
}
println!(" Execution order:");
for (index, name) in info.middleware_names.iter().enumerate() {
println!(" {}. {}", index + 1, name);
}
println!("\n💡 Tip: Use debug_middleware(true) for runtime execution logs");
}
pub fn use_profiler(&mut self) -> &mut Self {
use crate::middleware::v2::ProfilerMiddleware;
self.use_middleware(ProfilerMiddleware::new());
println!("📊 Profiler middleware enabled - request timings will be logged");
self
}
pub async fn listen<A: Into<String>>(self, addr: A) -> HttpResult<()> {
let addr_str = addr.into();
let socket_addr: SocketAddr = addr_str
.parse()
.map_err(|e| HttpError::config(format!("Invalid address '{}': {}", addr_str, e)))?;
self.listen_on(socket_addr).await
}
pub async fn listen_on(self, addr: SocketAddr) -> HttpResult<()> {
info!("🚀 Starting Elif server on {}", addr);
info!(
"📋 Health check endpoint: {}",
self.config.health_check_path
);
let axum_router = build_internal_router(
self.container.clone(),
self.config.clone(),
self.router,
self.middleware,
)
.await?;
start_server(addr, axum_router).await?;
info!("🛑 Server shut down gracefully");
Ok(())
}
pub fn container(&self) -> &Arc<IocContainer> {
&self.container
}
pub fn config(&self) -> &HttpConfig {
&self.config
}
pub fn router(&self) -> Option<&ElifRouter> {
self.router.as_ref()
}
pub fn middleware(&self) -> &MiddlewarePipelineV2 {
&self.middleware
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::testing::create_test_container;
#[test]
fn test_server_creation() {
let container = create_test_container();
let config = HttpConfig::default();
let server = Server::with_container(container, config);
assert!(server.is_ok());
}
#[test]
fn test_server_with_arc_container() {
let container = create_test_container();
let config = HttpConfig::default();
let server = Server::with_container(container, config);
assert!(server.is_ok());
}
#[test]
fn test_server_configuration() {
let container = create_test_container();
let config = HttpConfig::default();
let server = Server::with_container(container, config).unwrap();
assert_eq!(server.config().health_check_path, "/health");
}
#[test]
fn test_middleware_debugging_tools() {
let container = create_test_container();
let config = HttpConfig::default();
let mut server = Server::with_container(container, config).unwrap();
server
.use_middleware(crate::middleware::v2::LoggingMiddleware)
.use_middleware(crate::middleware::v2::factories::cors())
.use_profiler();
server.inspect_middleware();
server.debug_middleware(true);
server.debug_middleware(false);
assert_eq!(server.middleware().len(), 3); }
}