ferron/util/
match_location.rs1pub fn match_location(path: &str, req_path: &str) -> bool {
2 let mut path_without_trailing_slashes = path;
3 while path_without_trailing_slashes.ends_with("/") {
4 path_without_trailing_slashes =
5 &path_without_trailing_slashes[..(path_without_trailing_slashes.len() - 1)];
6 }
7
8 let mut path_prepared = path_without_trailing_slashes.to_owned();
9 let mut req_path_prepared = req_path.to_owned();
10
11 while path_prepared.contains("//") {
12 path_prepared = path_prepared.replace("//", "/");
13 }
14
15 while req_path_prepared.contains("//") {
16 req_path_prepared = path_prepared.replace("//", "/");
17 }
18
19 if cfg!(windows) {
20 path_prepared = path_prepared.to_lowercase();
21 req_path_prepared = req_path_prepared.to_lowercase();
22 }
23
24 path_prepared == req_path_prepared
25 || req_path_prepared.starts_with(&format!("{}/", path_prepared))
26}
27
28#[cfg(test)]
29mod tests {
30 use super::match_location;
31
32 #[test]
33 fn test_exact_match() {
34 assert!(match_location("/home", "/home"));
35 assert!(match_location("/api/v1", "/api/v1"));
36 }
37
38 #[test]
39 fn test_trailing_slash() {
40 assert!(match_location("/home/", "/home"));
41 assert!(match_location("/home", "/home/"));
42 assert!(match_location("/api/v1/", "/api/v1"));
43 }
44
45 #[test]
46 fn test_subpath_match() {
47 assert!(match_location("/api", "/api/v1"));
48 assert!(match_location("/users", "/users/profile"));
49 }
50
51 #[test]
52 fn test_non_matching_paths() {
53 assert!(!match_location("/home", "/dashboard"));
54 assert!(!match_location("/api", "/user"));
55 }
56
57 #[test]
58 fn test_multiple_slashes() {
59 assert!(match_location("/api//v1", "/api/v1"));
60 assert!(match_location("//home///", "/home"));
61 }
62
63 #[test]
64 fn test_case_insensitivity_on_windows() {
65 #[cfg(windows)]
66 {
67 assert!(match_location("/API", "/api"));
68 assert!(match_location("/Home", "/home"));
69 }
70 }
71}