mirror of https://github.com/fafhrd91/actix-web
add some more rmap tests
This commit is contained in:
parent
4bfaaf3df8
commit
0fbfd06752
105
src/rmap.rs
105
src/rmap.rs
|
@ -72,14 +72,13 @@ impl ResourceMap {
|
||||||
pub(crate) fn finish(self: &Rc<Self>) {
|
pub(crate) fn finish(self: &Rc<Self>) {
|
||||||
for node in self.nodes.iter().flatten() {
|
for node in self.nodes.iter().flatten() {
|
||||||
node.parent.replace(Rc::downgrade(self));
|
node.parent.replace(Rc::downgrade(self));
|
||||||
Self::finish(node);
|
ResourceMap::finish(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate url for named resource
|
/// Generate url for named resource
|
||||||
///
|
///
|
||||||
/// Check [`HttpRequest::url_for()`](../struct.HttpRequest.html#method.
|
/// Check [`HttpRequest::url_for`] for detailed information.
|
||||||
/// url_for) for detailed information.
|
|
||||||
pub fn url_for<U, I>(
|
pub fn url_for<U, I>(
|
||||||
&self,
|
&self,
|
||||||
req: &HttpRequest,
|
req: &HttpRequest,
|
||||||
|
@ -96,15 +95,10 @@ impl ResourceMap {
|
||||||
.named
|
.named
|
||||||
.get(name)
|
.get(name)
|
||||||
.ok_or(UrlGenerationError::ResourceNotFound)?
|
.ok_or(UrlGenerationError::ResourceNotFound)?
|
||||||
.fold_parents(String::new(), |mut acc, node| {
|
.root_rmap_fn(String::with_capacity(24), |mut acc, node| {
|
||||||
if node
|
node.pattern
|
||||||
.pattern
|
|
||||||
.resource_path_from_iter(&mut acc, &mut elements)
|
.resource_path_from_iter(&mut acc, &mut elements)
|
||||||
{
|
.then(|| acc)
|
||||||
Some(acc)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.ok_or(UrlGenerationError::NotEnoughElements)?;
|
.ok_or(UrlGenerationError::NotEnoughElements)?;
|
||||||
|
|
||||||
|
@ -134,11 +128,13 @@ impl ResourceMap {
|
||||||
/// Returns the full resource pattern matched against a path or None if no full match
|
/// Returns the full resource pattern matched against a path or None if no full match
|
||||||
/// is possible.
|
/// is possible.
|
||||||
pub fn match_pattern(&self, path: &str) -> Option<String> {
|
pub fn match_pattern(&self, path: &str) -> Option<String> {
|
||||||
self.find_matching_node(path)?
|
self.find_matching_node(path)?.root_rmap_fn(
|
||||||
.fold_parents(String::new(), |mut acc, node| {
|
String::with_capacity(24),
|
||||||
|
|mut acc, node| {
|
||||||
acc.push_str(node.pattern.pattern()?);
|
acc.push_str(node.pattern.pattern()?);
|
||||||
Some(acc)
|
Some(acc)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_matching_node(&self, path: &str) -> Option<&ResourceMap> {
|
fn find_matching_node(&self, path: &str) -> Option<&ResourceMap> {
|
||||||
|
@ -153,6 +149,7 @@ impl ResourceMap {
|
||||||
let path = &path[matched_len..];
|
let path = &path[matched_len..];
|
||||||
|
|
||||||
Some(match &self.nodes {
|
Some(match &self.nodes {
|
||||||
|
// find first sub-node to match remaining path
|
||||||
Some(nodes) => nodes
|
Some(nodes) => nodes
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|node| node._find_matching_node(path))
|
.filter_map(|node| node._find_matching_node(path))
|
||||||
|
@ -164,20 +161,21 @@ impl ResourceMap {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Folds the parents from the root of the tree to self.
|
/// Find `self`'s highest ancestor and then run `F`, providing `B`, in that rmap context.
|
||||||
fn fold_parents<F, B>(&self, init: B, mut f: F) -> Option<B>
|
fn root_rmap_fn<F, B>(&self, init: B, mut f: F) -> Option<B>
|
||||||
where
|
where
|
||||||
F: FnMut(B, &ResourceMap) -> Option<B>,
|
F: FnMut(B, &ResourceMap) -> Option<B>,
|
||||||
{
|
{
|
||||||
self._fold_parents(init, &mut f)
|
self._root_rmap_fn(init, &mut f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _fold_parents<F, B>(&self, init: B, f: &mut F) -> Option<B>
|
/// Run `F`, providing `B`, if `self` is top-level resource map, else recurse to parent map.
|
||||||
|
fn _root_rmap_fn<F, B>(&self, init: B, f: &mut F) -> Option<B>
|
||||||
where
|
where
|
||||||
F: FnMut(B, &ResourceMap) -> Option<B>,
|
F: FnMut(B, &ResourceMap) -> Option<B>,
|
||||||
{
|
{
|
||||||
let data = match self.parent.borrow().upgrade() {
|
let data = match self.parent.borrow().upgrade() {
|
||||||
Some(ref parent) => parent._fold_parents(init, f)?,
|
Some(ref parent) => parent._root_rmap_fn(init, f)?,
|
||||||
None => init,
|
None => init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -374,4 +372,73 @@ mod tests {
|
||||||
assert!(rmap.has_resource("/user/u3"));
|
assert!(rmap.has_resource("/user/u3"));
|
||||||
assert!(!rmap.has_resource("/user/u4"));
|
assert!(!rmap.has_resource("/user/u4"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn url_for() {
|
||||||
|
let mut root = ResourceMap::new(ResourceDef::prefix(""));
|
||||||
|
|
||||||
|
let mut user_scope_rdef = ResourceDef::prefix("/user");
|
||||||
|
let mut user_scope_map = ResourceMap::new(user_scope_rdef.clone());
|
||||||
|
|
||||||
|
let mut user_rdef = ResourceDef::new("/{user_id}");
|
||||||
|
let mut user_map = ResourceMap::new(user_rdef.clone());
|
||||||
|
|
||||||
|
let mut post_rdef = ResourceDef::new("/post/{sub_id}");
|
||||||
|
post_rdef.set_name("post");
|
||||||
|
|
||||||
|
user_map.add(&mut post_rdef, None);
|
||||||
|
user_scope_map.add(&mut user_rdef, Some(Rc::new(user_map)));
|
||||||
|
root.add(&mut user_scope_rdef, Some(Rc::new(user_scope_map)));
|
||||||
|
|
||||||
|
let rmap = Rc::new(root);
|
||||||
|
ResourceMap::finish(&rmap);
|
||||||
|
|
||||||
|
let mut req = crate::test::TestRequest::default();
|
||||||
|
req.set_server_hostname("localhost:8888");
|
||||||
|
let req = req.to_http_request();
|
||||||
|
|
||||||
|
let url = rmap
|
||||||
|
.url_for(&req, "post", &["u123", "foobar"])
|
||||||
|
.unwrap()
|
||||||
|
.to_string();
|
||||||
|
assert_eq!(url, "http://localhost:8888/user/u123/post/foobar");
|
||||||
|
|
||||||
|
assert!(rmap.url_for(&req, "missing", &["u123"]).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn external_resource_with_no_name() {
|
||||||
|
let mut root = ResourceMap::new(ResourceDef::prefix(""));
|
||||||
|
|
||||||
|
let mut rdef = ResourceDef::new("https://duck.com/{query}");
|
||||||
|
root.add(&mut rdef, None);
|
||||||
|
|
||||||
|
let rmap = Rc::new(root);
|
||||||
|
ResourceMap::finish(&rmap);
|
||||||
|
|
||||||
|
assert!(!rmap.has_resource("https://duck.com/abc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn external_resource_with_name() {
|
||||||
|
let mut root = ResourceMap::new(ResourceDef::prefix(""));
|
||||||
|
|
||||||
|
let mut rdef = ResourceDef::new("https://duck.com/{query}");
|
||||||
|
rdef.set_name("duck");
|
||||||
|
root.add(&mut rdef, None);
|
||||||
|
|
||||||
|
let rmap = Rc::new(root);
|
||||||
|
ResourceMap::finish(&rmap);
|
||||||
|
|
||||||
|
assert!(!rmap.has_resource("https://duck.com/abc"));
|
||||||
|
|
||||||
|
let mut req = crate::test::TestRequest::default();
|
||||||
|
req.set_server_hostname("localhost:8888");
|
||||||
|
let req = req.to_http_request();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
rmap.url_for(&req, "duck", &["abcd"]).unwrap().to_string(),
|
||||||
|
"https://duck.com/abcd"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue