Skip to main content

trillium_router/
lib.rs

1#![forbid(unsafe_code)]
2#![deny(
3    clippy::dbg_macro,
4    missing_copy_implementations,
5    rustdoc::missing_crate_level_docs,
6    missing_debug_implementations,
7    missing_docs,
8    nonstandard_style,
9    unused_qualifications
10)]
11
12/*!
13# Welcome to the trillium router crate!
14
15This router is built on top of
16[routefinder](https://github.com/jbr/routefinder), and the details of
17route resolution and definition are documented on that repository.
18
19```
20use trillium::{conn_unwrap, Conn};
21use trillium_router::{Router, RouterConnExt};
22
23let router = Router::new()
24    .get("/", |conn: Conn| async move { conn.ok("you have reached the index") })
25    .get("/pages/:page_name", |conn: Conn| async move {
26        let page_name = conn_unwrap!(conn.param("page_name"), conn);
27        let content = format!("you have reached the page named {}", page_name);
28        conn.ok(content)
29    });
30
31use trillium_testing::prelude::*;
32assert_ok!(get("/").on(&router), "you have reached the index");
33assert_ok!(get("/pages/trillium").on(&router), "you have reached the page named trillium");
34assert_not_handled!(get("/unknown/route").on(&router));
35```
36
37Although this is currently the only trillium router, it is an
38important aspect of trillium's architecture that the router uses only
39public apis and is interoperable with other router implementations. If
40you have different ideas of how a router might work, please publish a
41crate! It should be possible to nest different types of routers (and
42different versions of router crates) within each other as long as they
43all depend on the same version of the `trillium` crate.
44
45## Options handling
46
47By default, the trillium router will reply to an OPTIONS request with
48the list of supported http methods at the given route. If the OPTIONS
49request is sent for `*`, it responds with the full set of http methods
50supported by this router.
51
52**Note:** This behavior is superceded by an explicit OPTIONS handler
53or an `any` handler.
54
55To disable the default OPTIONS behavior, use
56[`Router::without_options_handling`] or
57[`RouterRef::set_options_handling`]
58*/
59
60mod router;
61pub use router::Router;
62
63mod router_ref;
64pub use router_ref::RouterRef;
65
66mod router_conn_ext;
67pub use router_conn_ext::RouterConnExt;
68
69/**
70The routes macro represents an experimental macro for defining
71routers.
72
73**stability note:** this may be removed entirely if it is not widely
74used. please open an issue if you like it, or if you have ideas to
75improve it.
76
77```
78use trillium::{conn_unwrap, Conn};
79use trillium_router::{routes, RouterConnExt};
80
81let router = routes!(
82    get "/" |conn: Conn| async move { conn.ok("you have reached the index") },
83    get "/pages/:page_name" |conn: Conn| async move {
84        let page_name = conn_unwrap!(conn.param("page_name"), conn);
85        let content = format!("you have reached the page named {}", page_name);
86        conn.ok(content)
87    }
88);
89
90use trillium_testing::prelude::*;
91assert_ok!(get("/").on(&router), "you have reached the index");
92assert_ok!(get("/pages/trillium").on(&router), "you have reached the page named trillium");
93assert_not_handled!(get("/unknown/route").on(&router));
94```
95*/
96#[macro_export]
97macro_rules! routes {
98    ($($method:ident $path:literal $(-> )?$handler:expr),+ $(,)?) => {
99	$crate::Router::new()$(
100            .$method($path, $handler)
101        )+;
102    };
103}
104
105/// Builds a new [`Router`]. Alias for [`Router::new`].
106pub fn router() -> Router {
107    Router::new()
108}
109
110pub(crate) struct CapturesNewType<'a, 'b>(routefinder::Captures<'a, 'b>);
111pub(crate) struct RouteSpecNewType(routefinder::RouteSpec);