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 || req_path_prepared.starts_with(&format!("{path_prepared}/"))
25}
26
27#[cfg(test)]
28mod tests {
29 use super::match_location;
30
31 #[test]
32 fn test_exact_match() {
33 assert!(match_location("/home", "/home"));
34 assert!(match_location("/api/v1", "/api/v1"));
35 }
36
37 #[test]
38 fn test_trailing_slash() {
39 assert!(match_location("/home/", "/home"));
40 assert!(match_location("/home", "/home/"));
41 assert!(match_location("/api/v1/", "/api/v1"));
42 }
43
44 #[test]
45 fn test_subpath_match() {
46 assert!(match_location("/api", "/api/v1"));
47 assert!(match_location("/users", "/users/profile"));
48 }
49
50 #[test]
51 fn test_non_matching_paths() {
52 assert!(!match_location("/home", "/dashboard"));
53 assert!(!match_location("/api", "/user"));
54 }
55
56 #[test]
57 fn test_multiple_slashes() {
58 assert!(match_location("/api//v1", "/api/v1"));
59 assert!(match_location("//home///", "/home"));
60 }
61
62 #[test]
63 fn test_case_insensitivity_on_windows() {
64 #[cfg(windows)]
65 {
66 assert!(match_location("/API", "/api"));
67 assert!(match_location("/Home", "/home"));
68 }
69 }
70}