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