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}