use std::{any::type_name_of_val, collections::HashMap, error::Error, sync::Arc}; use http_body_util::{Either, Full}; use hyper::{ Request, Response, StatusCode, body::{Body, Bytes, Incoming}, rt::{Read, Write}, server::conn::http1, service::{HttpService, Service}, }; use hyper_util::rt::TokioIo; use json::JsonValue; use log::{error, info}; use rustls::server::Acceptor; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls::{LazyConfigAcceptor, StartHandshake}; use crate::tls::TlsOption; 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, tls: TlsOption, } 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: String) -> GeneralResponse { Response::builder() .status(e) .body(GeneralBody::Right(Full::from(Bytes::from(m)))) .unwrap() } pub async fn json_to_vec(v: JsonValue) -> Option> { if let JsonValue::Array(arr) = v { Some( arr.into_iter() .map(|val| val.as_str().unwrap().to_string()) .collect(), ) } else { None } } impl Server where S: TcpIntercept + Sync, 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 (tcp_stream, _) = self.listener.accept().await.unwrap(); let mut svc_clone = self.service.clone(); let tls = self.tls.clone(); tokio::task::spawn(async move { svc_clone.stream(&tcp_stream); match tls { TlsOption::NoTls => { if let Err(err) = http1::Builder::new() .writev(false) .serve_connection(TokioIo::new(tcp_stream), svc_clone) .await { error!("Error while trying to serve connection: {err}") }; } TlsOption::Tls(x) => { let acceptor = LazyConfigAcceptor::new(Acceptor::default(), tcp_stream); match acceptor.await { Ok(y) => { let hello = y.client_hello(); let hostname = hello.server_name().clone().unwrap(); let config = Arc::new(x.matcher(hostname).unwrap()); let stream = y .into_stream(config) .await .unwrap(); if let Err(err) = http1::Builder::new() .writev(false) .serve_connection(TokioIo::new(stream), svc_clone) .await { error!("Error while trying to serve connection: {err}") } } Err(e) => { error!("Error while initiating handshake: {e}"); return; } } } }; }); } } pub async fn new(service: S, a: (String, u16), tls: TlsOption) -> Result> { Ok(Self { listener: TcpListener::bind(&a).await?, service, tls, }) } } /* */