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 {
186 Self {
187 get_routes: MatchitRouter::new(),
188 post_routes: MatchitRouter::new(),
189 put_routes: MatchitRouter::new(),
190 patch_routes: MatchitRouter::new(),
191 delete_routes: MatchitRouter::new(),
192 route_middleware: HashMap::new(),
193 fallback_handler: None,
194 fallback_middleware: Vec::new(),
195 }
196 }
197
198 pub fn get_route_middleware(&self, path: &str) -> Vec<BoxedMiddleware> {
200 self.route_middleware.get(path).cloned().unwrap_or_default()
201 }
202
203 pub(crate) fn add_middleware(&mut self, path: &str, middleware: BoxedMiddleware) {
205 self.route_middleware
206 .entry(path.to_string())
207 .or_default()
208 .push(middleware);
209 }
210
211 pub(crate) fn set_fallback(&mut self, handler: Arc<BoxedHandler>) {
213 self.fallback_handler = Some(handler);
214 }
215
216 pub(crate) fn add_fallback_middleware(&mut self, middleware: BoxedMiddleware) {
218 self.fallback_middleware.push(middleware);
219 }
220
221 pub fn get_fallback(&self) -> Option<(Arc<BoxedHandler>, Vec<BoxedMiddleware>)> {
223 self.fallback_handler
224 .as_ref()
225 .map(|h| (h.clone(), self.fallback_middleware.clone()))
226 }
227
228 pub(crate) fn insert_get(&mut self, path: &str, handler: Arc<BoxedHandler>) {
230 self.get_routes
231 .insert(path, (handler, path.to_string()))
232 .ok();
233 register_route("GET", path);
234 }
235
236 pub(crate) fn insert_post(&mut self, path: &str, handler: Arc<BoxedHandler>) {
238 self.post_routes
239 .insert(path, (handler, path.to_string()))
240 .ok();
241 register_route("POST", path);
242 }
243
244 pub(crate) fn insert_put(&mut self, path: &str, handler: Arc<BoxedHandler>) {
246 self.put_routes
247 .insert(path, (handler, path.to_string()))
248 .ok();
249 register_route("PUT", path);
250 }
251
252 pub(crate) fn insert_patch(&mut self, path: &str, handler: Arc<BoxedHandler>) {
254 self.patch_routes
255 .insert(path, (handler, path.to_string()))
256 .ok();
257 register_route("PATCH", path);
258 }
259
260 pub(crate) fn insert_delete(&mut self, path: &str, handler: Arc<BoxedHandler>) {
262 self.delete_routes
263 .insert(path, (handler, path.to_string()))
264 .ok();
265 register_route("DELETE", path);
266 }
267
268 pub fn get<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
270 where
271 H: Fn(Request) -> Fut + Send + Sync + 'static,
272 Fut: Future<Output = Response> + Send + 'static,
273 {
274 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
275 self.get_routes
276 .insert(path, (Arc::new(handler), path.to_string()))
277 .ok();
278 register_route("GET", path);
279 RouteBuilder {
280 router: self,
281 last_path: path.to_string(),
282 _last_method: Method::Get,
283 }
284 }
285
286 pub fn post<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
288 where
289 H: Fn(Request) -> Fut + Send + Sync + 'static,
290 Fut: Future<Output = Response> + Send + 'static,
291 {
292 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
293 self.post_routes
294 .insert(path, (Arc::new(handler), path.to_string()))
295 .ok();
296 register_route("POST", path);
297 RouteBuilder {
298 router: self,
299 last_path: path.to_string(),
300 _last_method: Method::Post,
301 }
302 }
303
304 pub fn put<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
306 where
307 H: Fn(Request) -> Fut + Send + Sync + 'static,
308 Fut: Future<Output = Response> + Send + 'static,
309 {
310 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
311 self.put_routes
312 .insert(path, (Arc::new(handler), path.to_string()))
313 .ok();
314 register_route("PUT", path);
315 RouteBuilder {
316 router: self,
317 last_path: path.to_string(),
318 _last_method: Method::Put,
319 }
320 }
321
322 pub fn patch<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
324 where
325 H: Fn(Request) -> Fut + Send + Sync + 'static,
326 Fut: Future<Output = Response> + Send + 'static,
327 {
328 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
329 self.patch_routes
330 .insert(path, (Arc::new(handler), path.to_string()))
331 .ok();
332 register_route("PATCH", path);
333 RouteBuilder {
334 router: self,
335 last_path: path.to_string(),
336 _last_method: Method::Patch,
337 }
338 }
339
340 pub fn delete<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
342 where
343 H: Fn(Request) -> Fut + Send + Sync + 'static,
344 Fut: Future<Output = Response> + Send + 'static,
345 {
346 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
347 self.delete_routes
348 .insert(path, (Arc::new(handler), path.to_string()))
349 .ok();
350 register_route("DELETE", path);
351 RouteBuilder {
352 router: self,
353 last_path: path.to_string(),
354 _last_method: Method::Delete,
355 }
356 }
357
358 pub fn match_route(
363 &self,
364 method: &hyper::Method,
365 path: &str,
366 ) -> Option<(Arc<BoxedHandler>, HashMap<String, String>, String)> {
367 let router = match *method {
368 hyper::Method::GET => &self.get_routes,
369 hyper::Method::POST => &self.post_routes,
370 hyper::Method::PUT => &self.put_routes,
371 hyper::Method::PATCH => &self.patch_routes,
372 hyper::Method::DELETE => &self.delete_routes,
373 _ => return None,
374 };
375
376 router.at(path).ok().map(|matched| {
377 let params: HashMap<String, String> = matched
378 .params
379 .iter()
380 .map(|(k, v)| (k.to_string(), v.to_string()))
381 .collect();
382 let (handler, pattern) = matched.value.clone();
383 (handler, params, pattern)
384 })
385 }
386}
387
388impl Default for Router {
389 fn default() -> Self {
390 Self::new()
391 }
392}
393
394pub struct RouteBuilder {
396 pub(crate) router: Router,
397 last_path: String,
398 #[allow(dead_code)]
399 _last_method: Method,
400}
401
402impl RouteBuilder {
403 pub fn name(self, name: &str) -> Router {
405 register_route_name(name, &self.last_path);
406 self.router
407 }
408
409 pub fn middleware<M: Middleware + 'static>(mut self, middleware: M) -> RouteBuilder {
419 let type_name = std::any::type_name::<M>();
421 let short_name = type_name.rsplit("::").next().unwrap_or(type_name);
422 update_route_middleware(&self.last_path, short_name);
423
424 self.router
425 .add_middleware(&self.last_path, into_boxed(middleware));
426 self
427 }
428
429 pub fn middleware_boxed(mut self, middleware: BoxedMiddleware) -> RouteBuilder {
432 update_route_middleware(&self.last_path, "BoxedMiddleware");
434
435 self.router
436 .route_middleware
437 .entry(self.last_path.clone())
438 .or_default()
439 .push(middleware);
440 self
441 }
442
443 pub fn get<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
445 where
446 H: Fn(Request) -> Fut + Send + Sync + 'static,
447 Fut: Future<Output = Response> + Send + 'static,
448 {
449 self.router.get(path, handler)
450 }
451
452 pub fn post<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
454 where
455 H: Fn(Request) -> Fut + Send + Sync + 'static,
456 Fut: Future<Output = Response> + Send + 'static,
457 {
458 self.router.post(path, handler)
459 }
460
461 pub fn put<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
463 where
464 H: Fn(Request) -> Fut + Send + Sync + 'static,
465 Fut: Future<Output = Response> + Send + 'static,
466 {
467 self.router.put(path, handler)
468 }
469
470 pub fn patch<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
472 where
473 H: Fn(Request) -> Fut + Send + Sync + 'static,
474 Fut: Future<Output = Response> + Send + 'static,
475 {
476 self.router.patch(path, handler)
477 }
478
479 pub fn delete<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
481 where
482 H: Fn(Request) -> Fut + Send + Sync + 'static,
483 Fut: Future<Output = Response> + Send + 'static,
484 {
485 self.router.delete(path, handler)
486 }
487}
488
489impl From<RouteBuilder> for Router {
490 fn from(builder: RouteBuilder) -> Self {
491 builder.router
492 }
493}