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