ferron/util/
match_location.rs

1pub 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}