bolt_web/
lib.rs

1use std::{convert::Infallible, net::SocketAddr, sync::Arc};
2
3use hyper::{
4    Request,
5    body::Incoming,
6    server::conn::{http1, http2},
7    service::service_fn,
8};
9use hyper_util::rt::{TokioExecutor, TokioIo};
10use tokio::net::TcpListener;
11
12use crate::{
13    client::Client,
14    group::Group,
15    middleware::error::DefaultErrorHandler,
16    request::RequestBody,
17    response::ResponseWriter,
18    router::Router,
19    types::{ErrorHandler, Handler, Method, Middleware, Mode},
20};
21
22pub mod client;
23mod group;
24pub mod macros;
25pub mod middleware;
26pub mod request;
27pub mod response;
28mod router;
29pub mod types;
30pub use paste;
31
32#[allow(dead_code)]
33pub struct Bolt {
34    router: Router,
35    error_handler: Arc<dyn ErrorHandler>,
36    client: Client,
37}
38
39#[allow(dead_code)]
40impl Bolt {
41    pub fn new() -> Self {
42        Self {
43            router: Router::new(),
44            error_handler: Arc::new(DefaultErrorHandler),
45            client: Client::new(),
46        }
47    }
48
49    pub async fn run(
50        &self,
51        addr: &str,
52        mode: Mode,
53    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
54        println!("⚡ A high performance & minimalist web framework in rust.");
55        println!(
56            r#"
57    __          ____
58   / /_  ____  / / /_
59  / __ \/ __ \/ / __/
60 / /_/ / /_/ / / /_  
61/_.___/\____/_/\__/  v0.1.3
62"#
63        );
64
65        println!("=> Server running on http://{}", addr);
66
67        let addr: SocketAddr = addr.parse().unwrap();
68
69        let listener = TcpListener::bind(addr).await?;
70        let router = Arc::new(self.router.clone());
71
72        loop {
73            let (stream, _) = listener.accept().await?;
74            let io = TokioIo::new(stream);
75
76            let router = router.clone();
77            let error_handler = self.error_handler.clone();
78
79            let service = service_fn(move |req: Request<Incoming>| {
80                let router = router.clone();
81
82                let error_handler = error_handler.clone();
83
84                async move {
85                    let mut req_body = RequestBody::new(req);
86                    let mut res_body = ResponseWriter::new();
87
88                    let method = match *req_body.method() {
89                        hyper::Method::GET => Method::GET,
90                        hyper::Method::POST => Method::POST,
91                        hyper::Method::PUT => Method::PUT,
92                        hyper::Method::PATCH => Method::PATCH,
93                        hyper::Method::DELETE => Method::DELETE,
94                        hyper::Method::OPTIONS => Method::OPTIONS,
95                        hyper::Method::HEAD => Method::HEAD,
96                        hyper::Method::TRACE => Method::TRACE,
97                        _ => {
98                            res_body.status(405);
99                            res_body.send("Method Not Allowed");
100                            return Ok::<_, Infallible>(res_body.into_response());
101                        }
102                    };
103
104                    let path = req_body.path().to_string();
105
106                    let mws = router.collect_middleware(&path, method);
107
108                    for mw in mws {
109                        mw.run(&mut req_body, &mut res_body).await;
110
111                        if res_body.has_error() {
112                            break;
113                        }
114                    }
115
116                    if !res_body.has_error() {
117                        if let Some((handler, params)) = router.find(&path, method) {
118                            req_body.set_params(params);
119
120                            handler.handle(&mut req_body, &mut res_body).await;
121                        } else {
122                            let method_str = match *req_body.method() {
123                                hyper::Method::GET => "GET",
124                                hyper::Method::POST => "POST",
125                                hyper::Method::PUT => "PUT",
126                                hyper::Method::PATCH => "PATCH",
127                                hyper::Method::DELETE => "DELETE",
128                                hyper::Method::OPTIONS => "OPTIONS",
129                                hyper::Method::HEAD => "HEAD",
130                                hyper::Method::TRACE => "TRACE",
131                                _ => "UNKNOWN",
132                            };
133
134                            res_body.error(404, &format!("Not Found {} {}", method_str, path));
135                        }
136                    }
137
138                    if res_body.has_error() {
139                        let msg = res_body.body.clone();
140                        error_handler.run(msg, &mut res_body).await;
141                    }
142
143                    Ok::<_, Infallible>(res_body.into_response())
144                }
145            });
146
147            match mode {
148                Mode::Http1 => {
149                    tokio::task::spawn(async move {
150                        if let Err(err) = http1::Builder::new().serve_connection(io, service).await
151                        {
152                            eprintln!("Error serving connection: {}", err);
153                        }
154                    });
155                }
156
157                Mode::Http2 => {
158                    tokio::task::spawn(async move {
159                        if let Err(err) = http2::Builder::new(TokioExecutor::new())
160                            .serve_connection(io, service)
161                            .await
162                        {
163                            eprintln!("Error serving connection: {}", err);
164                        }
165                    });
166                }
167            }
168        }
169    }
170
171    fn add_route<H>(&mut self, method: Method, path: &str, handler: H)
172    where
173        H: Handler + 'static,
174    {
175        self.router.insert(path, method, handler);
176    }
177
178    pub fn get<H>(&mut self, path: &str, handler: H)
179    where
180        H: Handler + 'static,
181    {
182        self.add_route(Method::GET, path, handler);
183    }
184
185    pub fn post<H>(&mut self, path: &str, handler: H)
186    where
187        H: Handler + 'static,
188    {
189        self.add_route(Method::POST, path, handler);
190    }
191
192    pub fn put<H>(&mut self, path: &str, handler: H)
193    where
194        H: Handler + 'static,
195    {
196        self.add_route(Method::PUT, path, handler);
197    }
198
199    pub fn patch<H>(&mut self, path: &str, handler: H)
200    where
201        H: Handler + 'static,
202    {
203        self.add_route(Method::PATCH, path, handler);
204    }
205
206    pub fn delete<H>(&mut self, path: &str, handler: H)
207    where
208        H: Handler + 'static,
209    {
210        self.add_route(Method::DELETE, path, handler);
211    }
212
213    pub fn group(&mut self, path: &str) -> Group {
214        Group {
215            prefix: path.to_string(),
216            app: self,
217        }
218    }
219
220    pub fn middleware<M>(&mut self, path: &str, method: Option<Method>, middleware_fn: M)
221    where
222        M: Middleware + 'static,
223    {
224        let mw = Arc::new(middleware_fn);
225        let full_path = path.to_string();
226
227        match method {
228            Some(m) => self.router.insert_middleware(&full_path, m, mw),
229            None => {
230                for m in [
231                    Method::GET,
232                    Method::POST,
233                    Method::PUT,
234                    Method::PATCH,
235                    Method::DELETE,
236                    Method::OPTIONS,
237                    Method::HEAD,
238                    Method::TRACE,
239                ] {
240                    self.router.insert_middleware(&full_path, m, mw.clone());
241                }
242            }
243        }
244    }
245
246    pub fn set_error_handler(&mut self, handler: Arc<dyn ErrorHandler>) {
247        self.error_handler = handler;
248    }
249}