1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-08-14 12:20:30 +02:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Nikolay Kim
76c317e0b2 Added support for remainder match 2019-04-22 21:19:22 -07:00
Nikolay Kim
3b314e4c8c Connect::set_addr() 2019-04-19 17:43:52 -07:00
7 changed files with 99 additions and 19 deletions

View File

@@ -1,5 +1,10 @@
# Changes
## [0.1.5] - 2019-04-19
### Added
* `Connect::set_addr()`
### Changed

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-connect"
version = "0.1.4"
version = "0.1.5"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix Connector - tcp connector service"
keywords = ["network", "framework", "async", "futures"]
@@ -34,9 +34,9 @@ actix-service = "0.3.6"
actix-codec = "0.1.2"
actix-utils = "0.3.5"
derive_more = "0.14.0"
either = "1.5.1"
either = "1.5.2"
futures = "0.1.25"
http = { version = "0.1.16", optional = true }
http = { version = "0.1.17", optional = true }
log = "0.4"
tokio-tcp = "0.1.3"
tokio-current-thread = "0.1.5"

View File

@@ -69,6 +69,14 @@ impl<T: Address> Connect<T> {
self
}
/// Use address.
pub fn set_addr(mut self, addr: Option<SocketAddr>) -> Self {
if let Some(addr) = addr {
self.addr = Some(Either::Left(addr));
}
self
}
/// Host name
pub fn host(&self) -> &str {
self.req.host()

View File

@@ -8,10 +8,13 @@ pub type BoxedService<Req, Res, Err> = Box<
Request = Req,
Response = Res,
Error = Err,
Future = Either<FutureResult<Res, Err>, Box<Future<Item = Res, Error = Err>>>,
Future = BoxedServiceResponse<Res, Err>,
>,
>;
pub type BoxedServiceResponse<Res, Err> =
Either<FutureResult<Res, Err>, Box<Future<Item = Res, Error = Err>>>;
/// Create boxed new service
pub fn new_service<T, C>(
service: T,

View File

@@ -1,5 +1,9 @@
# Changes
## [0.1.3] - 2019-04-22
* Added support for `remainder match` (i.e "/path/{tail}*")
## [0.1.2] - 2019-04-07
* Export `Quoter` type

View File

@@ -1,8 +1,8 @@
[package]
name = "actix-router"
version = "0.1.2"
version = "0.1.3"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Path router"
description = "Path table router"
keywords = ["actix"]
homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-net.git"

View File

@@ -267,8 +267,9 @@ impl ResourceDef {
true
}
fn parse_param(pattern: &str) -> (PatternElement, String, &str) {
fn parse_param(pattern: &str) -> (PatternElement, String, &str, bool) {
const DEFAULT_PATTERN: &str = "[^/]+";
const DEFAULT_PATTERN_TAIL: &str = ".*";
let mut params_nesting = 0usize;
let close_idx = pattern
.find(|c| match c {
@@ -283,34 +284,54 @@ impl ResourceDef {
_ => false,
})
.expect("malformed dynamic segment");
let (mut param, rem) = pattern.split_at(close_idx + 1);
let (mut param, mut rem) = pattern.split_at(close_idx + 1);
param = &param[1..param.len() - 1]; // Remove outer brackets
let tail = rem == "*";
let (name, pattern) = match param.find(':') {
Some(idx) => {
if tail {
panic!("Custom regex is not supported for remainder match");
}
let (name, pattern) = param.split_at(idx);
(name, &pattern[1..])
}
None => (param, DEFAULT_PATTERN),
None => (
param,
if tail {
rem = &rem[1..];
DEFAULT_PATTERN_TAIL
} else {
DEFAULT_PATTERN
},
),
};
(
PatternElement::Var(name.to_string()),
format!(r"(?P<{}>{})", &name, &pattern),
rem,
tail,
)
}
fn parse(
mut pattern: &str,
for_prefix: bool,
mut for_prefix: bool,
) -> (String, Vec<PatternElement>, bool, usize) {
if pattern.find('{').is_none() {
return (
String::from(pattern),
vec![PatternElement::Str(String::from(pattern))],
false,
pattern.chars().count(),
);
};
return if pattern.ends_with('*') {
let path = &pattern[..pattern.len() - 1];
let re = String::from("^") + path + "(.*)";
(re, vec![PatternElement::Str(String::from(path))], true, 0)
} else {
(
String::from(pattern),
vec![PatternElement::Str(String::from(pattern))],
false,
pattern.chars().count(),
)
};
}
let mut elems = Vec::new();
let mut re = String::from("^");
@@ -320,7 +341,11 @@ impl ResourceDef {
let (prefix, rem) = pattern.split_at(idx);
elems.push(PatternElement::Str(String::from(prefix)));
re.push_str(&escape(prefix));
let (param_pattern, re_part, rem) = Self::parse_param(rem);
let (param_pattern, re_part, rem, tail) = Self::parse_param(rem);
if tail {
for_prefix = true;
}
elems.push(param_pattern);
re.push_str(&re_part);
pattern = rem;
@@ -340,7 +365,6 @@ impl ResourceDef {
if !for_prefix {
re.push_str("$");
}
(re, elems, true, pattern.chars().count())
}
}
@@ -448,6 +472,42 @@ mod tests {
assert_eq!(path.get("id").unwrap(), "012345");
}
#[test]
fn test_parse_tail() {
let re = ResourceDef::new("/user/-{id}*");
let mut path = Path::new("/user/-profile");
assert!(re.match_path(&mut path));
assert_eq!(path.get("id").unwrap(), "profile");
let mut path = Path::new("/user/-2345");
assert!(re.match_path(&mut path));
assert_eq!(path.get("id").unwrap(), "2345");
let mut path = Path::new("/user/-2345/");
assert!(re.match_path(&mut path));
assert_eq!(path.get("id").unwrap(), "2345/");
let mut path = Path::new("/user/-2345/sdg");
assert!(re.match_path(&mut path));
assert_eq!(path.get("id").unwrap(), "2345/sdg");
}
#[test]
fn test_static_tail() {
let re = ResourceDef::new("/user*");
assert!(re.is_match("/user/profile"));
assert!(re.is_match("/user/2345"));
assert!(re.is_match("/user/2345/"));
assert!(re.is_match("/user/2345/sdg"));
let re = ResourceDef::new("/user/*");
assert!(re.is_match("/user/profile"));
assert!(re.is_match("/user/2345"));
assert!(re.is_match("/user/2345/"));
assert!(re.is_match("/user/2345/sdg"));
}
#[test]
fn test_parse_urlencoded_param() {
let re = ResourceDef::new("/user/{id}/test");