1use crate::error::{Error, Result};
4use crate::handler::DynHandler;
5use crate::openapi::{RouteInfo, RouteKind};
6use crate::request::Params;
7
8#[derive(Default)]
10pub struct Router {
11 get: matchit::Router<DynHandler>,
12 post: matchit::Router<DynHandler>,
13 put: matchit::Router<DynHandler>,
14 delete: matchit::Router<DynHandler>,
15 patch: matchit::Router<DynHandler>,
16 registered: Vec<RouteInfo>,
17}
18
19impl Router {
20 pub fn new() -> Self {
21 Self::default()
22 }
23
24 pub fn insert(&mut self, method: &str, path: &str, handler: DynHandler) -> Result<()> {
25 self.insert_as(RouteKind::Http, method, path, handler)
26 }
27
28 pub(crate) fn insert_as(
29 &mut self,
30 kind: RouteKind,
31 method: &str,
32 path: &str,
33 handler: DynHandler,
34 ) -> Result<()> {
35 let method = method.to_uppercase();
36 let router = match method.as_str() {
37 "GET" => &mut self.get,
38 "POST" => &mut self.post,
39 "PUT" => &mut self.put,
40 "DELETE" => &mut self.delete,
41 "PATCH" => &mut self.patch,
42 _ => {
43 return Err(Error::bad_request(format!(
44 "Unsupported method: {}",
45 method
46 )))
47 }
48 };
49
50 router
51 .insert(path, handler)
52 .map_err(|e| Error::internal(format!("Failed to insert route: {}", e)))?;
53
54 self.registered.push(RouteInfo {
55 method,
56 path: path.to_string(),
57 kind,
58 });
59 Ok(())
60 }
61
62 pub(crate) fn registered(&self) -> &[RouteInfo] {
63 &self.registered
64 }
65
66 pub fn match_route(&self, method: &str, path: &str) -> Result<(DynHandler, Params)> {
67 let router = match method.to_uppercase().as_str() {
68 "GET" => &self.get,
69 "POST" => &self.post,
70 "PUT" => &self.put,
71 "DELETE" => &self.delete,
72 "PATCH" => &self.patch,
73 _ => return Err(Error::not_found("Route not found")),
74 };
75
76 let matched = router
77 .at(path)
78 .map_err(|_| Error::not_found("Route not found"))?;
79
80 let mut params = Params::new();
81 for (key, value) in matched.params.iter() {
82 params.insert(key.to_string(), value.to_string());
83 }
84
85 Ok((matched.value.clone(), params))
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use crate::handler::Handler;
93 use crate::request::Request;
94 use crate::response::Response;
95 use std::sync::Arc;
96
97 struct TestHandler;
98
99 #[async_trait::async_trait]
100 impl Handler for TestHandler {
101 async fn call(&self, _req: Request) -> Result<Response> {
102 Ok(Response::text("test"))
103 }
104 }
105
106 #[test]
107 fn test_router_insert_and_match() {
108 let mut router = Router::new();
109 let handler = Arc::new(TestHandler) as DynHandler;
110
111 router
112 .insert("GET", "/hello/{name}", handler.clone())
113 .unwrap();
114
115 let (_, params) = router.match_route("GET", "/hello/world").unwrap();
116 assert_eq!(params.get("name").unwrap(), "world");
117 }
118
119 #[test]
120 fn test_router_not_found() {
121 let router = Router::new();
122 assert!(router.match_route("GET", "/not-found").is_err());
123 }
124}