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
91
92
93
94
95
96
97
extern crate iron;
extern crate regex;

use std::collections::HashMap;
use iron::method::Method;
use iron::{status, Handler, Request, Response, IronResult};
use regex::{Regex, Captures};

type RouteHandler = fn(&mut Request, Captures) -> IronResult<Response>;
type NotFoundHandler = fn(&mut Request) -> IronResult<Response>;
type Routes = HashMap<Method, Vec<(Regex, RouteHandler)>>;

pub struct Router {
    routes: Routes,
    not_found: NotFoundHandler,
}

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let url = ["/", &req.url.path().join("/")].concat();
        let routes = self.routes.get(&req.method).unwrap();
        match routes.clone().into_iter().find(|ref x| x.0.is_match(&url)) {
            Some((re, handler)) => {
                let captures = re.captures(&url).unwrap();
                handler(req, captures)
            }
            None => (self.not_found)(req)
        }
    }
}

pub struct RouterBuilder {
    pub routes: Routes,
    pub not_found: Option<NotFoundHandler>
}

impl RouterBuilder {
    pub fn new() -> RouterBuilder {
        let mut routes = HashMap::new();
        routes.insert(Method::Get, Vec::new());
        routes.insert(Method::Post, Vec::new());
        routes.insert(Method::Put, Vec::new());
        routes.insert(Method::Delete, Vec::new());

        RouterBuilder {
            routes: routes,
            not_found: None
        }
    }

    fn route(&mut self, method: Method, pattern: &str, handler: RouteHandler) -> &mut RouterBuilder {
        let pattern = [r"\A", pattern, r"\z"].join("");
        let re = Regex::new(&pattern).unwrap();
        self.routes.get_mut(&method).unwrap().push((re, handler));
        self
    }

    pub fn get(&mut self, pattern: &str, handler: RouteHandler) -> &mut RouterBuilder {
        self.route(Method::Get, pattern, handler)
    }

    pub fn post(&mut self, pattern: &str, handler: RouteHandler) -> &mut RouterBuilder {
        self.route(Method::Post, pattern, handler)
    }

    pub fn put(&mut self, pattern: &str, handler: RouteHandler) -> &mut RouterBuilder {
        self.route(Method::Put, pattern, handler)
    }

    pub fn delete(&mut self, pattern: &str, handler: RouteHandler) -> &mut RouterBuilder {
        self.route(Method::Delete, pattern, handler)
    }

    pub fn not_found(&mut self, handler: NotFoundHandler) -> &mut RouterBuilder {
        self.not_found = Some(handler);
        self
    }

    pub fn finalize(self) -> Router {
        Router {
            routes: self.routes,
            not_found: self.not_found.unwrap_or_else(|| default_not_found)
        }
    }
}

fn default_not_found(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::NotFound)))
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}