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}