1extern crate alloc;
2
3use alloc::boxed::Box;
4use alloc::string::{String, ToString};
5use alloc::vec;
6use alloc::vec::Vec;
7
8use crate::method::Method;
9use crate::request::Request;
10use crate::response::Response;
11use crate::uri::path::Path;
12
13type RequestHandler<'a> = Box<dyn FnMut(Request, Vec<String>) -> Response + 'a>;
14
15#[derive(Debug, Clone)]
16pub struct HttpRoute {
17 pub method: Method,
18 pub path: Path,
19}
20
21pub struct HttpRouter<'a> {
22 routes: Vec<(HttpRoute, RequestHandler<'a>)>,
23 not_found_handler: RequestHandler<'a>,
24}
25
26impl<'a> HttpRouter<'a> {
27 pub fn new(not_found_handler: RequestHandler<'a>) -> Self {
28 Self {
29 routes: vec![],
30 not_found_handler,
31 }
32 }
33
34 pub fn add_route(&mut self, route: HttpRoute, handler: RequestHandler<'a>) {
35 self.routes.push((route, handler));
36 }
37
38 pub fn handle_request(&mut self, request: Request) -> Response {
39 let request_path = match &request.uri.path {
40 Some(path) => path.clone(),
41 None => Path { segments: vec![] },
42 };
43
44 for (route, handler) in self.routes.iter_mut() {
45 if route.method == request.method {
46 if route.path.segments.len() != request_path.segments.len() {
47 continue;
48 }
49
50 let mut variables = vec![];
51 let mut matched = true;
52
53 for (i, route_segment) in route.path.segments.iter().enumerate() {
54 let request_segment = request_path.segments.iter().nth(i).unwrap();
55
56 if *route_segment == "{}".to_string() {
57 variables.push(request_segment.clone());
58 } else if *route_segment == *request_segment {
59 continue;
60 } else {
61 matched = false;
62 break;
63 }
64 }
65
66 if matched {
67 return handler(request, variables);
68 }
69 }
70 }
71
72 (self.not_found_handler)(request, vec![])
73 }
74}