api_gateway/middleware/
common.rs1use axum::extract::Request;
2
3pub fn resolve_path(req: &Request, matched_path: &str) -> String {
4 req.extensions()
5 .get::<axum::extract::NestedPath>()
6 .and_then(|np| strip_path_prefix(matched_path, np.as_str()))
7 .unwrap_or_else(|| matched_path.to_owned())
8}
9
10fn strip_path_prefix(path: &str, prefix: &str) -> Option<String> {
15 let rest = path.strip_prefix(prefix)?;
16 if rest.is_empty() {
17 Some("/".to_owned())
19 } else if rest.starts_with('/') {
20 Some(rest.to_owned())
22 } else {
23 None
25 }
26}
27
28#[cfg(test)]
29#[cfg_attr(coverage_nightly, coverage(off))]
30mod tests {
31 use super::*;
32
33 #[test]
34 fn exact_match_returns_root() {
35 assert_eq!(strip_path_prefix("/cf", "/cf"), Some("/".to_owned()));
36 }
37
38 #[test]
39 fn segment_boundary_strips_correctly() {
40 assert_eq!(
41 strip_path_prefix("/cf/users", "/cf"),
42 Some("/users".to_owned())
43 );
44 }
45
46 #[test]
47 fn partial_segment_overlap_rejected() {
48 assert_eq!(strip_path_prefix("/cfish", "/cf"), None);
49 }
50
51 #[test]
52 fn no_prefix_match_returns_none() {
53 assert_eq!(strip_path_prefix("/other/path", "/cf"), None);
54 }
55
56 #[test]
57 fn nested_prefix_strips_correctly() {
58 assert_eq!(
59 strip_path_prefix("/api/v1/users", "/api/v1"),
60 Some("/users".to_owned())
61 );
62 }
63
64 #[test]
65 fn path_with_params_strips_correctly() {
66 assert_eq!(
67 strip_path_prefix("/cf/users/{id}", "/cf"),
68 Some("/users/{id}".to_owned())
69 );
70 }
71
72 #[test]
73 fn empty_prefix_returns_full_path() {
74 assert_eq!(strip_path_prefix("/users", ""), Some("/users".to_owned()));
75 }
76}