Skip to main content

rustio_core/
server.rs

1use std::convert::Infallible;
2use std::future::Future;
3use std::net::SocketAddr;
4use std::sync::Arc;
5
6use hyper::server::conn::http1;
7use hyper::service::service_fn;
8use hyper_util::rt::TokioIo;
9use tokio::net::TcpListener;
10
11use crate::http::{Request, Response};
12use crate::router::Router;
13
14pub struct Server {
15    addr: SocketAddr,
16}
17
18impl Server {
19    pub fn bind(addr: SocketAddr) -> Self {
20        Self { addr }
21    }
22
23    pub async fn serve<F, Fut>(self, handler: F) -> std::io::Result<()>
24    where
25        F: Fn(Request) -> Fut + Clone + Send + Sync + 'static,
26        Fut: Future<Output = Response> + Send + 'static,
27    {
28        let listener = TcpListener::bind(self.addr).await?;
29        eprintln!("rustio-core: listening on http://{}", self.addr);
30
31        loop {
32            let (stream, _peer) = listener.accept().await?;
33            let io = TokioIo::new(stream);
34            let handler = handler.clone();
35
36            tokio::spawn(async move {
37                let service = service_fn(move |raw: hyper::Request<hyper::body::Incoming>| {
38                    let handler = handler.clone();
39                    async move {
40                        let req = Request::new(raw);
41                        Ok::<Response, Infallible>(handler(req).await)
42                    }
43                });
44
45                if let Err(err) = http1::Builder::new().serve_connection(io, service).await {
46                    eprintln!("rustio-core: connection error: {err}");
47                }
48            });
49        }
50    }
51
52    pub async fn serve_router(self, router: Router) -> std::io::Result<()> {
53        let router = Arc::new(router);
54        self.serve(move |req| {
55            let router = router.clone();
56            async move { router.dispatch(req).await }
57        })
58        .await
59    }
60}