1use crate::http::{Request, Response};
2use crate::middleware::{into_boxed, BoxedMiddleware, Middleware};
3use matchit::Router as MatchitRouter;
4use std::collections::HashMap;
5use std::future::Future;
6use std::pin::Pin;
7use std::sync::{Arc, OnceLock, RwLock};
8
9static ROUTE_REGISTRY: OnceLock<RwLock<HashMap<String, String>>> = OnceLock::new();
11
12pub fn register_route_name(name: &str, path: &str) {
14 let registry = ROUTE_REGISTRY.get_or_init(|| RwLock::new(HashMap::new()));
15 if let Ok(mut map) = registry.write() {
16 map.insert(name.to_string(), path.to_string());
17 }
18}
19
20pub fn route(name: &str, params: &[(&str, &str)]) -> Option<String> {
36 let registry = ROUTE_REGISTRY.get()?.read().ok()?;
37 let path_pattern = registry.get(name)?;
38
39 let mut url = path_pattern.clone();
40 for (key, value) in params {
41 url = url.replace(&format!("{{{}}}", key), value);
42 }
43 Some(url)
44}
45
46pub fn route_with_params(name: &str, params: &HashMap<String, String>) -> Option<String> {
48 let registry = ROUTE_REGISTRY.get()?.read().ok()?;
49 let path_pattern = registry.get(name)?;
50
51 let mut url = path_pattern.clone();
52 for (key, value) in params {
53 url = url.replace(&format!("{{{}}}", key), value);
54 }
55 Some(url)
56}
57
58#[derive(Clone, Copy)]
60enum Method {
61 Get,
62 Post,
63 Put,
64 Delete,
65}
66
67pub type BoxedHandler =
69 Box<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync>;
70
71pub struct Router {
73 get_routes: MatchitRouter<Arc<BoxedHandler>>,
74 post_routes: MatchitRouter<Arc<BoxedHandler>>,
75 put_routes: MatchitRouter<Arc<BoxedHandler>>,
76 delete_routes: MatchitRouter<Arc<BoxedHandler>>,
77 route_middleware: HashMap<String, Vec<BoxedMiddleware>>,
79}
80
81impl Router {
82 pub fn new() -> Self {
83 Self {
84 get_routes: MatchitRouter::new(),
85 post_routes: MatchitRouter::new(),
86 put_routes: MatchitRouter::new(),
87 delete_routes: MatchitRouter::new(),
88 route_middleware: HashMap::new(),
89 }
90 }
91
92 pub fn get_route_middleware(&self, path: &str) -> Vec<BoxedMiddleware> {
94 self.route_middleware.get(path).cloned().unwrap_or_default()
95 }
96
97 pub(crate) fn add_middleware(&mut self, path: &str, middleware: BoxedMiddleware) {
99 self.route_middleware
100 .entry(path.to_string())
101 .or_default()
102 .push(middleware);
103 }
104
105 pub(crate) fn insert_get(&mut self, path: &str, handler: Arc<BoxedHandler>) {
107 self.get_routes.insert(path, handler).ok();
108 }
109
110 pub(crate) fn insert_post(&mut self, path: &str, handler: Arc<BoxedHandler>) {
112 self.post_routes.insert(path, handler).ok();
113 }
114
115 pub(crate) fn insert_put(&mut self, path: &str, handler: Arc<BoxedHandler>) {
117 self.put_routes.insert(path, handler).ok();
118 }
119
120 pub(crate) fn insert_delete(&mut self, path: &str, handler: Arc<BoxedHandler>) {
122 self.delete_routes.insert(path, handler).ok();
123 }
124
125 pub fn get<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
127 where
128 H: Fn(Request) -> Fut + Send + Sync + 'static,
129 Fut: Future<Output = Response> + Send + 'static,
130 {
131 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
132 self.get_routes.insert(path, Arc::new(handler)).ok();
133 RouteBuilder {
134 router: self,
135 last_path: path.to_string(),
136 _last_method: Method::Get,
137 }
138 }
139
140 pub fn post<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
142 where
143 H: Fn(Request) -> Fut + Send + Sync + 'static,
144 Fut: Future<Output = Response> + Send + 'static,
145 {
146 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
147 self.post_routes.insert(path, Arc::new(handler)).ok();
148 RouteBuilder {
149 router: self,
150 last_path: path.to_string(),
151 _last_method: Method::Post,
152 }
153 }
154
155 pub fn put<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
157 where
158 H: Fn(Request) -> Fut + Send + Sync + 'static,
159 Fut: Future<Output = Response> + Send + 'static,
160 {
161 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
162 self.put_routes.insert(path, Arc::new(handler)).ok();
163 RouteBuilder {
164 router: self,
165 last_path: path.to_string(),
166 _last_method: Method::Put,
167 }
168 }
169
170 pub fn delete<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
172 where
173 H: Fn(Request) -> Fut + Send + Sync + 'static,
174 Fut: Future<Output = Response> + Send + 'static,
175 {
176 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
177 self.delete_routes.insert(path, Arc::new(handler)).ok();
178 RouteBuilder {
179 router: self,
180 last_path: path.to_string(),
181 _last_method: Method::Delete,
182 }
183 }
184
185 pub fn match_route(
187 &self,
188 method: &hyper::Method,
189 path: &str,
190 ) -> Option<(Arc<BoxedHandler>, HashMap<String, String>)> {
191 let router = match *method {
192 hyper::Method::GET => &self.get_routes,
193 hyper::Method::POST => &self.post_routes,
194 hyper::Method::PUT => &self.put_routes,
195 hyper::Method::DELETE => &self.delete_routes,
196 _ => return None,
197 };
198
199 router.at(path).ok().map(|matched| {
200 let params: HashMap<String, String> = matched
201 .params
202 .iter()
203 .map(|(k, v)| (k.to_string(), v.to_string()))
204 .collect();
205 (matched.value.clone(), params)
206 })
207 }
208}
209
210impl Default for Router {
211 fn default() -> Self {
212 Self::new()
213 }
214}
215
216pub struct RouteBuilder {
218 pub(crate) router: Router,
219 last_path: String,
220 #[allow(dead_code)]
221 _last_method: Method,
222}
223
224impl RouteBuilder {
225 pub fn name(self, name: &str) -> Router {
227 register_route_name(name, &self.last_path);
228 self.router
229 }
230
231 pub fn middleware<M: Middleware + 'static>(mut self, middleware: M) -> RouteBuilder {
241 self.router
242 .add_middleware(&self.last_path, into_boxed(middleware));
243 self
244 }
245
246 pub fn middleware_boxed(mut self, middleware: BoxedMiddleware) -> RouteBuilder {
249 self.router
250 .route_middleware
251 .entry(self.last_path.clone())
252 .or_default()
253 .push(middleware);
254 self
255 }
256
257 pub fn get<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
259 where
260 H: Fn(Request) -> Fut + Send + Sync + 'static,
261 Fut: Future<Output = Response> + Send + 'static,
262 {
263 self.router.get(path, handler)
264 }
265
266 pub fn post<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
268 where
269 H: Fn(Request) -> Fut + Send + Sync + 'static,
270 Fut: Future<Output = Response> + Send + 'static,
271 {
272 self.router.post(path, handler)
273 }
274
275 pub fn put<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
277 where
278 H: Fn(Request) -> Fut + Send + Sync + 'static,
279 Fut: Future<Output = Response> + Send + 'static,
280 {
281 self.router.put(path, handler)
282 }
283
284 pub fn delete<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
286 where
287 H: Fn(Request) -> Fut + Send + Sync + 'static,
288 Fut: Future<Output = Response> + Send + 'static,
289 {
290 self.router.delete(path, handler)
291 }
292}
293
294impl From<RouteBuilder> for Router {
295 fn from(builder: RouteBuilder) -> Self {
296 builder.router
297 }
298}