mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
add method to extract matched resource name (#1577)
Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
parent
487f90be5b
commit
23c8191cca
@ -7,6 +7,7 @@
|
||||
* Re-export `actix_rt::main` as `actix_web::main`.
|
||||
* `HttpRequest::match_pattern` and `ServiceRequest::match_pattern` for extracting the matched
|
||||
resource pattern.
|
||||
* `HttpRequest::match_name` and `ServiceRequest::match_name` for extracting matched resource name.
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -137,6 +137,14 @@ impl HttpRequest {
|
||||
self.0.rmap.match_pattern(self.path())
|
||||
}
|
||||
|
||||
/// 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]
|
||||
pub fn match_name(&self) -> Option<&str> {
|
||||
self.0.rmap.match_name(self.path())
|
||||
}
|
||||
|
||||
/// Request extensions
|
||||
#[inline]
|
||||
pub fn extensions(&self) -> Ref<'_, Extensions> {
|
||||
@ -462,6 +470,24 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_match_name() {
|
||||
let mut rdef = ResourceDef::new("/index.html");
|
||||
*rdef.name_mut() = "index".to_string();
|
||||
|
||||
let mut rmap = ResourceMap::new(ResourceDef::new(""));
|
||||
rmap.add(&mut rdef, None);
|
||||
|
||||
assert!(rmap.has_resource("/index.html"));
|
||||
|
||||
let req = TestRequest::default()
|
||||
.uri("/index.html")
|
||||
.rmap(rmap)
|
||||
.to_http_request();
|
||||
|
||||
assert_eq!(req.match_name(), Some("index"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_url_for_external() {
|
||||
let mut rdef = ResourceDef::new("https://youtube.com/watch/{video_id}");
|
||||
|
65
src/rmap.rs
65
src/rmap.rs
@ -93,6 +93,27 @@ impl ResourceMap {
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns the name of the route that matches the given path or None if no full match
|
||||
/// is possible.
|
||||
pub fn match_name(&self, path: &str) -> Option<&str> {
|
||||
let path = if path.is_empty() { "/" } else { path };
|
||||
|
||||
for (pattern, rmap) in &self.patterns {
|
||||
if let Some(ref rmap) = rmap {
|
||||
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),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns the full resource pattern matched against a path or None if no full match
|
||||
/// is possible.
|
||||
pub fn match_pattern(&self, path: &str) -> Option<String> {
|
||||
@ -302,4 +323,48 @@ mod tests {
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +196,12 @@ impl ServiceRequest {
|
||||
self.0.match_info()
|
||||
}
|
||||
|
||||
/// Counterpart to [`HttpRequest::match_name`](../struct.HttpRequest.html#method.match_name).
|
||||
#[inline]
|
||||
pub fn match_name(&self) -> Option<&str> {
|
||||
self.0.match_name()
|
||||
}
|
||||
|
||||
/// Counterpart to [`HttpRequest::match_pattern`](../struct.HttpRequest.html#method.match_pattern).
|
||||
#[inline]
|
||||
pub fn match_pattern(&self) -> Option<String> {
|
||||
|
Loading…
Reference in New Issue
Block a user