1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 07:53:00 +01:00

fixed HttpRequest::url_for for a named route with no variables #265

This commit is contained in:
Nikolay Kim 2018-06-02 11:44:09 -07:00
parent 8d905c8504
commit 4a39216aa7
2 changed files with 81 additions and 19 deletions

View File

@ -311,6 +311,7 @@ impl<S> HttpRequest<S> {
Err(UrlGenerationError::RouterNotAvailable)
} else {
let path = self.router().unwrap().resource_path(name, elements)?;
println!("==== {:?}", path);
if path.starts_with('/') {
let conn = self.connection_info();
Ok(Url::parse(&format!(
@ -325,6 +326,15 @@ impl<S> HttpRequest<S> {
}
}
/// Generate url for named resource
///
/// This method is similar to `HttpRequest::url_for()` but it can be used
/// for urls that do not contain variable parts.
pub fn url_for_static(&self, name: &str) -> Result<Url, UrlGenerationError> {
const NO_PARAMS: [&str; 0] = [];
self.url_for(name, &NO_PARAMS)
}
/// This method returns reference to current `Router` object.
#[inline]
pub fn router(&self) -> Option<&Router> {
@ -695,20 +705,38 @@ mod tests {
let mut resource = ResourceHandler::<()>::default();
resource.name("index");
let routes =
vec![(Resource::new("index", "/user/{name}.{ext}"), Some(resource))];
let routes = vec![(Resource::new("index", "/user/{name}.html"), Some(resource))];
let (router, _) = Router::new("/prefix/", ServerSettings::default(), routes);
assert!(router.has_route("/user/test.html"));
assert!(!router.has_route("/prefix/user/test.html"));
let req = req.with_state(Rc::new(()), router);
let url = req.url_for("index", &["test", "html"]);
let url = req.url_for("index", &["test"]);
assert_eq!(
url.ok().unwrap().as_str(),
"http://www.rust-lang.org/prefix/user/test.html"
);
}
#[test]
fn test_url_for_static() {
let req = TestRequest::with_header(header::HOST, "www.rust-lang.org").finish();
let mut resource = ResourceHandler::<()>::default();
resource.name("index");
let routes = vec![(Resource::new("index", "/index.html"), Some(resource))];
let (router, _) = Router::new("/prefix/", ServerSettings::default(), routes);
assert!(router.has_route("/index.html"));
assert!(!router.has_route("/prefix/index.html"));
let req = req.with_state(Rc::new(()), router);
let url = req.url_for_static("index");
assert_eq!(
url.ok().unwrap().as_str(),
"http://www.rust-lang.org/prefix/index.html"
);
}
#[test]
fn test_url_for_external() {
let req = HttpRequest::default();

View File

@ -211,6 +211,8 @@ impl Resource {
let (pattern, elements, is_dynamic, len) =
Resource::parse(path, prefix, for_prefix);
println!("ELEMENT: {:?} {:?} {:?}", pattern, elements, is_dynamic);
let tp = if is_dynamic {
let re = match Regex::new(&pattern) {
Ok(re) => re,
@ -338,22 +340,42 @@ impl Resource {
U: IntoIterator<Item = I>,
I: AsRef<str>,
{
let mut iter = elements.into_iter();
let mut path = if self.rtp != ResourceType::External {
format!("{}/", router.prefix())
} else {
String::new()
};
for el in &self.elements {
match *el {
PatternElement::Str(ref s) => path.push_str(s),
PatternElement::Var(_) => {
if let Some(val) = iter.next() {
path.push_str(val.as_ref())
} else {
return Err(UrlGenerationError::NotEnoughElements);
let mut path = match self.tp {
PatternType::Prefix(ref p) => p.to_owned(),
PatternType::Static(ref p) => p.to_owned(),
PatternType::Dynamic(..) => {
let mut path = String::new();
let mut iter = elements.into_iter();
for el in &self.elements {
println!("EL: {:?}", el);
match *el {
PatternElement::Str(ref s) => path.push_str(s),
PatternElement::Var(_) => {
if let Some(val) = iter.next() {
path.push_str(val.as_ref())
} else {
return Err(UrlGenerationError::NotEnoughElements);
}
}
}
}
path
}
};
if self.rtp != ResourceType::External {
let prefix = router.prefix();
if prefix.ends_with('/') {
if path.starts_with('/') {
path.insert_str(0, &prefix[..prefix.len() - 1]);
} else {
path.insert_str(0, prefix);
}
} else {
if !path.starts_with('/') {
path.insert(0, '/');
}
path.insert_str(0, prefix);
}
}
Ok(path)
@ -418,6 +440,10 @@ impl Resource {
}
}
if !el.is_empty() {
elems.push(PatternElement::Str(el.clone()));
}
let re = if is_dynamic {
if !for_prefix {
re1.push('$');
@ -450,7 +476,7 @@ mod tests {
use test::TestRequest;
#[test]
fn test_recognizer() {
fn test_recognizer10() {
let routes = vec![
(Resource::new("", "/name"), Some(ResourceHandler::default())),
(
@ -473,6 +499,10 @@ mod tests {
Resource::new("", "/v/{tail:.*}"),
Some(ResourceHandler::default()),
),
(
Resource::new("", "/test2/{test}.html"),
Some(ResourceHandler::default()),
),
(
Resource::new("", "{test}/index.html"),
Some(ResourceHandler::default()),
@ -510,8 +540,12 @@ mod tests {
"blah-blah/index.html"
);
let mut req = TestRequest::with_uri("/bbb/index.html").finish();
let mut req = TestRequest::with_uri("/test2/index.html").finish();
assert_eq!(rec.recognize(&mut req), Some(6));
assert_eq!(req.match_info().get("test").unwrap(), "index");
let mut req = TestRequest::with_uri("/bbb/index.html").finish();
assert_eq!(rec.recognize(&mut req), Some(7));
assert_eq!(req.match_info().get("test").unwrap(), "bbb");
}