use std::{any::type_name_of_val, error::Error}; use http_body_util::{Either, Full}; use hyper::{ body::{Body, Bytes, Incoming}, server::conn::http1, service::{HttpService, Service}, Request, Response, StatusCode }; use hyper_util::rt::TokioIo; use log::{error, info}; use tokio::net::{TcpListener, TcpStream}; pub type GeneralResponse = Response; pub type GeneralBody = Either>; pub fn to_general_response(res: Response) -> GeneralResponse { let (parts, body) = res.into_parts(); Response::from_parts(parts, GeneralBody::Left(body)) } pub struct Server { listener: TcpListener, service: S, } pub trait TcpIntercept { fn stream(&mut self, stream: &TcpStream); } pub async fn default_response() -> GeneralResponse { Response::builder() .status(404) .body(GeneralBody::Right(Full::from(Bytes::from( "That route doesn't exist.", )))) .unwrap() } pub async fn custom_resp(e: StatusCode, m: &'static str) -> GeneralResponse { Response::builder() .status(e) .body(GeneralBody::Right(Full::from(Bytes::from(m)))) .unwrap() } impl Server where S: TcpIntercept, S: Service> + Clone + Send + 'static, S: HttpService + Clone + Send, ::Error: Into>, ::Data: Send, S::ResBody: Send, >::Future: Send, { pub async fn handle(&self) { info!( "Server started at http://{} for service: {}", self.listener.local_addr().unwrap(), type_name_of_val(&self.service) ); loop { let (stream, _) = self.listener.accept().await.unwrap(); let mut svc_clone = self.service.clone(); svc_clone.stream(&stream); let io = TokioIo::new(stream); tokio::task::spawn(async move { if let Err(err) = http1::Builder::new() .writev(false) .serve_connection(io, svc_clone) .await { error!("Error while trying to serve connection: {err}") }; }); } } pub async fn new(service: S, a: (String, u16)) -> Result> { Ok(Self { listener: TcpListener::bind(&a).await?, service, }) } } /* */