diff --git a/router/CHANGES.txt b/router/CHANGES.txt index 48532c01..5d05d2cc 100644 --- a/router/CHANGES.txt +++ b/router/CHANGES.txt @@ -1,5 +1,9 @@ # Changes +## [0.1.4] - 2019-05-15 + +* Fix checked resource match + ## [0.1.3] - 2019-04-22 * Added support for `remainder match` (i.e "/path/{tail}*") diff --git a/router/Cargo.toml b/router/Cargo.toml index e176fbff..29b21081 100644 --- a/router/Cargo.toml +++ b/router/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "actix-router" -version = "0.1.3" +version = "0.1.4" authors = ["Nikolay Kim "] -description = "Path table router" +description = "Path router" keywords = ["actix"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-net.git" diff --git a/router/src/resource.rs b/router/src/resource.rs index ccbb3e59..10a96209 100644 --- a/router/src/resource.rs +++ b/router/src/resource.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use regex::{escape, Regex}; use crate::path::{Path, PathItem}; -use crate::ResourcePath; +use crate::{Resource, ResourcePath}; const MAX_DYNAMIC_SEGMENTS: usize = 16; @@ -240,6 +240,90 @@ impl ResourceDef { } } + /// Is the given path and parameters a match against this pattern? + pub fn match_path_checked( + &self, + res: &mut R, + check: &F, + user_data: &Option, + ) -> bool + where + T: ResourcePath, + R: Resource, + F: Fn(&R, &Option) -> bool, + { + match self.tp { + PatternType::Static(ref s) => { + if s == res.resource_path().path() && check(res, user_data) { + let path = res.resource_path(); + path.skip(path.len() as u16); + true + } else { + false + } + } + PatternType::Dynamic(ref re, ref names, len) => { + let mut idx = 0; + let mut pos = 0; + let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = + [PathItem::Static(""); MAX_DYNAMIC_SEGMENTS]; + + if let Some(captures) = re.captures(res.resource_path().path()) { + for (no, name) in names.iter().enumerate() { + if let Some(m) = captures.name(&name) { + idx += 1; + pos = m.end(); + segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16); + } else { + log::error!( + "Dynamic path match but not all segments found: {}", + name + ); + false; + } + } + } else { + return false; + } + + if !check(res, user_data) { + return false; + } + + let path = res.resource_path(); + for idx in 0..idx { + path.add(names[idx].clone(), segments[idx]); + } + path.skip((pos + len) as u16); + true + } + PatternType::Prefix(ref s) => { + let len = { + let rpath = res.resource_path().path(); + if s == rpath { + s.len() + } else if rpath.starts_with(s) + && (s.ends_with('/') || rpath.split_at(s.len()).1.starts_with('/')) + { + if s.ends_with('/') { + s.len() - 1 + } else { + s.len() + } + } else { + return false; + } + }; + if !check(res, user_data) { + return false; + } + let path = res.resource_path(); + path.skip(min(path.path().len(), len) as u16); + true + } + } + } + /// Build resource path from elements. Returns `true` on success. pub fn resource_path(&self, path: &mut String, elements: &mut U) -> bool where diff --git a/router/src/router.rs b/router/src/router.rs index 21bcc674..1e3c652c 100644 --- a/router/src/router.rs +++ b/router/src/router.rs @@ -19,26 +19,26 @@ impl Router { } } - pub fn recognize(&self, path: &mut R) -> Option<(&T, ResourceId)> + pub fn recognize(&self, reosurce: &mut R) -> Option<(&T, ResourceId)> where R: Resource

, P: ResourcePath, { for item in self.0.iter() { - if item.0.match_path(path.resource_path()) { + if item.0.match_path(reosurce.resource_path()) { return Some((&item.1, ResourceId(item.0.id()))); } } None } - pub fn recognize_mut(&mut self, res: &mut R) -> Option<(&mut T, ResourceId)> + pub fn recognize_mut(&mut self, reosurce: &mut R) -> Option<(&mut T, ResourceId)> where R: Resource

, P: ResourcePath, { for item in self.0.iter_mut() { - if item.0.match_path(res.resource_path()) { + if item.0.match_path(reosurce.resource_path()) { return Some((&mut item.1, ResourceId(item.0.id()))); } } @@ -47,7 +47,7 @@ impl Router { pub fn recognize_mut_checked( &mut self, - res: &mut R, + resource: &mut R, check: F, ) -> Option<(&mut T, ResourceId)> where @@ -55,8 +55,11 @@ impl Router { R: Resource

, P: ResourcePath, { + println!("router ==== {:?}", self.0.len()); for item in self.0.iter_mut() { - if item.0.match_path(res.resource_path()) && check(res, &item.2) { + println!("1"); + if item.0.match_path_checked(resource, &check, &item.2) { + println!("lll"); return Some((&mut item.1, ResourceId(item.0.id()))); } }