1use crate::http::{Request, Response};
2use crate::middleware::{into_boxed, BoxedMiddleware, Middleware};
3use matchit::Router as MatchitRouter;
4use std::collections::HashMap;
5use std::future::Future;
6use std::pin::Pin;
7use std::sync::{Arc, OnceLock, RwLock};
8
9static ROUTE_REGISTRY: OnceLock<RwLock<HashMap<String, String>>> = OnceLock::new();
11
12fn register_route_name(name: &str, path: &str) {
14 let registry = ROUTE_REGISTRY.get_or_init(|| RwLock::new(HashMap::new()));
15 if let Ok(mut map) = registry.write() {
16 map.insert(name.to_string(), path.to_string());
17 }
18}
19
20pub fn route(name: &str, params: &[(&str, &str)]) -> Option<String> {
36 let registry = ROUTE_REGISTRY.get()?.read().ok()?;
37 let path_pattern = registry.get(name)?;
38
39 let mut url = path_pattern.clone();
40 for (key, value) in params {
41 url = url.replace(&format!("{{{}}}", key), value);
42 }
43 Some(url)
44}
45
46pub fn route_with_params(name: &str, params: &HashMap<String, String>) -> Option<String> {
48 let registry = ROUTE_REGISTRY.get()?.read().ok()?;
49 let path_pattern = registry.get(name)?;
50
51 let mut url = path_pattern.clone();
52 for (key, value) in params {
53 url = url.replace(&format!("{{{}}}", key), value);
54 }
55 Some(url)
56}
57
58#[derive(Clone, Copy)]
60enum Method {
61 Get,
62 Post,
63 Put,
64 Delete,
65}
66
67pub type BoxedHandler = Box<
69 dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync,
70>;
71
72pub struct Router {
74 get_routes: MatchitRouter<Arc<BoxedHandler>>,
75 post_routes: MatchitRouter<Arc<BoxedHandler>>,
76 put_routes: MatchitRouter<Arc<BoxedHandler>>,
77 delete_routes: MatchitRouter<Arc<BoxedHandler>>,
78 route_middleware: HashMap<String, Vec<BoxedMiddleware>>,
80}
81
82impl Router {
83 pub fn new() -> Self {
84 Self {
85 get_routes: MatchitRouter::new(),
86 post_routes: MatchitRouter::new(),
87 put_routes: MatchitRouter::new(),
88 delete_routes: MatchitRouter::new(),
89 route_middleware: HashMap::new(),
90 }
91 }
92
93 pub fn get_route_middleware(&self, path: &str) -> Vec<BoxedMiddleware> {
95 self.route_middleware.get(path).cloned().unwrap_or_default()
96 }
97
98 pub(crate) fn add_middleware(&mut self, path: &str, middleware: BoxedMiddleware) {
100 self.route_middleware
101 .entry(path.to_string())
102 .or_default()
103 .push(middleware);
104 }
105
106 pub(crate) fn insert_get(&mut self, path: &str, handler: Arc<BoxedHandler>) {
108 self.get_routes.insert(path, handler).ok();
109 }
110
111 pub(crate) fn insert_post(&mut self, path: &str, handler: Arc<BoxedHandler>) {
113 self.post_routes.insert(path, handler).ok();
114 }
115
116 pub(crate) fn insert_put(&mut self, path: &str, handler: Arc<BoxedHandler>) {
118 self.put_routes.insert(path, handler).ok();
119 }
120
121 pub(crate) fn insert_delete(&mut self, path: &str, handler: Arc<BoxedHandler>) {
123 self.delete_routes.insert(path, handler).ok();
124 }
125
126 pub fn get<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
128 where
129 H: Fn(Request) -> Fut + Send + Sync + 'static,
130 Fut: Future<Output = Response> + Send + 'static,
131 {
132 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
133 self.get_routes.insert(path, Arc::new(handler)).ok();
134 RouteBuilder {
135 router: self,
136 last_path: path.to_string(),
137 _last_method: Method::Get,
138 }
139 }
140
141 pub fn post<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
143 where
144 H: Fn(Request) -> Fut + Send + Sync + 'static,
145 Fut: Future<Output = Response> + Send + 'static,
146 {
147 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
148 self.post_routes.insert(path, Arc::new(handler)).ok();
149 RouteBuilder {
150 router: self,
151 last_path: path.to_string(),
152 _last_method: Method::Post,
153 }
154 }
155
156 pub fn put<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
158 where
159 H: Fn(Request) -> Fut + Send + Sync + 'static,
160 Fut: Future<Output = Response> + Send + 'static,
161 {
162 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
163 self.put_routes.insert(path, Arc::new(handler)).ok();
164 RouteBuilder {
165 router: self,
166 last_path: path.to_string(),
167 _last_method: Method::Put,
168 }
169 }
170
171 pub fn delete<H, Fut>(mut self, path: &str, handler: H) -> RouteBuilder
173 where
174 H: Fn(Request) -> Fut + Send + Sync + 'static,
175 Fut: Future<Output = Response> + Send + 'static,
176 {
177 let handler: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
178 self.delete_routes.insert(path, Arc::new(handler)).ok();
179 RouteBuilder {
180 router: self,
181 last_path: path.to_string(),
182 _last_method: Method::Delete,
183 }
184 }
185
186 pub fn match_route(
188 &self,
189 method: &hyper::Method,
190 path: &str,
191 ) -> Option<(Arc<BoxedHandler>, HashMap<String, String>)> {
192 let router = match *method {
193 hyper::Method::GET => &self.get_routes,
194 hyper::Method::POST => &self.post_routes,
195 hyper::Method::PUT => &self.put_routes,
196 hyper::Method::DELETE => &self.delete_routes,
197 _ => return None,
198 };
199
200 router.at(path).ok().map(|matched| {
201 let params: HashMap<String, String> = matched
202 .params
203 .iter()
204 .map(|(k, v)| (k.to_string(), v.to_string()))
205 .collect();
206 (matched.value.clone(), params)
207 })
208 }
209}
210
211impl Default for Router {
212 fn default() -> Self {
213 Self::new()
214 }
215}
216
217pub struct RouteBuilder {
219 pub(crate) router: Router,
220 last_path: String,
221 #[allow(dead_code)]
222 _last_method: Method,
223}
224
225impl RouteBuilder {
226 pub fn name(self, name: &str) -> Router {
228 register_route_name(name, &self.last_path);
229 self.router
230 }
231
232 pub fn middleware<M: Middleware + 'static>(mut self, middleware: M) -> RouteBuilder {
242 self.router
243 .add_middleware(&self.last_path, into_boxed(middleware));
244 self
245 }
246
247 pub fn get<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
249 where
250 H: Fn(Request) -> Fut + Send + Sync + 'static,
251 Fut: Future<Output = Response> + Send + 'static,
252 {
253 self.router.get(path, handler)
254 }
255
256 pub fn post<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
258 where
259 H: Fn(Request) -> Fut + Send + Sync + 'static,
260 Fut: Future<Output = Response> + Send + 'static,
261 {
262 self.router.post(path, handler)
263 }
264
265 pub fn put<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
267 where
268 H: Fn(Request) -> Fut + Send + Sync + 'static,
269 Fut: Future<Output = Response> + Send + 'static,
270 {
271 self.router.put(path, handler)
272 }
273
274 pub fn delete<H, Fut>(self, path: &str, handler: H) -> RouteBuilder
276 where
277 H: Fn(Request) -> Fut + Send + Sync + 'static,
278 Fut: Future<Output = Response> + Send + 'static,
279 {
280 self.router.delete(path, handler)
281 }
282}
283
284impl From<RouteBuilder> for Router {
285 fn from(builder: RouteBuilder) -> Self {
286 builder.router
287 }
288}