diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 6305b45c3..b51cccc6e 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,6 +2,14 @@ ## Unreleased +### Added + +- Add conflict path detection and handling to enhance routing performance. + +### Changed + +- Refactor capture_match_info_fn by splitting it into three distinct functions: capture_match_info(), resolve_path_if_match(), and resolve(). + ## 0.5.3 - Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. diff --git a/actix-router/src/de.rs b/actix-router/src/de.rs index 5eddfa33b..5ce3623ef 100644 --- a/actix-router/src/de.rs +++ b/actix-router/src/de.rs @@ -662,13 +662,13 @@ mod tests { let rdef = ResourceDef::new("/{key}"); let mut path = Path::new("/%25"); - rdef.resolve_path_if_matches(&mut path); + rdef.resolve_path_if_match(&mut path); let de = PathDeserializer::new(&path); let segment: String = serde::Deserialize::deserialize(de).unwrap(); assert_eq!(segment, "%"); let mut path = Path::new("/%2F"); - rdef.resolve_path_if_matches(&mut path); + rdef.resolve_path_if_match(&mut path); let de = PathDeserializer::new(&path); let segment: String = serde::Deserialize::deserialize(de).unwrap(); assert_eq!(segment, "/") @@ -679,7 +679,7 @@ mod tests { let rdef = ResourceDef::new("/{key}/{value}"); let mut path = Path::new("/%30%25/%30%2F"); - rdef.resolve_path_if_matches(&mut path); + rdef.resolve_path_if_match(&mut path); let de = PathDeserializer::new(&path); let segment: (String, String) = serde::Deserialize::deserialize(de).unwrap(); assert_eq!(segment.0, "0%"); @@ -697,7 +697,7 @@ mod tests { let rdef = ResourceDef::new("/{key}/{value}"); let mut path = Path::new("/%25/%2F"); - rdef.resolve_path_if_matches(&mut path); + rdef.resolve_path_if_match(&mut path); let de = PathDeserializer::new(&path); let vals: Vals = serde::Deserialize::deserialize(de).unwrap(); assert_eq!(vals.key, "%"); @@ -714,7 +714,7 @@ mod tests { let rdef = ResourceDef::new("/{val}"); let mut path = Path::new("/X"); - rdef.resolve_path_if_matches(&mut path); + rdef.resolve_path_if_match(&mut path); let de = PathDeserializer::new(&path); let params: Params<'_> = serde::Deserialize::deserialize(de).unwrap(); assert_eq!(params.val, "X"); @@ -723,7 +723,7 @@ mod tests { assert_eq!(params, "X"); let mut path = Path::new("/%2F"); - rdef.resolve_path_if_matches(&mut path); + rdef.resolve_path_if_match(&mut path); let de = PathDeserializer::new(&path); assert!( as serde::Deserialize>::deserialize(de).is_err()); let de = PathDeserializer::new(&path); diff --git a/actix-router/src/path.rs b/actix-router/src/path.rs index f18a102fe..2a7a76fc5 100644 --- a/actix-router/src/path.rs +++ b/actix-router/src/path.rs @@ -1,10 +1,12 @@ use std::{ borrow::Cow, + mem, ops::{DerefMut, Index}, }; use serde::{de, Deserialize}; +use crate::resource::ResourceMatchInfo; use crate::{de::PathDeserializer, Resource, ResourcePath}; #[derive(Debug, Clone)] @@ -106,6 +108,27 @@ impl Path { self.skip += n; } + /// Post-processes the path to resolve dynamic segments, if any, and determines the character offset to skip. + pub fn resolve(&mut self, match_info: ResourceMatchInfo<'_>) { + match match_info { + ResourceMatchInfo::Static { matched_len } => { + self.resource_path().skip(matched_len); + } + ResourceMatchInfo::Dynamic { + matched_len, + matched_vars, + mut segments, + } => { + for i in 0..matched_vars.len() { + self.resource_path() + .add(matched_vars[i], mem::take(&mut segments[i])); + } + + self.resource_path().skip(matched_len); + } + } + } + pub(crate) fn add(&mut self, name: impl Into>, value: PathItem) { match value { PathItem::Static(seg) => self.segments.push((name.into(), PathItem::Static(seg))), @@ -260,4 +283,49 @@ mod tests { let foo = RefCell::new(foo); let _ = foo.borrow_mut().resource_path(); } + + #[test] + fn test_dynamic_path_resolve() { + let mut path = Path::new("/foo/{var1}/{var2}"); + + assert_eq!(0, path.segments.len()); + assert_eq!(0, path.skip); + + let mut segments = <[PathItem; 16]>::default(); + segments[0] = PathItem::Static(Cow::Borrowed("foo")); + segments[1] = PathItem::Segment(2, 5); + let match_info = ResourceMatchInfo::Dynamic { + matched_len: 3, + matched_vars: &["var1", "var2"], + segments, + }; + + path.resolve(match_info); + + assert_eq!(2, path.segments.len()); + assert_eq!(3, path.skip); + + let (name, value) = path.segments.get(0).unwrap(); + assert_eq!(name.as_ref(), "var1"); + assert!(matches!(value, PathItem::Static(Cow::Borrowed("foo")))); + + let (name, value) = path.segments.get(1).unwrap(); + assert_eq!(name.as_ref(), "var2"); + assert!(matches!(value, PathItem::Segment(2, 5))); + } + + #[test] + fn test_static_path_resolve() { + let mut path = Path::new("/foo"); + + assert_eq!(0, path.segments.len()); + assert_eq!(0, path.skip); + + let match_info = ResourceMatchInfo::Static { matched_len: 2 }; + + path.resolve(match_info); + + assert_eq!(0, path.segments.len()); + assert_eq!(2, path.skip); + } } diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index 9c49cc802..3bd01ed2a 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -79,8 +79,7 @@ const REGEX_FLAGS: &str = "(?s-m)"; /// `/rust-is-hard`. /// /// For information on capturing segment values from paths or other custom resource types, -/// see [`capture_match_info`][Self::capture_match_info] -/// and [`capture_match_info_fn`][Self::capture_match_info_fn]. +/// see [`capture_match_info`][Self::capture_match_info]. /// /// A resource definition can contain at most 16 dynamic segments. /// @@ -95,7 +94,7 @@ const REGEX_FLAGS: &str = "(?s-m)"; /// assert!(!resource.is_match("/user/")); /// /// let mut path = Path::new("/user/123"); -/// resource.resolve_path_if_matches(&mut path); +/// resource.resolve_path_if_match(&mut path); /// assert_eq!(path.get("id").unwrap(), "123"); /// ``` /// @@ -170,7 +169,7 @@ const REGEX_FLAGS: &str = "(?s-m)"; /// assert!(resource.is_match("/blob/HEAD/README.md")); /// /// let mut path = Path::new("/blob/main/LICENSE"); -/// resource.resolve_path_if_matches(&mut path); +/// resource.resolve_path_if_match(&mut path); /// assert_eq!(path.get("tail").unwrap(), "main/LICENSE"); /// ``` /// @@ -248,6 +247,7 @@ enum PatternType { DynamicSet(RegexSet, Vec<(Regex, Vec<&'static str>)>), } +/// Holds metadata and parameters used during path resolution. pub enum ResourceMatchInfo<'a> { Static { matched_len: u16, @@ -633,21 +633,21 @@ impl ResourceDef { /// /// let resource = ResourceDef::prefix("/user/{id}"); /// let mut path = Path::new("/user/123/stars"); - /// assert!(resource.resolve_path_if_matches(&mut path)); + /// assert!(resource.resolve_path_if_match(&mut path)); /// assert_eq!(path.get("id").unwrap(), "123"); /// assert_eq!(path.unprocessed(), "/stars"); /// /// let resource = ResourceDef::new("/blob/{path}*"); /// let mut path = Path::new("/blob/HEAD/Cargo.toml"); - /// assert!(resource.resolve_path_if_matches(&mut path)); + /// assert!(resource.resolve_path_if_match(&mut path)); /// assert_eq!(path.get("path").unwrap(), "HEAD/Cargo.toml"); /// assert_eq!(path.unprocessed(), ""); /// ``` - pub fn resolve_path_if_matches(&self, resource: &mut R) -> bool { + pub fn resolve_path_if_match(&self, resource: &mut R) -> bool { match self.capture_match_info(resource) { None => false, Some(match_info) => { - resource.resolve_path(match_info); + resource.resource_path().resolve(match_info); true } } @@ -660,21 +660,22 @@ impl ResourceDef { /// This is useful if you want to conditionally match on some non-path related aspect of the /// resource type. /// - /// Returns `true` if resource path matches this resource definition _and_ satisfies the - /// given check function. - /// + /// Returns `ResourceMatchInfo` if the given resource path matches this resource definition, + /// containing the information required to perform path resolution. /// # Examples /// ``` - /// use actix_router::{Path, ResourceDef}; + /// use actix_router::{Path, Resource, ResourceDef}; /// /// fn try_match(resource: &ResourceDef, path: &mut Path<&str>) -> bool { - /// let admin_allowed = std::env::var("ADMIN_ALLOWED").is_ok(); /// - /// resource.capture_match_info_fn( - /// path, - /// // when env var is not set, reject when path contains "admin" - /// |path| !(!admin_allowed && path.as_str().contains("admin")), - /// ) + /// let match_info = resource.capture_match_info(path); + /// match match_info{ + /// None => {false} + /// Some(match_info) => { + /// path.resource_path().resolve(match_info); + /// true + /// } + /// } /// } /// /// let resource = ResourceDef::prefix("/user/{id}"); @@ -685,10 +686,6 @@ impl ResourceDef { /// assert_eq!(path.get("id").unwrap(), "james"); /// assert_eq!(path.unprocessed(), "/stars"); /// - /// // path matches but fails check function; no segments are collected - /// let mut path = Path::new("/user/admin/stars"); - /// assert!(!try_match(&resource, &mut path)); - /// assert_eq!(path.unprocessed(), "/user/admin/stars"); /// ``` pub fn capture_match_info(&self, resource: &mut R) -> Option> where @@ -1179,7 +1176,7 @@ mod tests { assert!(!re.is_match("/name~")); let mut path = Path::new("/name"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.unprocessed(), ""); assert_eq!(re.find_match("/name"), Some(5)); @@ -1197,7 +1194,7 @@ mod tests { assert!(!re.is_match("/user/profile/profile")); let mut path = Path::new("/user/profile"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.unprocessed(), ""); } @@ -1210,12 +1207,12 @@ mod tests { assert!(!re.is_match("/user/2345/sdg")); let mut path = Path::new("/user/profile"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "profile"); assert_eq!(path.unprocessed(), ""); let mut path = Path::new("/user/1245125"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "1245125"); assert_eq!(path.unprocessed(), ""); @@ -1225,7 +1222,7 @@ mod tests { assert!(!re.is_match("/resource")); let mut path = Path::new("/v151/resource/adage32"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("version").unwrap(), "151"); assert_eq!(path.get("id").unwrap(), "adage32"); assert_eq!(path.unprocessed(), ""); @@ -1237,7 +1234,7 @@ mod tests { assert!(!re.is_match("/XXXXXX")); let mut path = Path::new("/012345"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "012345"); assert_eq!(path.unprocessed(), ""); } @@ -1257,12 +1254,12 @@ mod tests { assert!(!re.is_match("/user/2345/sdg")); let mut path = Path::new("/user/profile"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "profile"); assert_eq!(path.unprocessed(), ""); let mut path = Path::new("/user/1245125"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "1245125"); assert_eq!(path.unprocessed(), ""); @@ -1271,7 +1268,7 @@ mod tests { assert!(!re.is_match("/resource")); let mut path = Path::new("/v151/resource/adage32"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("version").unwrap(), "151"); assert_eq!(path.get("id").unwrap(), "adage32"); @@ -1285,7 +1282,7 @@ mod tests { assert!(!re.is_match("/static/a")); let mut path = Path::new("/012345"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "012345"); let re = ResourceDef::new([ @@ -1322,7 +1319,7 @@ mod tests { assert_eq!(re.find_match("/12345"), None); let mut path = Path::new("/151/res"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "151"); assert_eq!(path.unprocessed(), "/res"); } @@ -1332,19 +1329,19 @@ mod tests { let re = ResourceDef::new("/user/-{id}*"); let mut path = Path::new("/user/-profile"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "profile"); let mut path = Path::new("/user/-2345"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "2345"); let mut path = Path::new("/user/-2345/"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "2345/"); let mut path = Path::new("/user/-2345/sdg"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "2345/sdg"); } @@ -1372,7 +1369,7 @@ mod tests { let re = ResourceDef::new("/user/{id}/{tail}*"); assert!(!re.is_match("/user/2345")); let mut path = Path::new("/user/2345/sdg"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "2345"); assert_eq!(path.get("tail").unwrap(), "sdg"); assert_eq!(path.unprocessed(), ""); @@ -1387,7 +1384,7 @@ mod tests { let re = ResourceDef::new("/a{x}b/test/a{y}b"); let mut path = Path::new("/a\nb/test/a\nb"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("x").unwrap(), "\n"); assert_eq!(path.get("y").unwrap(), "\n"); @@ -1396,12 +1393,12 @@ mod tests { let re = ResourceDef::new("/user/{id}*"); let mut path = Path::new("/user/a\nb/a\nb"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "a\nb/a\nb"); let re = ResourceDef::new("/user/{id:.*}"); let mut path = Path::new("/user/a\nb/a\nb"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "a\nb/a\nb"); } @@ -1411,16 +1408,16 @@ mod tests { let re = ResourceDef::new("/user/{id}/test"); let mut path = Path::new("/user/2345/test"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "2345"); let mut path = Path::new("/user/qwe%25/test"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "qwe%25"); let uri = http::Uri::try_from("/user/qwe%25/test").unwrap(); let mut path = Path::new(uri); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.get("id").unwrap(), "qwe%25"); } @@ -1437,11 +1434,11 @@ mod tests { assert!(!re.is_match("/name~")); let mut path = Path::new("/name"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.unprocessed(), ""); let mut path = Path::new("/name/test"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.unprocessed(), "/test"); assert_eq!(re.find_match("/name"), Some(5)); @@ -1457,10 +1454,10 @@ mod tests { assert!(!re.is_match("/name")); let mut path = Path::new("/name/gs"); - assert!(!re.resolve_path_if_matches(&mut path)); + assert!(!re.resolve_path_if_match(&mut path)); let mut path = Path::new("/name//gs"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(path.unprocessed(), "/gs"); let re = ResourceDef::root_prefix("name/"); @@ -1470,7 +1467,7 @@ mod tests { assert!(!re.is_match("/name")); let mut path = Path::new("/name/gs"); - assert!(!re.resolve_path_if_matches(&mut path)); + assert!(!re.resolve_path_if_match(&mut path)); } #[test] @@ -1489,13 +1486,13 @@ mod tests { assert_eq!(re.find_match(""), None); let mut path = Path::new("/test2/"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(&path["name"], "test2"); assert_eq!(&path[0], "test2"); assert_eq!(path.unprocessed(), "/"); let mut path = Path::new("/test2/subpath1/subpath2/index.html"); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); assert_eq!(&path["name"], "test2"); assert_eq!(&path[0], "test2"); assert_eq!(path.unprocessed(), "/subpath1/subpath2/index.html"); @@ -1569,22 +1566,22 @@ mod tests { let resource = ResourceDef::new(["/user/{id}", "/profile/{id}"]); let mut path = Path::new("/user/123"); - assert!(resource.resolve_path_if_matches(&mut path)); + assert!(resource.resolve_path_if_match(&mut path)); assert!(path.get("id").is_some()); let mut path = Path::new("/profile/123"); - assert!(resource.resolve_path_if_matches(&mut path)); + assert!(resource.resolve_path_if_match(&mut path)); assert!(path.get("id").is_some()); let resource = ResourceDef::new(["/user/{id}", "/profile/{uid}"]); let mut path = Path::new("/user/123"); - assert!(resource.resolve_path_if_matches(&mut path)); + assert!(resource.resolve_path_if_match(&mut path)); assert!(path.get("id").is_some()); assert!(path.get("uid").is_none()); let mut path = Path::new("/profile/123"); - assert!(resource.resolve_path_if_matches(&mut path)); + assert!(resource.resolve_path_if_match(&mut path)); assert!(path.get("id").is_none()); assert!(path.get("uid").is_some()); } diff --git a/actix-router/src/resource_path.rs b/actix-router/src/resource_path.rs index 60ca60aa1..610dc344d 100644 --- a/actix-router/src/resource_path.rs +++ b/actix-router/src/resource_path.rs @@ -1,6 +1,3 @@ -use std::mem; - -use crate::resource::ResourceMatchInfo; use crate::Path; // TODO: this trait is necessary, document it @@ -10,26 +7,6 @@ pub trait Resource { type Path: ResourcePath; fn resource_path(&mut self) -> &mut Path; - - fn resolve_path(&mut self, match_info: ResourceMatchInfo<'_>) { - let path = self.resource_path(); - match match_info { - ResourceMatchInfo::Static { matched_len } => { - path.skip(matched_len); - } - ResourceMatchInfo::Dynamic { - matched_len, - matched_vars, - mut segments, - } => { - for i in 0..matched_vars.len() { - path.add(matched_vars[i], mem::take(&mut segments[i])); - } - - path.skip(matched_len); - } - } - } } pub trait ResourcePath { diff --git a/actix-router/src/router.rs b/actix-router/src/router.rs index cfcab8546..cc31f2029 100644 --- a/actix-router/src/router.rs +++ b/actix-router/src/router.rs @@ -55,18 +55,18 @@ impl Router { R: Resource, F: FnMut(&R, &U) -> bool, { - let mut next_match_count = 1; + let mut next_resource_match_count = 1; for (rdef, val, ctx) in self.routes.iter() { match rdef.capture_match_info(resource) { None => {} Some(match_info) => { if check_fn(resource, ctx) { - resource.resolve_path(match_info); + resource.resource_path().resolve(match_info); return Some((val, ResourceId(rdef.id()))); - } else if next_match_count == self.max_path_conflicts { + } else if next_resource_match_count == self.max_path_conflicts { return None; } - next_match_count += 1; + next_resource_match_count += 1; } } } @@ -92,7 +92,7 @@ impl Router { Some(match_info) => { matches += 1; if check_fn(resource, ctx) { - resource.resolve_path(match_info); + resource.resource_path().resolve(match_info); return Some((val, ResourceId(rdef.id()))); } else if matches == self.max_path_conflicts { return None; @@ -108,7 +108,7 @@ impl Router { /// Builder for an ordered [routing](Router) list. pub struct RouterBuilder { routes: Vec<(ResourceDef, T, U)>, - path_conflicts: Vec<(ResourceDef, u16)>, + path_conflicts: Vec<(usize, u16)>, } impl RouterBuilder { @@ -124,14 +124,15 @@ impl RouterBuilder { if let Some((_, path_conflicts)) = self .path_conflicts .iter_mut() - .find(|(current_rdef, _)| rdef.eq(current_rdef)) + .find(|(route_idx, _)| rdef.eq(&self.routes.get(*route_idx).unwrap().0)) { *path_conflicts += 1; } else { - self.path_conflicts.push((rdef.clone(), 1)); + self.path_conflicts.push((self.routes.len(), 1)); } self.routes.push((rdef, val, ctx)); + #[allow(clippy::map_identity)] // map is used to distribute &mut-ness to tuple elements self.routes .last_mut() @@ -141,9 +142,7 @@ impl RouterBuilder { /// Finish configuration and create router instance. pub fn finish(self) -> Router { - let max_path_conflicts = self - .path_conflicts - .iter() + let max_path_conflicts = self.path_conflicts.iter() .map(|(_, path_conflicts)| *path_conflicts) .max() .unwrap_or(1); diff --git a/actix-router/src/url.rs b/actix-router/src/url.rs index 8baed700e..fe85ea2de 100644 --- a/actix-router/src/url.rs +++ b/actix-router/src/url.rs @@ -75,7 +75,7 @@ mod tests { let re = ResourceDef::new(pattern); let uri = Uri::try_from(url.as_ref()).unwrap(); let mut path = Path::new(Url::new(uri)); - assert!(re.resolve_path_if_matches(&mut path)); + assert!(re.resolve_path_if_match(&mut path)); path } diff --git a/actix-web/src/types/path.rs b/actix-web/src/types/path.rs index bb34d1f28..4da7ec3c8 100644 --- a/actix-web/src/types/path.rs +++ b/actix-web/src/types/path.rs @@ -176,7 +176,7 @@ mod tests { let resource = ResourceDef::new("/{value}/"); let mut req = TestRequest::with_uri("/32/").to_srv_request(); - resource.resolve_path_if_matches(req.match_info_mut()); + resource.resolve_path_if_match(req.match_info_mut()); let (req, mut pl) = req.into_parts(); assert_eq!(*Path::::from_request(&req, &mut pl).await.unwrap(), 32); @@ -189,7 +189,7 @@ mod tests { let resource = ResourceDef::new("/{key}/{value}/"); let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request(); - resource.resolve_path_if_matches(req.match_info_mut()); + resource.resolve_path_if_match(req.match_info_mut()); let (req, mut pl) = req.into_parts(); let (Path(res),) = <(Path<(String, String)>,)>::from_request(&req, &mut pl) @@ -215,7 +215,7 @@ mod tests { let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request(); let resource = ResourceDef::new("/{key}/{value}/"); - resource.resolve_path_if_matches(req.match_info_mut()); + resource.resolve_path_if_match(req.match_info_mut()); let (req, mut pl) = req.into_parts(); let mut s = Path::::from_request(&req, &mut pl).await.unwrap(); @@ -238,7 +238,7 @@ mod tests { let mut req = TestRequest::with_uri("/name/32/").to_srv_request(); let resource = ResourceDef::new("/{key}/{value}/"); - resource.resolve_path_if_matches(req.match_info_mut()); + resource.resolve_path_if_match(req.match_info_mut()); let (req, mut pl) = req.into_parts(); let s = Path::::from_request(&req, &mut pl).await.unwrap(); @@ -262,7 +262,7 @@ mod tests { async fn paths_decoded() { let resource = ResourceDef::new("/{key}/{value}"); let mut req = TestRequest::with_uri("/na%2Bme/us%2Fer%254%32").to_srv_request(); - resource.resolve_path_if_matches(req.match_info_mut()); + resource.resolve_path_if_match(req.match_info_mut()); let (req, mut pl) = req.into_parts(); let path_items = Path::::from_request(&req, &mut pl).await.unwrap();