use super::HandleFn;
use crate::{request::HTTPMethod, Request};
use regex::Regex;
use std::{collections::HashMap, sync::Arc};
pub type MatchRoute = (String, Vec<String>, HandleFn);
pub struct MatchRouter {
pub get: Vec<MatchRoute>,
pub post: Vec<MatchRoute>,
}
pub fn match_route(request: &mut Request, router: Arc<MatchRouter>) -> Option<HandleFn> {
let route_list;
match request.method {
HTTPMethod::GET => route_list = &router.get,
HTTPMethod::POST => route_list = &router.post,
}
for route in route_list {
if let Some(map) = match_route_path(route.0.clone(), route.1.clone(), request.path.clone()) {
request.params_map = map;
return Some(route.2);
}
}
None
}
pub fn match_route_path(
re: String,
params: Vec<String>,
path: String,
) -> Option<HashMap<String, String>> {
let re = Regex::new(&re).unwrap();
let caps = re.captures(&path);
if let Some(caps) = caps {
let mut map = HashMap::<String, String>::new();
for (index, key) in params.iter().enumerate() {
if let Some(value) = caps.get(index + 1) {
map.insert(key.to_string(), value.as_str().to_string());
}
}
return Some(map);
}
None
}
#[test]
fn test_match_route_path() {
let params_map = match_route_path("^/aa$".to_string(), vec![], "/aa".to_string());
assert_ne!(params_map, None);
let params_map = match_route_path(
"^/aa/([^/]*?)$".to_string(),
vec!["bb".to_string()],
"/aa/11".to_string(),
);
assert_ne!(params_map, None);
let params_map = match_route_path(
"^/aa/([^/]*?)/cc$".to_string(),
vec!["bb".to_string()],
"/aa/11/cc".to_string(),
);
assert_ne!(params_map, None);
let params_map = match_route_path(
"^/aa/(.+)$".to_string(),
vec!["bb".to_string()],
"/aa/11/cc".to_string(),
);
assert_ne!(params_map, None);
}