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 fn get<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
271 where
272 H: Fn(Request) -> Fut + Send + Sync + 'static,
273 Fut: Future<Output = Response> + Send + 'static,
274 {
275 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
276 self.get_routes
277 .insert(path, (Arc::new(handler), path.to_string()))
278 .ok();
279 register_route("GET", path);
280 RouteBuilder {
281 router: self,
282 last_path: path.to_string(),
283 _last_method: Method::Get,
284 }
285 }
286
287 pub fn post<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
289 where
290 H: Fn(Request) -> Fut + Send + Sync + 'static,
291 Fut: Future<Output = Response> + Send + 'static,
292 {
293 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
294 self.post_routes
295 .insert(path, (Arc::new(handler), path.to_string()))
296 .ok();
297 register_route("POST", path);
298 RouteBuilder {
299 router: self,
300 last_path: path.to_string(),
301 _last_method: Method::Post,
302 }
303 }
304
305 pub fn put<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
307 where
308 H: Fn(Request) -> Fut + Send + Sync + 'static,
309 Fut: Future<Output = Response> + Send + 'static,
310 {
311 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
312 self.put_routes
313 .insert(path, (Arc::new(handler), path.to_string()))
314 .ok();
315 register_route("PUT", path);
316 RouteBuilder {
317 router: self,
318 last_path: path.to_string(),
319 _last_method: Method::Put,
320 }
321 }
322
323 pub fn patch<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
325 where
326 H: Fn(Request) -> Fut + Send + Sync + 'static,
327 Fut: Future<Output = Response> + Send + 'static,
328 {
329 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
330 self.patch_routes
331 .insert(path, (Arc::new(handler), path.to_string()))
332 .ok();
333 register_route("PATCH", path);
334 RouteBuilder {
335 router: self,
336 last_path: path.to_string(),
337 _last_method: Method::Patch,
338 }
339 }
340
341 pub fn delete<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
343 where
344 H: Fn(Request) -> Fut + Send + Sync + 'static,
345 Fut: Future<Output = Response> + Send + 'static,
346 {
347 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
348 self.delete_routes
349 .insert(path, (Arc::new(handler), path.to_string()))
350 .ok();
351 register_route("DELETE", path);
352 RouteBuilder {
353 router: self,
354 last_path: path.to_string(),
355 _last_method: Method::Delete,
356 }
357 }
358
359 pub fn match_route(
364 &self,
365 method: &hyper::Method,
366 path: &str,
367 ) -> Option<(Arc<BoxedHandler>, HashMap<String, String>, String)> {
368 let router = match *method {
369 hyper::Method::GET => &self.get_routes,
370 hyper::Method::POST => &self.post_routes,
371 hyper::Method::PUT => &self.put_routes,
372 hyper::Method::PATCH => &self.patch_routes,
373 hyper::Method::DELETE => &self.delete_routes,
374 _ => return None,
375 };
376
377 router.at(path).ok().map(|matched| {
378 let params: HashMap<String, String> = matched
379 .params
380 .iter()
381 .map(|(k, v)| (k.to_string(), v.to_string()))
382 .collect();
383 let (handler, pattern) = matched.value.clone();
384 (handler, params, pattern)
385 })
386 }
387}
388
389impl Default for Router {
390 fn default() -> Self {
391 Self::new()
392 }
393}
394
395pub struct RouteBuilder {
397 pub(crate) router: Router,
398 last_path: String,
399 #[allow(dead_code)]
400 _last_method: Method,
401}
402
403impl RouteBuilder {
404 pub fn name(self, name: &str) -> Router {
406 register_route_name(name, &self.last_path);
407 self.router
408 }
409
410 pub fn middleware<M: Middleware + 'static>(mut self, middleware: M) -> RouteBuilder {
420 let type_name = std::any::type_name::<M>();
422 let short_name = type_name.rsplit("::").next().unwrap_or(type_name);
423 update_route_middleware(&self.last_path, short_name);
424
425 self.router
426 .add_middleware(&self.last_path, into_boxed(middleware));
427 self
428 }
429
430 pub fn middleware_boxed(mut self, middleware: BoxedMiddleware) -> RouteBuilder {
433 update_route_middleware(&self.last_path, "BoxedMiddleware");
435
436 self.router
437 .route_middleware
438 .entry(self.last_path.clone())
439 .or_default()
440 .push(middleware);
441 self
442 }
443
444 pub fn get<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
446 where
447 H: Fn(Request) -> Fut + Send + Sync + 'static,
448 Fut: Future<Output = Response> + Send + 'static,
449 {
450 self.router.get(path, handler)
451 }
452
453 pub fn post<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
455 where
456 H: Fn(Request) -> Fut + Send + Sync + 'static,
457 Fut: Future<Output = Response> + Send + 'static,
458 {
459 self.router.post(path, handler)
460 }
461
462 pub fn put<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
464 where
465 H: Fn(Request) -> Fut + Send + Sync + 'static,
466 Fut: Future<Output = Response> + Send + 'static,
467 {
468 self.router.put(path, handler)
469 }
470
471 pub fn patch<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
473 where
474 H: Fn(Request) -> Fut + Send + Sync + 'static,
475 Fut: Future<Output = Response> + Send + 'static,
476 {
477 self.router.patch(path, handler)
478 }
479
480 pub fn delete<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
482 where
483 H: Fn(Request) -> Fut + Send + Sync + 'static,
484 Fut: Future<Output = Response> + Send + 'static,
485 {
486 self.router.delete(path, handler)
487 }
488}
489
490impl From<RouteBuilder> for Router {
491 fn from(builder: RouteBuilder) -> Self {
492 builder.router
493 }
494}