first commit, small server servme
This commit is contained in:
19
src/builder.rs
Normal file
19
src/builder.rs
Normal 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
13
src/config.rs
Normal 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
5
src/lib.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod builder;
|
||||
mod config;
|
||||
mod server;
|
||||
|
||||
pub use server::Server;
|
23
src/main.rs
Normal file
23
src/main.rs
Normal 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
50
src/server.rs
Normal 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"
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user