1use crate::extract::{ExtractError, FromRequest};
30use crate::handler::Handler;
31use crate::request::{Method, Request};
32use crate::response::{IntoResponse, Response, StatusCode};
33use std::collections::HashMap;
34
35#[derive(Debug, Clone)]
46pub struct Param<T>(pub T);
47
48#[derive(Debug, Clone, Default)]
61pub struct Params(pub HashMap<String, String>);
62
63impl Params {
64 pub fn get(&self, name: &str) -> Option<&str> {
66 self.0.get(name).map(|s| s.as_str())
67 }
68
69 pub fn get_parse<T: std::str::FromStr>(&self, name: &str) -> Option<T> {
71 self.0.get(name).and_then(|s| s.parse().ok())
72 }
73}
74
75std::thread_local! {
77 static CURRENT_PARAMS: std::cell::RefCell<HashMap<String, String>> = std::cell::RefCell::new(HashMap::new());
78}
79
80fn set_current_params(params: HashMap<String, String>) {
81 CURRENT_PARAMS.with(|p| {
82 *p.borrow_mut() = params;
83 });
84}
85
86fn get_current_params() -> HashMap<String, String> {
87 CURRENT_PARAMS.with(|p| p.borrow().clone())
88}
89
90impl FromRequest for Params {
91 type Error = ExtractError;
92
93 fn from_request(_req: &mut Request) -> Result<Self, Self::Error> {
94 Ok(Params(get_current_params()))
95 }
96}
97
98impl FromRequest for Param<String> {
99 type Error = ExtractError;
100
101 fn from_request(_req: &mut Request) -> Result<Self, Self::Error> {
102 let params = get_current_params();
103 params
105 .into_values()
106 .next()
107 .map(Param)
108 .ok_or_else(|| ExtractError::bad_request("No path parameter found"))
109 }
110}
111
112impl FromRequest for Param<i64> {
113 type Error = ExtractError;
114
115 fn from_request(_req: &mut Request) -> Result<Self, Self::Error> {
116 let params = get_current_params();
117 params
118 .into_values()
119 .next()
120 .ok_or_else(|| ExtractError::bad_request("No path parameter found"))?
121 .parse()
122 .map(Param)
123 .map_err(|_| ExtractError::bad_request("Invalid integer parameter"))
124 }
125}
126
127impl FromRequest for Param<u64> {
128 type Error = ExtractError;
129
130 fn from_request(_req: &mut Request) -> Result<Self, Self::Error> {
131 let params = get_current_params();
132 params
133 .into_values()
134 .next()
135 .ok_or_else(|| ExtractError::bad_request("No path parameter found"))?
136 .parse()
137 .map(Param)
138 .map_err(|_| ExtractError::bad_request("Invalid unsigned integer parameter"))
139 }
140}
141
142type BoxedHandler = Box<dyn Fn(&mut Request) -> Response>;
144
145#[derive(Clone)]
147struct RoutePattern {
148 segments: Vec<PatternSegment>,
149}
150
151#[derive(Clone)]
152enum PatternSegment {
153 Literal(String),
155 Param(String),
157 Wildcard,
159}
160
161impl RoutePattern {
162 fn parse(pattern: &str) -> Self {
163 let segments = pattern
164 .split('/')
165 .filter(|s| !s.is_empty())
166 .map(|s| {
167 if s == "*" {
168 PatternSegment::Wildcard
169 } else if let Some(name) = s.strip_prefix(':') {
170 PatternSegment::Param(name.to_string())
171 } else {
172 PatternSegment::Literal(s.to_string())
173 }
174 })
175 .collect();
176
177 RoutePattern { segments }
178 }
179
180 fn matches(&self, path: &str) -> Option<HashMap<String, String>> {
181 let path_segments: Vec<&str> = path.split('/').filter(|s| !s.is_empty()).collect();
182 let mut params = HashMap::new();
183 let mut path_idx = 0;
184
185 for (pattern_idx, segment) in self.segments.iter().enumerate() {
186 match segment {
187 PatternSegment::Literal(lit) => {
188 if path_idx >= path_segments.len() || path_segments[path_idx] != lit {
189 return None;
190 }
191 path_idx += 1;
192 }
193 PatternSegment::Param(name) => {
194 if path_idx >= path_segments.len() {
195 return None;
196 }
197 params.insert(name.clone(), path_segments[path_idx].to_string());
198 path_idx += 1;
199 }
200 PatternSegment::Wildcard => {
201 if pattern_idx == self.segments.len() - 1 {
203 return Some(params);
204 }
205 return None;
206 }
207 }
208 }
209
210 if path_idx == path_segments.len() {
212 Some(params)
213 } else {
214 None
215 }
216 }
217}
218
219struct Route {
221 method: Option<Method>, pattern: RoutePattern,
223 handler: BoxedHandler,
224}
225
226pub struct Router {
240 routes: Vec<Route>,
241 not_found_handler: Option<BoxedHandler>,
242 method_not_allowed_handler: Option<BoxedHandler>,
243}
244
245impl Default for Router {
246 fn default() -> Self {
247 Self::new()
248 }
249}
250
251impl Router {
252 pub fn new() -> Self {
254 Router {
255 routes: Vec::new(),
256 not_found_handler: None,
257 method_not_allowed_handler: None,
258 }
259 }
260
261 pub fn route<H, Args>(self, pattern: &str, handler: H) -> Self
263 where
264 H: Handler<Args> + 'static,
265 H::Output: IntoResponse,
266 {
267 self.add_route(None, pattern, handler)
268 }
269
270 pub fn get<H, Args>(self, pattern: &str, handler: H) -> Self
272 where
273 H: Handler<Args> + 'static,
274 H::Output: IntoResponse,
275 {
276 self.add_route(Some(Method::Get), pattern, handler)
277 }
278
279 pub fn post<H, Args>(self, pattern: &str, handler: H) -> Self
281 where
282 H: Handler<Args> + 'static,
283 H::Output: IntoResponse,
284 {
285 self.add_route(Some(Method::Post), pattern, handler)
286 }
287
288 pub fn put<H, Args>(self, pattern: &str, handler: H) -> Self
290 where
291 H: Handler<Args> + 'static,
292 H::Output: IntoResponse,
293 {
294 self.add_route(Some(Method::Put), pattern, handler)
295 }
296
297 pub fn delete<H, Args>(self, pattern: &str, handler: H) -> Self
299 where
300 H: Handler<Args> + 'static,
301 H::Output: IntoResponse,
302 {
303 self.add_route(Some(Method::Delete), pattern, handler)
304 }
305
306 pub fn patch<H, Args>(self, pattern: &str, handler: H) -> Self
308 where
309 H: Handler<Args> + 'static,
310 H::Output: IntoResponse,
311 {
312 self.add_route(Some(Method::Patch), pattern, handler)
313 }
314
315 pub fn head<H, Args>(self, pattern: &str, handler: H) -> Self
317 where
318 H: Handler<Args> + 'static,
319 H::Output: IntoResponse,
320 {
321 self.add_route(Some(Method::Head), pattern, handler)
322 }
323
324 pub fn options<H, Args>(self, pattern: &str, handler: H) -> Self
326 where
327 H: Handler<Args> + 'static,
328 H::Output: IntoResponse,
329 {
330 self.add_route(Some(Method::Options), pattern, handler)
331 }
332
333 pub fn not_found<H, Args>(mut self, handler: H) -> Self
335 where
336 H: Handler<Args> + 'static,
337 H::Output: IntoResponse,
338 {
339 let handler_cell = std::cell::RefCell::new(Some(handler));
340 self.not_found_handler = Some(Box::new(move |req| {
341 if let Some(h) = handler_cell.borrow_mut().take() {
342 h.call(req).into_response()
343 } else {
344 Response::new(StatusCode::INTERNAL_SERVER_ERROR)
345 .with_text("Handler already consumed")
346 }
347 }));
348 self
349 }
350
351 pub fn method_not_allowed<H, Args>(mut self, handler: H) -> Self
353 where
354 H: Handler<Args> + 'static,
355 H::Output: IntoResponse,
356 {
357 let handler_cell = std::cell::RefCell::new(Some(handler));
358 self.method_not_allowed_handler = Some(Box::new(move |req| {
359 if let Some(h) = handler_cell.borrow_mut().take() {
360 h.call(req).into_response()
361 } else {
362 Response::new(StatusCode::INTERNAL_SERVER_ERROR)
363 .with_text("Handler already consumed")
364 }
365 }));
366 self
367 }
368
369 pub fn nest(mut self, prefix: &str, nested: Router) -> Self {
383 let prefix = prefix.trim_end_matches('/');
384
385 for route in nested.routes {
386 let combined_pattern = if route.pattern.segments.is_empty() {
388 prefix.to_string()
389 } else {
390 let pattern_str: String = route
391 .pattern
392 .segments
393 .iter()
394 .map(|seg| match seg {
395 PatternSegment::Literal(s) => format!("/{}", s),
396 PatternSegment::Param(s) => format!("/:{}", s),
397 PatternSegment::Wildcard => "/*".to_string(),
398 })
399 .collect();
400 format!("{}{}", prefix, pattern_str)
401 };
402
403 self.routes.push(Route {
404 method: route.method,
405 pattern: RoutePattern::parse(&combined_pattern),
406 handler: route.handler,
407 });
408 }
409
410 self
411 }
412
413 fn add_route<H, Args>(mut self, method: Option<Method>, pattern: &str, handler: H) -> Self
414 where
415 H: Handler<Args> + 'static,
416 H::Output: IntoResponse,
417 {
418 let handler_cell = std::cell::RefCell::new(Some(handler));
422
423 let boxed: BoxedHandler = Box::new(move |req| {
424 if let Some(h) = handler_cell.borrow_mut().take() {
428 h.call(req).into_response()
429 } else {
430 Response::new(StatusCode::INTERNAL_SERVER_ERROR)
432 .with_text("Handler already consumed")
433 }
434 });
435
436 self.routes.push(Route {
437 method,
438 pattern: RoutePattern::parse(pattern),
439 handler: boxed,
440 });
441
442 self
443 }
444
445 pub fn handle(&self, req: &mut Request) -> Response {
447 let method = req.method();
448 let path = req.path().to_string();
449
450 let mut path_matched = false;
452
453 for route in &self.routes {
454 if let Some(params) = route.pattern.matches(&path) {
455 path_matched = true;
456
457 if let Some(route_method) = route.method {
459 if route_method != method {
460 continue;
461 }
462 }
463
464 set_current_params(params);
466
467 return (route.handler)(req);
469 }
470 }
471
472 if path_matched {
474 if let Some(ref handler) = self.method_not_allowed_handler {
476 return handler(req);
477 }
478 Response::new(StatusCode::METHOD_NOT_ALLOWED)
479 .with_text("Method Not Allowed")
480 } else {
481 if let Some(ref handler) = self.not_found_handler {
483 return handler(req);
484 }
485 Response::new(StatusCode::NOT_FOUND).with_text("Not Found")
486 }
487 }
488
489 pub fn run(self) {
504 let mut request = Request::new();
505 let method = request.method();
506 let path = request.path().to_string();
507 crate::log_info!("Handling request {} {}", method, path);
508 let response = self.handle(&mut request);
509 response.send();
510 }
511}