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}