first commit, small server servme

This commit is contained in:
2025-01-16 18:24:43 +01:00
commit 79db275dc9
8 changed files with 570 additions and 0 deletions

19
src/builder.rs Normal file
View File

@ -0,0 +1,19 @@
use crate::{config::ServerConfig, server::Server};
pub struct ServerBuilder {
pub config: ServerConfig,
}
impl ServerBuilder {
pub fn address(mut self, ip: &str, port: u16) -> Self {
self.config.ip = ip.to_string();
self.config.port = port;
self
}
pub fn build(self) -> Server {
Server {
config: self.config,
}
}
}

13
src/config.rs Normal file
View File

@ -0,0 +1,13 @@
pub struct ServerConfig {
pub ip: String,
pub port: u16,
}
impl Default for ServerConfig {
fn default() -> Self {
ServerConfig {
ip: "127.0.0.1".to_string(),
port: 8080,
}
}
}

5
src/lib.rs Normal file
View File

@ -0,0 +1,5 @@
mod builder;
mod config;
mod server;
pub use server::Server;

23
src/main.rs Normal file
View File

@ -0,0 +1,23 @@
use http_body_util::Full;
use hyper::{
body::{Bytes, Incoming},
Request, Response,
};
use servme::Server;
use std::convert::Infallible;
#[tokio::main]
async fn main() {
Server::builder()
.address("127.0.0.1", 8080)
.build()
.run(handler)
.await
}
async fn handler(req: Request<Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
Ok(Response::new(Full::new(Bytes::from(format!(
"Hello World! {}",
req.uri()
)))))
}

50
src/server.rs Normal file
View File

@ -0,0 +1,50 @@
use crate::{builder::ServerBuilder, config::ServerConfig};
use http_body_util::Full;
use hyper::{body::Incoming, server::conn::http1, service::service_fn, Request, Response};
use hyper_util::rt::{TokioIo, TokioTimer};
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: ServerConfig,
}
impl Server {
pub fn builder() -> ServerBuilder {
ServerBuilder {
config: ServerConfig::default(),
}
}
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.unwrap();
let handler = Arc::new(handler);
loop {
let (tcp, _) = listener.accept().await.unwrap();
let io = TokioIo::new(tcp);
let handler = Arc::clone(&handler);
spawn(async move {
if let Err(error) = http1::Builder::new()
.timer(TokioTimer::new())
.serve_connection(io, service_fn(move |req| handler(req)))
.await
{
error!(error = error.to_string().as_str();
"Serving connection"
);
}
});
}
}
}