find nested resource names

This commit is contained in:
Rob Ede 2020-06-26 19:59:40 +01:00
parent 1e8e4549e7
commit b9ec5d8914
No known key found for this signature in database
GPG Key ID: C2A3B36E841A91E6
3 changed files with 63 additions and 9 deletions

View File

@ -137,9 +137,11 @@ impl HttpRequest {
self.0.rmap.match_pattern(self.path()) self.0.rmap.match_pattern(self.path())
} }
/// Checks if a given path matches a route /// The resource name that matched the path. Useful for logging and metrics.
///
/// Returns a None when no resource is fully matched, including default services.
#[inline] #[inline]
pub fn match_name(&self) -> Option<String> { pub fn match_name(&self) -> Option<&str> {
self.0.rmap.match_name(self.path()) self.0.rmap.match_name(self.path())
} }

View File

@ -92,14 +92,22 @@ impl ResourceMap {
} }
false false
} }
/// Returns the name of the route that matches the given path or None if no match is
/// found. /// Returns the name of the route that matches the given path or None if no full match
pub fn match_name(&self, path: &str) -> Option<String> { /// is possible.
pub fn match_name(&self, path: &str) -> Option<&str> {
let path = if path.is_empty() { "/" } else { path }; let path = if path.is_empty() { "/" } else { path };
for (pattern, _) in &self.patterns { for (pattern, rmap) in &self.patterns {
if pattern.pattern() == path { if let Some(ref rmap) = rmap {
return Some(pattern.name().to_string()); if let Some(plen) = pattern.is_prefix_match(path) {
return rmap.match_name(&path[plen..]);
}
} else if pattern.is_match(path) {
return match pattern.name() {
"" => None,
s => Some(s),
};
} }
} }
@ -315,4 +323,48 @@ mod tests {
Some("/user/{id}/post/{post_id}/comment/{comment_id}".to_owned()) Some("/user/{id}/post/{post_id}/comment/{comment_id}".to_owned())
); );
} }
#[test]
fn extract_matched_name() {
let mut root = ResourceMap::new(ResourceDef::root_prefix(""));
let mut rdef = ResourceDef::new("/info");
*rdef.name_mut() = "root_info".to_owned();
root.add(&mut rdef, None);
let mut user_map = ResourceMap::new(ResourceDef::root_prefix(""));
let mut rdef = ResourceDef::new("/");
user_map.add(&mut rdef, None);
let mut rdef = ResourceDef::new("/post/{post_id}");
*rdef.name_mut() = "user_post".to_owned();
user_map.add(&mut rdef, None);
root.add(
&mut ResourceDef::root_prefix("/user/{id}"),
Some(Rc::new(user_map)),
);
let root = Rc::new(root);
root.finish(Rc::clone(&root));
// sanity check resource map setup
assert!(root.has_resource("/info"));
assert!(!root.has_resource("/bar"));
assert!(root.has_resource("/user/22"));
assert!(root.has_resource("/user/22/"));
assert!(root.has_resource("/user/22/post/55"));
// extract patterns from paths
assert!(root.match_name("/bar").is_none());
assert!(root.match_name("/v44").is_none());
assert_eq!(root.match_name("/info"), Some("root_info"));
assert_eq!(root.match_name("/user/22"), None);
assert_eq!(root.match_name("/user/22/"), None);
assert_eq!(root.match_name("/user/22/post/55"), Some("user_post"));
}
} }

View File

@ -198,7 +198,7 @@ impl ServiceRequest {
/// Counterpart to [`HttpRequest::match_name`](../struct.HttpRequest.html#method.match_name). /// Counterpart to [`HttpRequest::match_name`](../struct.HttpRequest.html#method.match_name).
#[inline] #[inline]
pub fn match_name(&self) -> Option<String> { pub fn match_name(&self) -> Option<&str> {
self.0.match_name() self.0.match_name()
} }