use crate::api::ApiHandler; use crate::config::Config; use anyhow::Result; use hyper_util::rt::TokioIo; use hyper_util::server::conn::auto::Builder as AutoBuilder; use std::net::SocketAddr; use std::sync::Arc; use tokio::net::TcpListener; use hyper::service::service_fn; use tracing::{error, info}; pub struct Server { config: Config, api_handler: Arc, } impl Server { pub async fn new(config: Config) -> Result { let api_handler = Arc::new(ApiHandler::new(config.clone()).await?); Ok(Self { config, api_handler, }) } pub async fn serve(&self, addr: SocketAddr) -> Result<()> { let listener = TcpListener::bind(addr).await?; loop { let (stream, peer_addr) = match listener.accept().await { Ok(conn) => conn, Err(e) => { error!("Failed to accept connection: {}", e); continue; } }; let io = TokioIo::new(stream); let handler = self.api_handler.clone(); tokio::spawn(async move { let service = service_fn(move |req| { let handler = handler.clone(); async move { handler.handle_request(req).await .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("{}", e))) } }); let mut builder = AutoBuilder::new( hyper_util::rt::TokioExecutor::new() ); // Use HTTP/1.1 only for now builder = builder.http1_only(); if let Err(e) = builder .serve_connection(io, service) .await { error!("Error serving connection from {}: {}", peer_addr, e); } }); } } }