1use std::collections::HashMap;
7use std::fmt;
8use std::future::Future;
9use std::pin::Pin;
10use std::sync::Arc;
11
12use axum::{
13 extract::{Path, Query, State},
14 http::{Method, StatusCode},
15 response::{IntoResponse, Response as AxumResponse},
16 Json,
17};
18use serde_json::{json, Value};
19
20use crate::{
21 errors::{Result, RustisanError},
22 http::{Request, Response},
23};
24
25pub type AsyncHandler = Arc<
27 dyn Fn() -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync,
28>;
29
30pub type AsyncHandlerWithRequest = Arc<
32 dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync,
33>;
34
35pub type AsyncHandlerWithId = Arc<
37 dyn Fn(u32) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync,
38>;
39
40pub type AsyncHandlerWithIdAndRequest = Arc<
42 dyn Fn(u32, Request) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync,
43>;
44
45#[derive(Clone)]
47pub struct Route {
48 pub method: Method,
50 pub path: String,
52 pub handler: RouteHandler,
54 pub middleware: Vec<String>,
56 pub name: Option<String>,
58}
59
60#[derive(Clone)]
62pub enum RouteHandler {
63 Simple(AsyncHandler),
65 WithRequest(AsyncHandlerWithRequest),
67 WithId(AsyncHandlerWithId),
69 WithIdAndRequest(AsyncHandlerWithIdAndRequest),
71}
72
73pub struct Router {
75 pub routes: Vec<Route>,
77 pub groups: Vec<RouteGroup>,
79 pub middleware: Vec<String>,
81 named_routes: HashMap<String, usize>,
83}
84
85pub struct RouteGroup {
87 pub prefix: String,
89 pub middleware: Vec<String>,
91 pub routes: Vec<Route>,
93}
94
95impl Router {
96 pub fn new() -> Self {
98 Self {
99 routes: Vec::new(),
100 groups: Vec::new(),
101 middleware: Vec::new(),
102 named_routes: HashMap::new(),
103 }
104 }
105
106 pub fn get<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
108 where
109 F: Fn() -> Fut + Send + Sync + 'static,
110 Fut: Future<Output = Response> + Send + 'static,
111 {
112 let async_handler: AsyncHandler = Arc::new(move || {
113 let fut = handler();
114 Box::pin(fut)
115 });
116
117 self.routes.push(Route {
118 method: Method::GET,
119 path: path.to_string(),
120 handler: RouteHandler::Simple(async_handler),
121 middleware: Vec::new(),
122 name: None,
123 });
124
125 self
126 }
127
128 pub fn post<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
130 where
131 F: Fn(Request) -> Fut + Send + Sync + 'static,
132 Fut: Future<Output = Response> + Send + 'static,
133 {
134 let async_handler: AsyncHandlerWithRequest = Arc::new(move |req| {
135 let fut = handler(req);
136 Box::pin(fut)
137 });
138
139 self.routes.push(Route {
140 method: Method::POST,
141 path: path.to_string(),
142 handler: RouteHandler::WithRequest(async_handler),
143 middleware: Vec::new(),
144 name: None,
145 });
146
147 self
148 }
149
150 pub fn put<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
152 where
153 F: Fn(u32, Request) -> Fut + Send + Sync + 'static,
154 Fut: Future<Output = Response> + Send + 'static,
155 {
156 let async_handler: AsyncHandlerWithIdAndRequest = Arc::new(move |id, req| {
157 let fut = handler(id, req);
158 Box::pin(fut)
159 });
160
161 self.routes.push(Route {
162 method: Method::PUT,
163 path: path.to_string(),
164 handler: RouteHandler::WithIdAndRequest(async_handler),
165 middleware: Vec::new(),
166 name: None,
167 });
168
169 self
170 }
171
172 pub fn patch<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
174 where
175 F: Fn(u32, Request) -> Fut + Send + Sync + 'static,
176 Fut: Future<Output = Response> + Send + 'static,
177 {
178 let async_handler: AsyncHandlerWithIdAndRequest = Arc::new(move |id, req| {
179 let fut = handler(id, req);
180 Box::pin(fut)
181 });
182
183 self.routes.push(Route {
184 method: Method::PATCH,
185 path: path.to_string(),
186 handler: RouteHandler::WithIdAndRequest(async_handler),
187 middleware: Vec::new(),
188 name: None,
189 });
190
191 self
192 }
193
194 pub fn delete<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
196 where
197 F: Fn(u32) -> Fut + Send + Sync + 'static,
198 Fut: Future<Output = Response> + Send + 'static,
199 {
200 let async_handler: AsyncHandlerWithId = Arc::new(move |id| {
201 let fut = handler(id);
202 Box::pin(fut)
203 });
204
205 self.routes.push(Route {
206 method: Method::DELETE,
207 path: path.to_string(),
208 handler: RouteHandler::WithId(async_handler),
209 middleware: Vec::new(),
210 name: None,
211 });
212
213 self
214 }
215
216 pub fn group<F>(&mut self, prefix: &str, group_fn: F) -> &mut Self
218 where
219 F: FnOnce(&mut RouteGroup),
220 {
221 let mut group = RouteGroup {
222 prefix: prefix.to_string(),
223 middleware: Vec::new(),
224 routes: Vec::new(),
225 };
226
227 group_fn(&mut group);
228 self.groups.push(group);
229
230 self
231 }
232
233 pub fn middleware(&mut self, middleware: Vec<String>) -> &mut Self {
235 self.middleware.extend(middleware);
236 self
237 }
238
239 pub fn name(&mut self, name: &str) -> &mut Self {
241 if let Some(route) = self.routes.last_mut() {
242 route.name = Some(name.to_string());
243 let index = self.routes.len() - 1;
244 self.named_routes.insert(name.to_string(), index);
245 }
246 self
247 }
248
249 pub fn find_route(&self, name: &str) -> Option<&Route> {
251 self.named_routes.get(name).map(|&idx| &self.routes[idx])
252 }
253
254 pub fn url(&self, name: &str, params: Option<HashMap<String, String>>) -> Result<String> {
256 if let Some(route) = self.find_route(name) {
257 let mut url = route.path.clone();
258
259 if let Some(params) = params {
260 for (key, value) in params {
261 url = url.replace(&format!(":{}", key), &value);
262 }
263 }
264
265 Ok(url)
266 } else {
267 Err(RustisanError::RoutingError(format!(
268 "Route '{}' not found",
269 name
270 )))
271 }
272 }
273
274 pub fn all_routes(&self) -> Vec<&Route> {
276 let mut all_routes = Vec::new();
277
278 all_routes.extend(self.routes.iter());
280
281 for group in &self.groups {
283 all_routes.extend(group.routes.iter());
284 }
285
286 all_routes
287 }
288
289 pub fn route_count(&self) -> usize {
291 let group_routes: usize = self.groups.iter().map(|g| g.routes.len()).sum();
292 self.routes.len() + group_routes
293 }
294}
295
296impl RouteGroup {
297 pub fn get<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
299 where
300 F: Fn() -> Fut + Send + Sync + 'static,
301 Fut: Future<Output = Response> + Send + 'static,
302 {
303 let async_handler: AsyncHandler = Arc::new(move || {
304 let fut = handler();
305 Box::pin(fut)
306 });
307
308 let full_path = format!("{}{}", self.prefix, path);
309
310 self.routes.push(Route {
311 method: Method::GET,
312 path: full_path,
313 handler: RouteHandler::Simple(async_handler),
314 middleware: self.middleware.clone(),
315 name: None,
316 });
317
318 self
319 }
320
321 pub fn get_with_id<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
323 where
324 F: Fn(u32) -> Fut + Send + Sync + 'static,
325 Fut: Future<Output = Response> + Send + 'static,
326 {
327 let async_handler: AsyncHandlerWithId = Arc::new(move |id| {
328 let fut = handler(id);
329 Box::pin(fut)
330 });
331
332 let full_path = format!("{}{}", self.prefix, path);
333
334 self.routes.push(Route {
335 method: Method::GET,
336 path: full_path,
337 handler: RouteHandler::WithId(async_handler),
338 middleware: self.middleware.clone(),
339 name: None,
340 });
341
342 self
343 }
344
345 pub fn post<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
347 where
348 F: Fn(Request) -> Fut + Send + Sync + 'static,
349 Fut: Future<Output = Response> + Send + 'static,
350 {
351 let async_handler: AsyncHandlerWithRequest = Arc::new(move |req| {
352 let fut = handler(req);
353 Box::pin(fut)
354 });
355
356 let full_path = format!("{}{}", self.prefix, path);
357
358 self.routes.push(Route {
359 method: Method::POST,
360 path: full_path,
361 handler: RouteHandler::WithRequest(async_handler),
362 middleware: self.middleware.clone(),
363 name: None,
364 });
365
366 self
367 }
368
369 pub fn put<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
371 where
372 F: Fn(u32, Request) -> Fut + Send + Sync + 'static,
373 Fut: Future<Output = Response> + Send + 'static,
374 {
375 let async_handler: AsyncHandlerWithIdAndRequest = Arc::new(move |id, req| {
376 let fut = handler(id, req);
377 Box::pin(fut)
378 });
379
380 let full_path = format!("{}{}", self.prefix, path);
381
382 self.routes.push(Route {
383 method: Method::PUT,
384 path: full_path,
385 handler: RouteHandler::WithIdAndRequest(async_handler),
386 middleware: self.middleware.clone(),
387 name: None,
388 });
389
390 self
391 }
392
393 pub fn delete<F, Fut>(&mut self, path: &str, handler: F) -> &mut Self
395 where
396 F: Fn(u32) -> Fut + Send + Sync + 'static,
397 Fut: Future<Output = Response> + Send + 'static,
398 {
399 let async_handler: AsyncHandlerWithId = Arc::new(move |id| {
400 let fut = handler(id);
401 Box::pin(fut)
402 });
403
404 let full_path = format!("{}{}", self.prefix, path);
405
406 self.routes.push(Route {
407 method: Method::DELETE,
408 path: full_path,
409 handler: RouteHandler::WithId(async_handler),
410 middleware: self.middleware.clone(),
411 name: None,
412 });
413
414 self
415 }
416
417 pub fn middleware(&mut self, middleware: Vec<String>) -> &mut Self {
419 self.middleware.extend(middleware);
420 self
421 }
422}
423
424impl Default for Router {
425 fn default() -> Self {
426 Self::new()
427 }
428}
429
430impl fmt::Debug for Route {
431 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432 f.debug_struct("Route")
433 .field("method", &self.method)
434 .field("path", &self.path)
435 .field("middleware", &self.middleware)
436 .field("name", &self.name)
437 .finish()
438 }
439}
440
441impl fmt::Debug for RouteHandler {
442 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443 match self {
444 RouteHandler::Simple(_) => write!(f, "Simple"),
445 RouteHandler::WithRequest(_) => write!(f, "WithRequest"),
446 RouteHandler::WithId(_) => write!(f, "WithId"),
447 RouteHandler::WithIdAndRequest(_) => write!(f, "WithIdAndRequest"),
448 }
449 }
450}
451
452pub fn create_success_response(data: Value) -> Result<Response> {
454 Response::success(data, None)
455}
456
457pub fn create_error_response(message: &str) -> Result<Response> {
459 Response::bad_request(message)
460}
461
462pub fn create_json_response(data: Value) -> Result<Response> {
464 Response::json(data)
465}
466
467pub fn create_response_with_status(status: StatusCode, data: Value) -> Result<Response> {
469 Ok(Response::new(status, data))
470}
471
472#[macro_export]
474macro_rules! routes {
475 ($router:expr, {
476 $($method:ident $path:literal => $handler:expr),* $(,)?
477 }) => {
478 $(
479 $router.$method($path, $handler);
480 )*
481 };
482}
483
484#[macro_export]
486macro_rules! route_group {
487 ($router:expr, $prefix:literal, {
488 $($method:ident $path:literal => $handler:expr),* $(,)?
489 }) => {
490 $router.group($prefix, |group| {
491 $(
492 group.$method($path, $handler);
493 )*
494 });
495 };
496}
497
498#[cfg(test)]
499mod tests {
500 use super::*;
501
502 #[tokio::test]
503 async fn test_router_creation() {
504 let router = Router::new();
505 assert!(router.routes.is_empty());
506 assert!(router.groups.is_empty());
507 assert_eq!(router.route_count(), 0);
508 }
509
510 #[tokio::test]
511 async fn test_add_get_route() {
512 let mut router = Router::new();
513 router.get("/test", || async {
514 Response::ok("Hello").unwrap()
515 });
516
517 assert_eq!(router.routes.len(), 1);
518 assert_eq!(router.routes[0].method, Method::GET);
519 assert_eq!(router.routes[0].path, "/test");
520 }
521
522 #[tokio::test]
523 async fn test_route_group() {
524 let mut router = Router::new();
525 router.group("/api", |group| {
526 group.get("/users", || async {
527 Response::ok("Users").unwrap()
528 });
529 });
530
531 assert_eq!(router.groups.len(), 1);
532 assert_eq!(router.groups[0].prefix, "/api");
533 assert_eq!(router.groups[0].routes.len(), 1);
534 assert_eq!(router.groups[0].routes[0].path, "/api/users");
535 }
536
537 #[tokio::test]
538 async fn test_named_routes() {
539 let mut router = Router::new();
540 router
541 .get("/users", || async {
542 Response::ok("Users").unwrap()
543 })
544 .name("users.index");
545
546 assert!(router.find_route("users.index").is_some());
547
548 let url = router.url("users.index", None).unwrap();
549 assert_eq!(url, "/users");
550 }
551
552 #[tokio::test]
553 async fn test_route_with_parameters() {
554 let mut router = Router::new();
555 router
556 .get("/users/:id", || async {
557 Response::ok("User").unwrap()
558 })
559 .name("users.show");
560
561 let mut params = HashMap::new();
562 params.insert("id".to_string(), "123".to_string());
563
564 let url = router.url("users.show", Some(params)).unwrap();
565 assert_eq!(url, "/users/123");
566 }
567
568 #[test]
569 fn test_helper_functions() {
570 let response = create_success_response(json!({"message": "test"}));
571 assert!(response.is_ok());
572
573 let response = create_error_response("error message");
574 assert!(response.is_ok());
575
576 let response = create_json_response(json!({"data": "test"}));
577 assert!(response.is_ok());
578 }
579
580 #[test]
581 fn test_route_count() {
582 let mut router = Router::new();
583
584 router.get("/", || async {
585 Response::ok("Home").unwrap()
586 });
587
588 router.group("/api", |group| {
589 group.get("/users", || async {
590 Response::ok("Users").unwrap()
591 });
592 group.get("/posts", || async {
593 Response::ok("Posts").unwrap()
594 });
595 });
596
597 assert_eq!(router.route_count(), 3);
598 }
599}