ferrum_router/
macros.rs

1/// Create and populate a router.
2///
3/// ```ignore
4/// let router = router!(
5///     get  "/"        => index        "index",
6///     get  "/{query}" => queryHandler "query",
7///     post "/"        => postHandler
8/// );
9/// ```
10///
11/// Is equivalent to:
12///
13/// ```ignore
14/// let mut router = Router::new();
15/// router.get("/", index, Id::some("index"));
16/// router.get("/{query}", queryHandler, Id::some("query"));
17/// router.post("/", postHandler, None);
18/// ```
19///
20/// The method name must be lowercase, supported methods:
21///
22/// `get`, `post`, `put`, `delete`, `head`, `patch`, `options` and `any`.
23#[macro_export]
24macro_rules! router {
25    ($($method:ident $glob:expr => $handler:tt $($route_id:expr)*),* $(,)*) => ({
26        let mut router = $crate::Router::new();
27        $(route_line!(router, $method $glob => $handler ($($route_id)*));)*
28        router
29    });
30}
31
32#[macro_export]
33macro_rules! route_line {
34    ($router:ident, $method:ident $glob:expr => $handler:tt () $(,)*) => {
35        $router.$method($glob, $handler, None);
36    };
37    ($router:ident, $method:ident $glob:expr => $handler:tt ($route_id:expr) $(,)*) => {
38        $router.$method($glob, $handler, $crate::Id::some($route_id));
39    };
40}
41
42/// Generate a URI based off of the requested one.
43///
44/// ```ignore
45/// uri_for!(request, "foo",
46///          "query" => "test",
47///          "extraparam" => "param")
48/// ```
49///
50/// Is equivalent to:
51///
52/// ```ignore
53/// ferrum_router::uri_for(&request, "foo", {
54///     let mut params = ferrum_router:recognizer::Params::new();
55///     params.insert("query".into(), "test".into());
56///     params.insert("extraparam".into(), "param".into());
57///     params
58/// })
59/// ```
60#[macro_export]
61macro_rules! uri_for {
62    ($request:expr, $route_id:expr $(,$key:expr => $value:expr)* $(,)*) => (
63        $crate::uri_for(&$request, $route_id, {
64            // Underscore-prefix suppresses `unused_mut` warning
65            // Also works on stable rust!
66            let mut _params = $crate::Params::new();
67            $(_params.insert($key.into(), $value.into());)*
68            _params
69        })
70    )
71}
72
73#[cfg(test)]
74mod tests {
75    use ferrum::{Response, Request, FerrumResult, Method, Handler, Uri};
76    use ferrum::request::HyperRequest;
77    use recognizer::{DefaultStore, DefaultStoreBuild};
78
79    //simple test to check that all methods expand without error
80    #[test]
81    fn test_methods_expand() {
82        fn handler(_: &mut Request) -> FerrumResult<Response> { Ok(Response::new()) }
83        let types = DefaultStore::with_default_types();
84
85        let _ = router!(
86            get "/" => handler "index",
87            get "/{query}" => handler,
88            post "/" => handler "post"
89        );
90
91        let _ = router!(
92            get     "/foo" => handler,
93            post    "/bar/" => handler "a",
94            put     "/bar/baz" => handler "b",
95            delete  "/bar/baz" => handler "c",
96            head    "/foo" => handler "d",
97            patch   "/bar/baz" => handler "e",
98            options "/foo" => handler "f",
99            any     "/" => handler "g",
100            get     "/foo/{id:[0-9]+}" => handler "h",
101            get     ("/foo/{name:string}", &types) => handler "i"
102        );
103    }
104
105    #[test]
106    fn test_uri_for() {
107        fn handler(_: &mut Request) -> FerrumResult<Response> { Ok(Response::new()) }
108        let router = router!(
109            get "/foo" => handler "foo",
110            get "/foo/{bar}" => handler "bar",
111        );
112
113        let mut request = Request::new(
114            HyperRequest::new(Method::Get, "http://www.rust-lang.org/foo".parse().unwrap())
115        );
116        let _response = router.handle(&mut request);
117
118        let uri: Uri = uri_for!(request, "foo",
119                  "query" => "test",
120                  "extraparam" => "param");
121        assert_eq!("http://www.rust-lang.org/foo?extraparam=param&query=test", uri);
122
123        let mut request = Request::new(
124            HyperRequest::new(Method::Get, "http://www.rust-lang.org/foo/foo".parse().unwrap())
125        );
126        let _response = router.handle(&mut request);
127
128        let uri: Uri = uri_for!(request, "bar",
129                  "bar" => "test",
130                  "query" => "param");
131        assert_eq!("http://www.rust-lang.org/foo/test?query=param", uri);
132    }
133}