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, Default, Serialize)]
18pub struct RouteInfo {
19 pub method: String,
21 pub path: String,
23 pub name: Option<String>,
25 pub middleware: Vec<String>,
27 pub mcp_tool_name: Option<String>,
29 pub mcp_description: Option<String>,
31 pub mcp_hint: Option<String>,
33 pub mcp_hidden: bool,
35}
36
37fn register_route(method: &str, path: &str) {
39 let registry = REGISTERED_ROUTES.get_or_init(|| RwLock::new(Vec::new()));
40 if let Ok(mut routes) = registry.write() {
41 routes.push(RouteInfo {
42 method: method.to_string(),
43 path: path.to_string(),
44 name: None,
45 middleware: Vec::new(),
46 mcp_tool_name: None,
47 mcp_description: None,
48 mcp_hint: None,
49 mcp_hidden: false,
50 });
51 }
52}
53
54fn update_route_name(path: &str, name: &str) {
56 let registry = REGISTERED_ROUTES.get_or_init(|| RwLock::new(Vec::new()));
57 if let Ok(mut routes) = registry.write() {
58 if let Some(route) = routes.iter_mut().rev().find(|r| r.path == path) {
60 route.name = Some(name.to_string());
61 }
62 }
63}
64
65fn update_route_middleware(path: &str, middleware_name: &str) {
67 let registry = REGISTERED_ROUTES.get_or_init(|| RwLock::new(Vec::new()));
68 if let Ok(mut routes) = registry.write() {
69 if let Some(route) = routes.iter_mut().rev().find(|r| r.path == path) {
71 route.middleware.push(middleware_name.to_string());
72 }
73 }
74}
75
76pub(crate) fn update_route_mcp(
78 path: &str,
79 tool_name: Option<String>,
80 description: Option<String>,
81 hint: Option<String>,
82 hidden: bool,
83) {
84 let registry = REGISTERED_ROUTES.get_or_init(|| RwLock::new(Vec::new()));
85 if let Ok(mut routes) = registry.write() {
86 if let Some(route) = routes.iter_mut().rev().find(|r| r.path == path) {
87 route.mcp_tool_name = tool_name;
88 route.mcp_description = description;
89 route.mcp_hint = hint;
90 route.mcp_hidden = hidden;
91 }
92 }
93}
94
95pub fn get_registered_routes() -> Vec<RouteInfo> {
97 REGISTERED_ROUTES
98 .get()
99 .and_then(|r| r.read().ok())
100 .map(|routes| routes.clone())
101 .unwrap_or_default()
102}
103
104pub fn register_route_name(name: &str, path: &str) {
106 let registry = ROUTE_REGISTRY.get_or_init(|| RwLock::new(HashMap::new()));
107 if let Ok(mut map) = registry.write() {
108 map.insert(name.to_string(), path.to_string());
109 }
110 update_route_name(path, name);
112}
113
114pub fn route(name: &str, params: &[(&str, &str)]) -> Option<String> {
130 let registry = ROUTE_REGISTRY.get()?.read().ok()?;
131 let path_pattern = registry.get(name)?;
132
133 let mut url = path_pattern.clone();
134 for (key, value) in params {
135 url = url.replace(&format!("{{{key}}}"), value);
136 }
137 Some(url)
138}
139
140pub fn route_with_params(name: &str, params: &HashMap<String, String>) -> Option<String> {
142 let registry = ROUTE_REGISTRY.get()?.read().ok()?;
143 let path_pattern = registry.get(name)?;
144
145 let mut url = path_pattern.clone();
146 for (key, value) in params {
147 url = url.replace(&format!("{{{key}}}"), value);
148 }
149 Some(url)
150}
151
152#[derive(Clone, Copy)]
154enum Method {
155 Get,
156 Post,
157 Put,
158 Patch,
159 Delete,
160}
161
162pub type BoxedHandler =
164 Box<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync>;
165
166type RouteValue = (Arc<BoxedHandler>, String);
168
169pub struct Router {
171 get_routes: MatchitRouter<RouteValue>,
172 post_routes: MatchitRouter<RouteValue>,
173 put_routes: MatchitRouter<RouteValue>,
174 patch_routes: MatchitRouter<RouteValue>,
175 delete_routes: MatchitRouter<RouteValue>,
176 route_middleware: HashMap<String, Vec<BoxedMiddleware>>,
178 fallback_handler: Option<Arc<BoxedHandler>>,
180 fallback_middleware: Vec<BoxedMiddleware>,
182}
183
184impl Router {
185 pub fn new() -> Self {
187 Self {
188 get_routes: MatchitRouter::new(),
189 post_routes: MatchitRouter::new(),
190 put_routes: MatchitRouter::new(),
191 patch_routes: MatchitRouter::new(),
192 delete_routes: MatchitRouter::new(),
193 route_middleware: HashMap::new(),
194 fallback_handler: None,
195 fallback_middleware: Vec::new(),
196 }
197 }
198
199 pub fn get_route_middleware(&self, path: &str) -> Vec<BoxedMiddleware> {
201 self.route_middleware.get(path).cloned().unwrap_or_default()
202 }
203
204 pub(crate) fn add_middleware(&mut self, path: &str, middleware: BoxedMiddleware) {
206 self.route_middleware
207 .entry(path.to_string())
208 .or_default()
209 .push(middleware);
210 }
211
212 pub(crate) fn set_fallback(&mut self, handler: Arc<BoxedHandler>) {
214 self.fallback_handler = Some(handler);
215 }
216
217 pub(crate) fn add_fallback_middleware(&mut self, middleware: BoxedMiddleware) {
219 self.fallback_middleware.push(middleware);
220 }
221
222 pub fn get_fallback(&self) -> Option<(Arc<BoxedHandler>, Vec<BoxedMiddleware>)> {
224 self.fallback_handler
225 .as_ref()
226 .map(|h| (h.clone(), self.fallback_middleware.clone()))
227 }
228
229 pub(crate) fn insert_get(&mut self, path: &str, handler: Arc<BoxedHandler>) {
231 self.get_routes
232 .insert(path, (handler, path.to_string()))
233 .ok();
234 register_route("GET", path);
235 }
236
237 pub(crate) fn insert_post(&mut self, path: &str, handler: Arc<BoxedHandler>) {
239 self.post_routes
240 .insert(path, (handler, path.to_string()))
241 .ok();
242 register_route("POST", path);
243 }
244
245 pub(crate) fn insert_put(&mut self, path: &str, handler: Arc<BoxedHandler>) {
247 self.put_routes
248 .insert(path, (handler, path.to_string()))
249 .ok();
250 register_route("PUT", path);
251 }
252
253 pub(crate) fn insert_patch(&mut self, path: &str, handler: Arc<BoxedHandler>) {
255 self.patch_routes
256 .insert(path, (handler, path.to_string()))
257 .ok();
258 register_route("PATCH", path);
259 }
260
261 pub(crate) fn insert_delete(&mut self, path: &str, handler: Arc<BoxedHandler>) {
263 self.delete_routes
264 .insert(path, (handler, path.to_string()))
265 .ok();
266 register_route("DELETE", path);
267 }
268
269 pub(crate) fn insert_get_alias(
276 &mut self,
277 alias_path: &str,
278 handler: Arc<BoxedHandler>,
279 canonical_path: &str,
280 ) {
281 self.get_routes
282 .insert(alias_path, (handler, canonical_path.to_string()))
283 .ok();
284 }
285
286 pub(crate) fn insert_post_alias(
289 &mut self,
290 alias_path: &str,
291 handler: Arc<BoxedHandler>,
292 canonical_path: &str,
293 ) {
294 self.post_routes
295 .insert(alias_path, (handler, canonical_path.to_string()))
296 .ok();
297 }
298
299 pub(crate) fn insert_put_alias(
302 &mut self,
303 alias_path: &str,
304 handler: Arc<BoxedHandler>,
305 canonical_path: &str,
306 ) {
307 self.put_routes
308 .insert(alias_path, (handler, canonical_path.to_string()))
309 .ok();
310 }
311
312 pub(crate) fn insert_patch_alias(
315 &mut self,
316 alias_path: &str,
317 handler: Arc<BoxedHandler>,
318 canonical_path: &str,
319 ) {
320 self.patch_routes
321 .insert(alias_path, (handler, canonical_path.to_string()))
322 .ok();
323 }
324
325 pub(crate) fn insert_delete_alias(
328 &mut self,
329 alias_path: &str,
330 handler: Arc<BoxedHandler>,
331 canonical_path: &str,
332 ) {
333 self.delete_routes
334 .insert(alias_path, (handler, canonical_path.to_string()))
335 .ok();
336 }
337
338 pub fn get<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
340 where
341 H: Fn(Request) -> Fut + Send + Sync + 'static,
342 Fut: Future<Output = Response> + Send + 'static,
343 {
344 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
345 self.get_routes
346 .insert(path, (Arc::new(handler), path.to_string()))
347 .ok();
348 register_route("GET", path);
349 RouteBuilder {
350 router: self,
351 last_path: path.to_string(),
352 _last_method: Method::Get,
353 }
354 }
355
356 pub fn post<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
358 where
359 H: Fn(Request) -> Fut + Send + Sync + 'static,
360 Fut: Future<Output = Response> + Send + 'static,
361 {
362 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
363 self.post_routes
364 .insert(path, (Arc::new(handler), path.to_string()))
365 .ok();
366 register_route("POST", path);
367 RouteBuilder {
368 router: self,
369 last_path: path.to_string(),
370 _last_method: Method::Post,
371 }
372 }
373
374 pub fn put<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
376 where
377 H: Fn(Request) -> Fut + Send + Sync + 'static,
378 Fut: Future<Output = Response> + Send + 'static,
379 {
380 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
381 self.put_routes
382 .insert(path, (Arc::new(handler), path.to_string()))
383 .ok();
384 register_route("PUT", path);
385 RouteBuilder {
386 router: self,
387 last_path: path.to_string(),
388 _last_method: Method::Put,
389 }
390 }
391
392 pub fn patch<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
394 where
395 H: Fn(Request) -> Fut + Send + Sync + 'static,
396 Fut: Future<Output = Response> + Send + 'static,
397 {
398 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
399 self.patch_routes
400 .insert(path, (Arc::new(handler), path.to_string()))
401 .ok();
402 register_route("PATCH", path);
403 RouteBuilder {
404 router: self,
405 last_path: path.to_string(),
406 _last_method: Method::Patch,
407 }
408 }
409
410 pub fn delete<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
412 where
413 H: Fn(Request) -> Fut + Send + Sync + 'static,
414 Fut: Future<Output = Response> + Send + 'static,
415 {
416 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
417 self.delete_routes
418 .insert(path, (Arc::new(handler), path.to_string()))
419 .ok();
420 register_route("DELETE", path);
421 RouteBuilder {
422 router: self,
423 last_path: path.to_string(),
424 _last_method: Method::Delete,
425 }
426 }
427
428 pub fn match_route(
433 &self,
434 method: &hyper::Method,
435 path: &str,
436 ) -> Option<(Arc<BoxedHandler>, HashMap<String, String>, String)> {
437 let router = match *method {
438 hyper::Method::GET => &self.get_routes,
439 hyper::Method::POST => &self.post_routes,
440 hyper::Method::PUT => &self.put_routes,
441 hyper::Method::PATCH => &self.patch_routes,
442 hyper::Method::DELETE => &self.delete_routes,
443 _ => return None,
444 };
445
446 router.at(path).ok().map(|matched| {
447 let params: HashMap<String, String> = matched
448 .params
449 .iter()
450 .map(|(k, v)| (k.to_string(), v.to_string()))
451 .collect();
452 let (handler, pattern) = matched.value.clone();
453 (handler, params, pattern)
454 })
455 }
456}
457
458impl Default for Router {
459 fn default() -> Self {
460 Self::new()
461 }
462}
463
464pub struct RouteBuilder {
466 pub(crate) router: Router,
467 last_path: String,
468 #[allow(dead_code)]
469 _last_method: Method,
470}
471
472impl RouteBuilder {
473 pub fn name(self, name: &str) -> Router {
475 register_route_name(name, &self.last_path);
476 self.router
477 }
478
479 pub fn middleware<M: Middleware + 'static>(mut self, middleware: M) -> RouteBuilder {
489 let type_name = std::any::type_name::<M>();
491 let short_name = type_name.rsplit("::").next().unwrap_or(type_name);
492 update_route_middleware(&self.last_path, short_name);
493
494 self.router
495 .add_middleware(&self.last_path, into_boxed(middleware));
496 self
497 }
498
499 pub fn middleware_boxed(mut self, middleware: BoxedMiddleware) -> RouteBuilder {
502 update_route_middleware(&self.last_path, "BoxedMiddleware");
504
505 self.router
506 .route_middleware
507 .entry(self.last_path.clone())
508 .or_default()
509 .push(middleware);
510 self
511 }
512
513 pub fn get<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
515 where
516 H: Fn(Request) -> Fut + Send + Sync + 'static,
517 Fut: Future<Output = Response> + Send + 'static,
518 {
519 self.router.get(path, handler)
520 }
521
522 pub fn post<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
524 where
525 H: Fn(Request) -> Fut + Send + Sync + 'static,
526 Fut: Future<Output = Response> + Send + 'static,
527 {
528 self.router.post(path, handler)
529 }
530
531 pub fn put<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
533 where
534 H: Fn(Request) -> Fut + Send + Sync + 'static,
535 Fut: Future<Output = Response> + Send + 'static,
536 {
537 self.router.put(path, handler)
538 }
539
540 pub fn patch<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
542 where
543 H: Fn(Request) -> Fut + Send + Sync + 'static,
544 Fut: Future<Output = Response> + Send + 'static,
545 {
546 self.router.patch(path, handler)
547 }
548
549 pub fn delete<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
551 where
552 H: Fn(Request) -> Fut + Send + Sync + 'static,
553 Fut: Future<Output = Response> + Send + 'static,
554 {
555 self.router.delete(path, handler)
556 }
557}
558
559impl From<RouteBuilder> for Router {
560 fn from(builder: RouteBuilder) -> Self {
561 builder.router
562 }
563}