yaiko-core 0.1.1

A modern, production-ready fullstack web framework for Rust
use crate::{App, Request};
use crate::handler::Handler;
use hyper::server::conn::AddrStream;
use hyper::service::{make_service_fn, service_fn};
use hyper::Server as HyperServer;
use std::convert::Infallible;
use std::net::SocketAddr;
use std::sync::Arc;

pub struct Server {
    app: Arc<App>,
    addr: SocketAddr,
}

impl Server {
    pub fn new(app: App, addr: SocketAddr) -> Self {
        Server {
            app: Arc::new(app),
            addr,
        }
    }

    pub async fn run(self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let app = self.app.clone();
        
        let make_svc = make_service_fn(move |conn: &AddrStream| {
            let app = app.clone();
            let remote_addr = conn.remote_addr();
            async move {
                Ok::<_, Infallible>(service_fn(move |req| {
                    let app = app.clone();
                    let remote_addr = remote_addr;
                    async move {
                        let request = Request::from_hyper_with_addr(req, Some(remote_addr)).await?;
                        let response = app.handle(request).await?;
                        Ok::<_, Box<dyn std::error::Error + Send + Sync>>(response.into_hyper())
                    }
                }))
            }
        });

        let server = HyperServer::bind(&self.addr)
            .serve(make_svc)
            .with_graceful_shutdown(async {
                tokio::signal::ctrl_c().await.ok();
                println!("\nReceived shutdown signal, draining connections...");
            });
        
        println!("Server running on http://{}", self.addr);
        
        if let Err(e) = server.await {
            eprintln!("Server error: {}", e);
        }

        println!("Server stopped gracefully.");

        Ok(())
    }
}