1use crate::http::{Request, Response};
2use crate::middleware::{into_boxed, BoxedMiddleware, Middleware};
3use matchit::Router as MatchitRouter;
4use serde::Serialize;
5use std::collections::HashMap;
6use std::future::Future;
7use std::pin::Pin;
8use std::sync::{Arc, OnceLock, RwLock};
9
10static ROUTE_REGISTRY: OnceLock<RwLock<HashMap<String, String>>> = OnceLock::new();
12
13static REGISTERED_ROUTES: OnceLock<RwLock<Vec<RouteInfo>>> = OnceLock::new();
15
16#[derive(Debug, Clone, Serialize)]
18pub struct RouteInfo {
19 pub method: String,
21 pub path: String,
23 pub name: Option<String>,
25 pub middleware: Vec<String>,
27}
28
29fn register_route(method: &str, path: &str) {
31 let registry = REGISTERED_ROUTES.get_or_init(|| RwLock::new(Vec::new()));
32 if let Ok(mut routes) = registry.write() {
33 routes.push(RouteInfo {
34 method: method.to_string(),
35 path: path.to_string(),
36 name: None,
37 middleware: Vec::new(),
38 });
39 }
40}
41
42fn update_route_name(path: &str, name: &str) {
44 let registry = REGISTERED_ROUTES.get_or_init(|| RwLock::new(Vec::new()));
45 if let Ok(mut routes) = registry.write() {
46 if let Some(route) = routes.iter_mut().rev().find(|r| r.path == path) {
48 route.name = Some(name.to_string());
49 }
50 }
51}
52
53fn update_route_middleware(path: &str, middleware_name: &str) {
55 let registry = REGISTERED_ROUTES.get_or_init(|| RwLock::new(Vec::new()));
56 if let Ok(mut routes) = registry.write() {
57 if let Some(route) = routes.iter_mut().rev().find(|r| r.path == path) {
59 route.middleware.push(middleware_name.to_string());
60 }
61 }
62}
63
64pub fn get_registered_routes() -> Vec<RouteInfo> {
66 REGISTERED_ROUTES
67 .get()
68 .and_then(|r| r.read().ok())
69 .map(|routes| routes.clone())
70 .unwrap_or_default()
71}
72
73pub fn register_route_name(name: &str, path: &str) {
75 let registry = ROUTE_REGISTRY.get_or_init(|| RwLock::new(HashMap::new()));
76 if let Ok(mut map) = registry.write() {
77 map.insert(name.to_string(), path.to_string());
78 }
79 update_route_name(path, name);
81}
82
83pub fn route(name: &str, params: &[(&str, &str)]) -> Option<String> {
99 let registry = ROUTE_REGISTRY.get()?.read().ok()?;
100 let path_pattern = registry.get(name)?;
101
102 let mut url = path_pattern.clone();
103 for (key, value) in params {
104 url = url.replace(&format!("{{{key}}}"), value);
105 }
106 Some(url)
107}
108
109pub fn route_with_params(name: &str, params: &HashMap<String, String>) -> Option<String> {
111 let registry = ROUTE_REGISTRY.get()?.read().ok()?;
112 let path_pattern = registry.get(name)?;
113
114 let mut url = path_pattern.clone();
115 for (key, value) in params {
116 url = url.replace(&format!("{{{key}}}"), value);
117 }
118 Some(url)
119}
120
121#[derive(Clone, Copy)]
123enum Method {
124 Get,
125 Post,
126 Put,
127 Patch,
128 Delete,
129}
130
131pub type BoxedHandler =
133 Box<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync>;
134
135type RouteValue = (Arc<BoxedHandler>, String);
137
138pub struct Router {
140 get_routes: MatchitRouter<RouteValue>,
141 post_routes: MatchitRouter<RouteValue>,
142 put_routes: MatchitRouter<RouteValue>,
143 patch_routes: MatchitRouter<RouteValue>,
144 delete_routes: MatchitRouter<RouteValue>,
145 route_middleware: HashMap<String, Vec<BoxedMiddleware>>,
147 fallback_handler: Option<Arc<BoxedHandler>>,
149 fallback_middleware: Vec<BoxedMiddleware>,
151}
152
153impl Router {
154 pub fn new() -> Self {
155 Self {
156 get_routes: MatchitRouter::new(),
157 post_routes: MatchitRouter::new(),
158 put_routes: MatchitRouter::new(),
159 patch_routes: MatchitRouter::new(),
160 delete_routes: MatchitRouter::new(),
161 route_middleware: HashMap::new(),
162 fallback_handler: None,
163 fallback_middleware: Vec::new(),
164 }
165 }
166
167 pub fn get_route_middleware(&self, path: &str) -> Vec<BoxedMiddleware> {
169 self.route_middleware.get(path).cloned().unwrap_or_default()
170 }
171
172 pub(crate) fn add_middleware(&mut self, path: &str, middleware: BoxedMiddleware) {
174 self.route_middleware
175 .entry(path.to_string())
176 .or_default()
177 .push(middleware);
178 }
179
180 pub(crate) fn set_fallback(&mut self, handler: Arc<BoxedHandler>) {
182 self.fallback_handler = Some(handler);
183 }
184
185 pub(crate) fn add_fallback_middleware(&mut self, middleware: BoxedMiddleware) {
187 self.fallback_middleware.push(middleware);
188 }
189
190 pub fn get_fallback(&self) -> Option<(Arc<BoxedHandler>, Vec<BoxedMiddleware>)> {
192 self.fallback_handler
193 .as_ref()
194 .map(|h| (h.clone(), self.fallback_middleware.clone()))
195 }
196
197 pub(crate) fn insert_get(&mut self, path: &str, handler: Arc<BoxedHandler>) {
199 self.get_routes
200 .insert(path, (handler, path.to_string()))
201 .ok();
202 register_route("GET", path);
203 }
204
205 pub(crate) fn insert_post(&mut self, path: &str, handler: Arc<BoxedHandler>) {
207 self.post_routes
208 .insert(path, (handler, path.to_string()))
209 .ok();
210 register_route("POST", path);
211 }
212
213 pub(crate) fn insert_put(&mut self, path: &str, handler: Arc<BoxedHandler>) {
215 self.put_routes
216 .insert(path, (handler, path.to_string()))
217 .ok();
218 register_route("PUT", path);
219 }
220
221 pub(crate) fn insert_patch(&mut self, path: &str, handler: Arc<BoxedHandler>) {
223 self.patch_routes
224 .insert(path, (handler, path.to_string()))
225 .ok();
226 register_route("PATCH", path);
227 }
228
229 pub(crate) fn insert_delete(&mut self, path: &str, handler: Arc<BoxedHandler>) {
231 self.delete_routes
232 .insert(path, (handler, path.to_string()))
233 .ok();
234 register_route("DELETE", path);
235 }
236
237 pub fn get<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
239 where
240 H: Fn(Request) -> Fut + Send + Sync + 'static,
241 Fut: Future<Output = Response> + Send + 'static,
242 {
243 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
244 self.get_routes
245 .insert(path, (Arc::new(handler), path.to_string()))
246 .ok();
247 register_route("GET", path);
248 RouteBuilder {
249 router: self,
250 last_path: path.to_string(),
251 _last_method: Method::Get,
252 }
253 }
254
255 pub fn post<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
257 where
258 H: Fn(Request) -> Fut + Send + Sync + 'static,
259 Fut: Future<Output = Response> + Send + 'static,
260 {
261 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
262 self.post_routes
263 .insert(path, (Arc::new(handler), path.to_string()))
264 .ok();
265 register_route("POST", path);
266 RouteBuilder {
267 router: self,
268 last_path: path.to_string(),
269 _last_method: Method::Post,
270 }
271 }
272
273 pub fn put<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
275 where
276 H: Fn(Request) -> Fut + Send + Sync + 'static,
277 Fut: Future<Output = Response> + Send + 'static,
278 {
279 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
280 self.put_routes
281 .insert(path, (Arc::new(handler), path.to_string()))
282 .ok();
283 register_route("PUT", path);
284 RouteBuilder {
285 router: self,
286 last_path: path.to_string(),
287 _last_method: Method::Put,
288 }
289 }
290
291 pub fn patch<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
293 where
294 H: Fn(Request) -> Fut + Send + Sync + 'static,
295 Fut: Future<Output = Response> + Send + 'static,
296 {
297 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
298 self.patch_routes
299 .insert(path, (Arc::new(handler), path.to_string()))
300 .ok();
301 register_route("PATCH", path);
302 RouteBuilder {
303 router: self,
304 last_path: path.to_string(),
305 _last_method: Method::Patch,
306 }
307 }
308
309 pub fn delete<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
311 where
312 H: Fn(Request) -> Fut + Send + Sync + 'static,
313 Fut: Future<Output = Response> + Send + 'static,
314 {
315 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
316 self.delete_routes
317 .insert(path, (Arc::new(handler), path.to_string()))
318 .ok();
319 register_route("DELETE", path);
320 RouteBuilder {
321 router: self,
322 last_path: path.to_string(),
323 _last_method: Method::Delete,
324 }
325 }
326
327 pub fn match_route(
332 &self,
333 method: &hyper::Method,
334 path: &str,
335 ) -> Option<(Arc<BoxedHandler>, HashMap<String, String>, String)> {
336 let router = match *method {
337 hyper::Method::GET => &self.get_routes,
338 hyper::Method::POST => &self.post_routes,
339 hyper::Method::PUT => &self.put_routes,
340 hyper::Method::PATCH => &self.patch_routes,
341 hyper::Method::DELETE => &self.delete_routes,
342 _ => return None,
343 };
344
345 router.at(path).ok().map(|matched| {
346 let params: HashMap<String, String> = matched
347 .params
348 .iter()
349 .map(|(k, v)| (k.to_string(), v.to_string()))
350 .collect();
351 let (handler, pattern) = matched.value.clone();
352 (handler, params, pattern)
353 })
354 }
355}
356
357impl Default for Router {
358 fn default() -> Self {
359 Self::new()
360 }
361}
362
363pub struct RouteBuilder {
365 pub(crate) router: Router,
366 last_path: String,
367 #[allow(dead_code)]
368 _last_method: Method,
369}
370
371impl RouteBuilder {
372 pub fn name(self, name: &str) -> Router {
374 register_route_name(name, &self.last_path);
375 self.router
376 }
377
378 pub fn middleware<M: Middleware + 'static>(mut self, middleware: M) -> RouteBuilder {
388 let type_name = std::any::type_name::<M>();
390 let short_name = type_name.rsplit("::").next().unwrap_or(type_name);
391 update_route_middleware(&self.last_path, short_name);
392
393 self.router
394 .add_middleware(&self.last_path, into_boxed(middleware));
395 self
396 }
397
398 pub fn middleware_boxed(mut self, middleware: BoxedMiddleware) -> RouteBuilder {
401 update_route_middleware(&self.last_path, "BoxedMiddleware");
403
404 self.router
405 .route_middleware
406 .entry(self.last_path.clone())
407 .or_default()
408 .push(middleware);
409 self
410 }
411
412 pub fn get<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
414 where
415 H: Fn(Request) -> Fut + Send + Sync + 'static,
416 Fut: Future<Output = Response> + Send + 'static,
417 {
418 self.router.get(path, handler)
419 }
420
421 pub fn post<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
423 where
424 H: Fn(Request) -> Fut + Send + Sync + 'static,
425 Fut: Future<Output = Response> + Send + 'static,
426 {
427 self.router.post(path, handler)
428 }
429
430 pub fn put<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
432 where
433 H: Fn(Request) -> Fut + Send + Sync + 'static,
434 Fut: Future<Output = Response> + Send + 'static,
435 {
436 self.router.put(path, handler)
437 }
438
439 pub fn patch<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
441 where
442 H: Fn(Request) -> Fut + Send + Sync + 'static,
443 Fut: Future<Output = Response> + Send + 'static,
444 {
445 self.router.patch(path, handler)
446 }
447
448 pub fn delete<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
450 where
451 H: Fn(Request) -> Fut + Send + Sync + 'static,
452 Fut: Future<Output = Response> + Send + 'static,
453 {
454 self.router.delete(path, handler)
455 }
456}
457
458impl From<RouteBuilder> for Router {
459 fn from(builder: RouteBuilder) -> Self {
460 builder.router
461 }
462}