86 lines
2.7 KiB
Rust
86 lines
2.7 KiB
Rust
use crate::{
|
|
builder::ServerBuilder,
|
|
config::ServerConfig,
|
|
middleware::{Middleware, MiddlewareResult},
|
|
};
|
|
use http1::Builder;
|
|
use http_body_util::Full;
|
|
use hyper::{body::Incoming, server::conn::http1, service::service_fn, Request, Response};
|
|
use hyper_util::rt::TokioIo;
|
|
use log::error;
|
|
use std::{convert::Infallible, future::Future, net::SocketAddr, sync::Arc};
|
|
use tokio::{net::TcpListener, spawn};
|
|
use tokio_util::bytes::Bytes;
|
|
|
|
pub struct Server {
|
|
pub config: Arc<ServerConfig>,
|
|
pub middlewares: Arc<Vec<Box<dyn Middleware>>>,
|
|
}
|
|
|
|
impl Server {
|
|
pub fn builder() -> ServerBuilder {
|
|
ServerBuilder {
|
|
config: ServerConfig::default(),
|
|
middlewares: vec![],
|
|
}
|
|
}
|
|
|
|
pub async fn run<F, Fut>(self, handler: F)
|
|
where
|
|
F: Fn(Request<Incoming>) -> Fut + Send + Sync + 'static,
|
|
Fut: Future<Output = Result<Response<Full<Bytes>>, Infallible>> + Send,
|
|
{
|
|
let addr: SocketAddr = format!("{}:{}", self.config.ip, self.config.port)
|
|
.parse()
|
|
.expect("Invalid IP or port");
|
|
|
|
let listener = TcpListener::bind(addr)
|
|
.await
|
|
.expect("Failed to bind to address");
|
|
let handler = Arc::new(handler);
|
|
|
|
let shared_middlewares = self.middlewares;
|
|
loop {
|
|
let (tcp, client_addr) = match listener.accept().await {
|
|
Ok(conn) => conn,
|
|
Err(e) => {
|
|
error!("Accept error: {}", e);
|
|
continue;
|
|
}
|
|
};
|
|
|
|
let io = TokioIo::new(tcp);
|
|
|
|
let mws = Arc::clone(&shared_middlewares);
|
|
let h = Arc::clone(&handler);
|
|
let client_ip = client_addr.ip();
|
|
|
|
spawn(async move {
|
|
let conn = Builder::new().serve_connection(
|
|
io,
|
|
service_fn(move |mut req| {
|
|
let mws = Arc::clone(&mws);
|
|
let h = Arc::clone(&h);
|
|
|
|
async move {
|
|
req.extensions_mut().insert(client_ip);
|
|
|
|
for mw in mws.iter() {
|
|
match mw.run(req).await {
|
|
MiddlewareResult::Continue(next_req) => req = next_req,
|
|
MiddlewareResult::Respond(res) => return Ok(res),
|
|
}
|
|
}
|
|
h(req).await
|
|
}
|
|
}),
|
|
);
|
|
|
|
if let Err(err) = conn.await {
|
|
error!("Error serving connection: {:?}", err);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|