-
Notifications
You must be signed in to change notification settings - Fork 10
/
router.rs
90 lines (76 loc) · 2.68 KB
/
router.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use request::{Method, Request};
use response::Response;
pub type Handler<T> = fn@(@Request<T>, @mut Response, pcre::Match);
pub struct Router<T> {
routes: DVec<(Method, pcre::Pcre, Handler<T>)>,
}
pub fn Router<T>() -> Router<T> {
Router { routes: DVec() }
}
impl<T> Router<T> {
fn add(method: Method, pattern: &str, handler: Handler<T>) {
let regex = match pcre::Pcre(pattern) {
Ok(move regex) => regex,
Err(move e) => fail e,
};
self.routes.push((method, regex, handler));
}
fn add_patterns(items: ~[(Method, ~str, Handler<T>)]) {
for items.each |item| {
match item {
&(method, pattern, handler) => {
self.add(method, pattern, handler)
}
}
};
}
fn find(method: Method, path: &str) -> Option<(Handler<T>, pcre::Match)> {
for self.routes.each() |item| {
match item {
&(meth, regex, handler) => {
if method == meth {
match regex.exec(path) {
None => { },
Some(move m) => return Some((handler, m)),
}
}
}
}
}
None
}
}
#[cfg(test)]
mod tests {
use pcre::Match;
use request::GET;
fn check_path<T>(router: &Router<T>, method: Method, path: ~str,
captures: ~[@~str]) {
let (_handler, m) = option::unwrap(router.find(method, path));
assert m.substrings == captures;
}
#[test]
fn test_router() {
let router = @Router::<()>();
assert router.find(GET, "").is_none();
assert router.find(GET, "/foo/bar/baz").is_none();
let a = |_req, rep: @mut Response, _m| { rep.reply_http(200u, "") };
let b = |_req, rep: @mut Response, _m| { rep.reply_http(200u, "") };
let c = |_req, rep: @mut Response, _m| { rep.reply_http(200u, "") };
let d = |_req, rep: @mut Response, _m| { rep.reply_http(200u, "") };
let z = |_req, rep: @mut Response, _m| { rep.reply_http(200u, "") };
router.add_patterns(~[
(GET, ~"^/$", a),
(GET, ~"^/foo$", b),
(GET, ~"^/foo/bar/baz$", c),
(GET, ~"^/([^\\/]+)/(.*)$", d),
(GET, ~"", z)
]);
check_path(router, GET, ~"/", ~[]);
check_path(router, GET, ~"/foo", ~[]);
check_path(router, GET, ~"/foo/bar/baz", ~[]);
check_path(router, GET, ~"/a12/b34", ~[@~"a12", @~"b34"]);
check_path(router, GET, ~"/a12/b34/c/d", ~[@~"a12", @~"b34/c/d"]);
check_path(router, GET, ~"lalala", ~[]);
}
}