1use std::convert::Infallible;
7use std::future::Future;
8use std::net::SocketAddr;
9use std::sync::Arc;
10
11use hyper::server::conn::http1;
12use hyper::service::service_fn;
13use hyper_util::rt::TokioIo;
14use tokio::net::TcpListener;
15
16use crate::http::{Request, Response};
17use crate::router::Router;
18
19pub struct Server {
20 addr: SocketAddr,
21}
22
23impl Server {
24 pub fn bind(addr: SocketAddr) -> Self {
25 Self { addr }
26 }
27
28 pub async fn serve<F, Fut>(self, handler: F) -> std::io::Result<()>
29 where
30 F: Fn(Request) -> Fut + Clone + Send + Sync + 'static,
31 Fut: Future<Output = Response> + Send + 'static,
32 {
33 let listener = TcpListener::bind(self.addr).await?;
34 eprintln!("rustio-core: listening on http://{}", self.addr);
35
36 loop {
37 let (stream, peer) = listener.accept().await?;
38 let io = TokioIo::new(stream);
39 let handler = handler.clone();
40
41 tokio::spawn(async move {
42 let service = service_fn(move |raw: hyper::Request<hyper::body::Incoming>| {
43 let handler = handler.clone();
44 async move {
45 let req = Request::new(raw, Some(peer));
50 Ok::<Response, Infallible>(handler(req).await)
51 }
52 });
53
54 if let Err(err) = http1::Builder::new().serve_connection(io, service).await {
55 eprintln!("rustio-core: connection error: {err}");
56 }
57 });
58 }
59 }
60
61 pub async fn serve_router(self, router: Router) -> std::io::Result<()> {
62 let router = Arc::new(router);
63 self.serve(move |req| {
64 let router = router.clone();
65 async move { router.dispatch(req).await }
66 })
67 .await
68 }
69
70 pub async fn serve_router_on(listener: TcpListener, router: Router) -> std::io::Result<()> {
77 let router = Arc::new(router);
78 loop {
79 let (stream, peer) = listener.accept().await?;
80 let io = TokioIo::new(stream);
81 let router = router.clone();
82
83 tokio::spawn(async move {
84 let service = service_fn(move |raw: hyper::Request<hyper::body::Incoming>| {
85 let router = router.clone();
86 async move {
87 let req = Request::new(raw, Some(peer));
88 Ok::<Response, Infallible>(router.dispatch(req).await)
89 }
90 });
91 if let Err(err) = http1::Builder::new().serve_connection(io, service).await {
92 eprintln!("rustio-core: connection error: {err}");
93 }
94 });
95 }
96 }
97}