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