Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
245 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
use super::Matcher; | ||
use regex::{Regex, Captures}; | ||
|
||
pub trait IntoMatcher { | ||
fn into_matcher(self) -> Matcher; | ||
} | ||
|
||
impl IntoMatcher for Regex { | ||
fn into_matcher(self) -> Matcher { | ||
let path = self.as_str().to_string(); | ||
Matcher::new(path, self) | ||
} | ||
} | ||
|
||
impl<'a> IntoMatcher for &'a str { | ||
fn into_matcher(self) -> Matcher { | ||
self.to_string().into_matcher() | ||
} | ||
} | ||
|
||
lazy_static! { | ||
static ref REGEX_VAR_SEQ: Regex = Regex::new(r":([,a-zA-Z0-9_-]*)").unwrap(); | ||
} | ||
|
||
impl IntoMatcher for String { | ||
fn into_matcher(self) -> Matcher { | ||
static FORMAT_VAR: &'static str = ":format"; | ||
static VAR_SEQ: &'static str = "[,a-zA-Z0-9_-]*"; | ||
static VAR_SEQ_WITH_SLASH: &'static str = "[,/a-zA-Z0-9_-]*"; | ||
// matches request params (e.g. ?foo=true&bar=false) | ||
static REGEX_PARAM_SEQ: &'static str = "(\\?[a-zA-Z0-9%_=&-]*)?"; | ||
|
||
let with_format = if self.contains(FORMAT_VAR) { | ||
self | ||
} else { | ||
format!("{}(\\.{})?", self, FORMAT_VAR) | ||
}; | ||
|
||
// first mark all double wildcards for replacement. | ||
// We can't directly replace them since the replacement | ||
// does contain the * symbol as well, which would get | ||
// overwritten with the next replace call | ||
let wildcarded = with_format.replace("**", "___DOUBLE_WILDCARD___") | ||
// then replace the regular wildcard symbols (*) with the | ||
// appropriate regex | ||
.replace("*", VAR_SEQ) | ||
// now replace the previously marked double wild cards (**) | ||
.replace("___DOUBLE_WILDCARD___", VAR_SEQ_WITH_SLASH); | ||
|
||
// Add a named capture for each :(variable) symbol | ||
let named_captures = REGEX_VAR_SEQ.replace_all(&wildcarded, |captures: &Captures| { | ||
// There should only ever be one match (after subgroup 0) | ||
let c = captures.iter().skip(1).next().unwrap(); | ||
format!("(?P<{}>[,a-zA-Z0-9%_-]*)", c.unwrap()) | ||
}); | ||
|
||
let line_regex = format!("^{}{}$", named_captures, REGEX_PARAM_SEQ); | ||
let regex = Regex::new(&line_regex).unwrap(); | ||
Matcher::new(with_format, regex) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use std::borrow::{IntoCow, Cow}; | ||
use std::ops::Deref; | ||
use regex::Regex; | ||
|
||
pub struct Matcher { | ||
pub path: Cow<'static, str>, | ||
pub regex: Regex | ||
} | ||
|
||
impl Matcher { | ||
pub fn new<P: IntoCow<'static, str>>(path: P, regex: Regex) -> Matcher { | ||
Matcher { | ||
path: path.into_cow(), | ||
regex: regex | ||
} | ||
} | ||
|
||
pub fn path(&self) -> &str { | ||
&self.path | ||
} | ||
} | ||
|
||
impl Deref for Matcher { | ||
type Target = Regex; | ||
|
||
fn deref(&self) -> &Regex { | ||
&self.regex | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,10 @@ | ||
//!Router asigns handlers to paths and resolves them per request | ||
pub use self::http_router::HttpRouter; | ||
pub use self::router::{Router, Route, RouteResult}; | ||
pub use self::matcher::Matcher; | ||
pub use self::into_matcher::IntoMatcher; | ||
|
||
pub mod http_router; | ||
pub mod router; | ||
|
||
/// The path_utils collects some small helper methods that operate on the path | ||
mod path_utils { | ||
use regex::{Regex, Captures}; | ||
|
||
// matches named variables (e.g. :userid) | ||
lazy_static! { | ||
static ref REGEX_VAR_SEQ: Regex = Regex::new(r":([,a-zA-Z0-9_-]*)").unwrap(); | ||
} | ||
static VAR_SEQ: &'static str = "[,a-zA-Z0-9_-]*"; | ||
static VAR_SEQ_WITH_SLASH: &'static str = "[,/a-zA-Z0-9_-]*"; | ||
|
||
// matches request params (e.g. ?foo=true&bar=false) | ||
static REGEX_PARAM_SEQ: &'static str = "(\\?[a-zA-Z0-9%_=&-]*)?"; | ||
|
||
pub fn create_regex(route_path: &str) -> Regex { | ||
let updated_path = | ||
route_path.to_string() | ||
// first mark all double wildcards for replacement. | ||
// We can't directly replace them since the replacement | ||
// does contain the * symbol as well, which would get | ||
// overwritten with the next replace call | ||
.replace("**", "___DOUBLE_WILDCARD___") | ||
// then replace the regular wildcard symbols (*) with the | ||
// appropriate regex | ||
.replace("*", VAR_SEQ) | ||
// now replace the previously marked double wild cards (**) | ||
.replace("___DOUBLE_WILDCARD___", VAR_SEQ_WITH_SLASH); | ||
|
||
// Add a named capture for each :(variable) symbol | ||
let named_captures = REGEX_VAR_SEQ.replace_all(&updated_path, |captures: &Captures| { | ||
// There should only ever be one match (after subgroup 0) | ||
let c = captures.iter().skip(1).next().unwrap(); | ||
format!("(?P<{}>[,a-zA-Z0-9%_-]*)", c.unwrap()) | ||
}); | ||
|
||
let line_regex = format!("^{}{}$", named_captures, REGEX_PARAM_SEQ); | ||
|
||
Regex::new(&line_regex).unwrap() | ||
} | ||
} | ||
mod matcher; | ||
mod into_matcher; |
Oops, something went wrong.