Skip to main content

trillium_router/
router_conn_ext.rs

1use crate::{CapturesNewType, RouteSpecNewType};
2use trillium::Conn;
3
4/// Extends trillium::Conn with accessors for router params.
5pub trait RouterConnExt {
6    /// Retrieves a captured param from the conn. Note that this will only
7    /// be Some if the exact param is present in the matched route.
8    ///
9    /// Routefinder params are defined starting with a colon, but the
10    /// colon is not needed when fetching the param.
11    ///
12    /// ```
13    /// use trillium::{Conn, conn_unwrap};
14    /// use trillium_router::{Router, RouterConnExt};
15    /// use trillium_testing::TestServer;
16    ///
17    /// # trillium_testing::block_on(async {
18    /// let router = Router::new().get("/pages/:page_name", |conn: Conn| async move {
19    ///     let page_name = conn_unwrap!(conn.param("page_name"), conn);
20    ///     let content = format!("you have reached the page named {}", page_name);
21    ///     conn.ok(content)
22    /// });
23    ///
24    /// let app = TestServer::new(router).await;
25    /// app.get("/pages/trillium")
26    ///     .await
27    ///     .assert_ok()
28    ///     .assert_body("you have reached the page named trillium");
29    /// # });
30    /// ```
31    fn param<'a>(&'a self, param: &str) -> Option<&'a str>;
32
33    /// Retrieves the wildcard match from the conn. Note that this will
34    /// only be Some if the matched route contains a wildcard, as
35    /// expressed by a "*" in the routefinder route spec.
36    ///
37    /// ```
38    /// use trillium::{Conn, conn_unwrap};
39    /// use trillium_router::{Router, RouterConnExt};
40    /// use trillium_testing::TestServer;
41    ///
42    /// # trillium_testing::block_on(async {
43    /// let router = Router::new().get("/pages/*", |conn: Conn| async move {
44    ///     let wildcard = conn_unwrap!(conn.wildcard(), conn);
45    ///     let content = format!("the wildcard matched {}", wildcard);
46    ///     conn.ok(content)
47    /// });
48    ///
49    /// let app = TestServer::new(router).await;
50    /// app.get("/pages/this/is/a/wildcard/match")
51    ///     .await
52    ///     .assert_ok()
53    ///     .assert_body("the wildcard matched this/is/a/wildcard/match");
54    /// # });
55    /// ```
56    fn wildcard(&self) -> Option<&str>;
57
58    /// Retrieves the matched route specification
59    /// ```
60    /// use trillium::{Conn, conn_unwrap};
61    /// use trillium_router::{Router, RouterConnExt};
62    /// use trillium_testing::TestServer;
63    ///
64    /// # trillium_testing::block_on(async {
65    /// let router = Router::new().get("/pages/:page_id", |conn: Conn| async move {
66    ///     let route = conn_unwrap!(conn.route(), conn).to_string();
67    ///     conn.ok(format!("route was {route}"))
68    /// });
69    ///
70    /// let app = TestServer::new(router).await;
71    /// app.get("/pages/12345")
72    ///     .await
73    ///     .assert_ok()
74    ///     .assert_body("route was /pages/:page_id");
75    /// # });
76    /// ```
77    fn route(&self) -> Option<&str>;
78}
79
80impl RouterConnExt for Conn {
81    fn param<'a>(&'a self, param: &str) -> Option<&'a str> {
82        self.state().and_then(|CapturesNewType(p)| p.get(param))
83    }
84
85    fn wildcard(&self) -> Option<&str> {
86        self.state().and_then(|CapturesNewType(p)| p.wildcard())
87    }
88
89    fn route(&self) -> Option<&str> {
90        self.state().and_then(|RouteSpecNewType(r)| r.source())
91    }
92}