Skip to main content

trillium_router/
router_ref.rs

1use crate::Router;
2use routefinder::RouteSpec;
3use std::fmt::Debug;
4use trillium::{Handler, Method};
5
6macro_rules! method_ref {
7    ($fn_name:ident, $method:ident) => {
8        method_ref!(
9            $fn_name,
10            $method,
11            concat!(
12                // yep, macro-generated doctests
13                "Registers a handler for the ",
14                stringify!($fn_name),
15                " http method.
16
17```
18# use trillium::Conn;
19# use trillium_router::Router;
20let router = Router::build(|mut router| {
21    router.",
22                stringify!($fn_name),
23                "(\"/some/route\", |conn: Conn| async move {
24        conn.ok(\"success\")
25    });
26});
27
28use trillium_testing::{methods::",
29                stringify!($fn_name),
30                ", assert_ok, assert_not_handled};
31assert_ok!(",
32                stringify!($fn_name),
33                "(\"/some/route\").on(&router), \"success\");
34assert_not_handled!(",
35                stringify!($fn_name),
36                "(\"/other/route\").on(&router));
37```
38"
39            )
40        );
41    };
42
43    ($fn_name:ident, $method:ident, $doc_comment:expr) => {
44        #[doc = $doc_comment]
45        pub fn $fn_name<R>(&mut self, path: R, handler: impl Handler)
46        where
47            R: TryInto<RouteSpec>,
48            R::Error: Debug,
49        {
50            self.0.add(path, Method::$method, handler);
51        }
52    };
53}
54
55/**
56# A `&mut Router` for use with `Router::build`
57
58A wrapper around a `&mut Router` that supports imperative route
59registration. See [`Router::build`] for further documentation.
60*/
61#[derive(Debug)]
62pub struct RouterRef<'r>(&'r mut Router);
63impl<'r> RouterRef<'r> {
64    method_ref!(get, Get);
65    method_ref!(post, Post);
66    method_ref!(put, Put);
67    method_ref!(delete, Delete);
68    method_ref!(patch, Patch);
69
70    /**
71    Appends the handler to all (get, post, put, delete, and patch) methods.
72
73    ```
74    # use trillium::Conn;
75    # use trillium_router::Router;
76    let router = Router::build(|mut router| {
77        router.all("/any", |conn: Conn| async move {
78            let response = format!("you made a {} request to /any", conn.method());
79            conn.ok(response)
80        });
81    });
82
83    use trillium_testing::prelude::*;
84    assert_ok!(get("/any").on(&router), "you made a GET request to /any");
85    assert_ok!(post("/any").on(&router), "you made a POST request to /any");
86    assert_ok!(delete("/any").on(&router), "you made a DELETE request to /any");
87    assert_ok!(patch("/any").on(&router), "you made a PATCH request to /any");
88    assert_ok!(put("/any").on(&router), "you made a PUT request to /any");
89
90    assert_not_handled!(get("/").on(&router));
91    ```
92
93    */
94    pub fn all<R>(&mut self, path: R, handler: impl Handler)
95    where
96        R: TryInto<RouteSpec>,
97        R::Error: Debug,
98    {
99        self.0.add_all(path, handler)
100    }
101
102    /**
103    Appends the handler to each of the provided http methods.
104    ```
105    # use trillium::Conn;
106    # use trillium_router::Router;
107    let router = Router::build(|mut router|{
108        router.any(&["get", "post"], "/get_or_post", |conn: Conn| async move {
109            let response = format!("you made a {} request to /get_or_post", conn.method());
110            conn.ok(response)
111        });
112    });
113
114    use trillium_testing::prelude::*;
115    assert_ok!(get("/get_or_post").on(&router), "you made a GET request to /get_or_post");
116    assert_ok!(post("/get_or_post").on(&router), "you made a POST request to /get_or_post");
117    assert_not_handled!(delete("/any").on(&router));
118    assert_not_handled!(patch("/any").on(&router));
119    assert_not_handled!(put("/any").on(&router));
120    assert_not_handled!(get("/").on(&router));
121    ```
122    */
123    pub fn any<IntoMethod, R>(&mut self, methods: &[IntoMethod], path: R, handler: impl Handler)
124    where
125        R: TryInto<RouteSpec>,
126        R::Error: Debug,
127        IntoMethod: TryInto<Method> + Clone,
128        <IntoMethod as TryInto<Method>>::Error: Debug,
129    {
130        let methods = methods
131            .iter()
132            .cloned()
133            .map(|m| m.try_into().unwrap())
134            .collect::<Vec<_>>();
135
136        self.0.add_any(&methods, path, handler);
137    }
138
139    pub(crate) fn new(router: &'r mut Router) -> Self {
140        Self(router)
141    }
142    /**
143    Registers a handler for a method other than get, put, post, patch, or delete.
144    ```
145    # use trillium::{Conn, Method};
146    # use trillium_router::Router;
147    let router = Router::build(|mut router| {
148        router.add_route("OPTIONS", "/some/route", |conn: Conn| async move {
149            conn.ok("directly handling options")
150        });
151
152        router.add_route(Method::Checkin, "/some/route", |conn: Conn| async move {
153            conn.ok("checkin??")
154        });
155    });
156
157    use trillium_testing::{prelude::*, TestConn};
158    assert_ok!(TestConn::build(Method::Options, "/some/route", ()).on(&router), "directly handling options");
159    assert_ok!(TestConn::build("checkin", "/some/route", ()).on(&router), "checkin??");
160    ```
161    */
162    pub fn add_route<M, R>(&mut self, method: M, path: R, handler: impl Handler)
163    where
164        M: TryInto<Method>,
165        <M as TryInto<Method>>::Error: Debug,
166        R: TryInto<RouteSpec>,
167        R::Error: Debug,
168    {
169        self.0.add(path, method.try_into().unwrap(), handler);
170    }
171
172    /**
173    enable or disable the router's behavior of responding to OPTIONS
174    requests with the supported methods at given path.
175
176    default: enabled
177
178    see crate-level docs for further explanation of the default behavior.
179     */
180    pub fn set_options_handling(&mut self, options_enabled: bool) {
181        self.0.set_options_handling(options_enabled);
182    }
183}