Skip to main content

nidus_http/
router.rs

1//! Axum router composition.
2
3mod metadata;
4mod path;
5
6use axum::{Router, handler::Handler, routing};
7use http::Method;
8
9use crate::error::RoutePathError;
10
11pub use metadata::{OpenApiSchemaRegistrar, RouteMetadata};
12pub(crate) use path::{join_normalized_paths, join_paths, normalize_mount_prefix, normalize_path};
13
14/// A route declaration that can be mounted by a controller.
15pub struct RouteDefinition {
16    method: Method,
17    path: String,
18    route: routing::MethodRouter,
19}
20
21impl RouteDefinition {
22    /// Creates a GET route.
23    pub fn get<H, T>(path: impl Into<String>, handler: H) -> Self
24    where
25        H: Handler<T, ()> + Clone + Send + Sync + 'static,
26        T: 'static,
27    {
28        Self::try_get(path, handler).unwrap_or_else(|error| panic!("{error}"))
29    }
30
31    /// Tries to create a GET route.
32    pub fn try_get<H, T>(path: impl Into<String>, handler: H) -> Result<Self, RoutePathError>
33    where
34        H: Handler<T, ()> + Clone + Send + Sync + 'static,
35        T: 'static,
36    {
37        Self::try_new(Method::GET, path, routing::get(handler))
38    }
39
40    /// Creates a POST route.
41    pub fn post<H, T>(path: impl Into<String>, handler: H) -> Self
42    where
43        H: Handler<T, ()> + Clone + Send + Sync + 'static,
44        T: 'static,
45    {
46        Self::try_post(path, handler).unwrap_or_else(|error| panic!("{error}"))
47    }
48
49    /// Tries to create a POST route.
50    pub fn try_post<H, T>(path: impl Into<String>, handler: H) -> Result<Self, RoutePathError>
51    where
52        H: Handler<T, ()> + Clone + Send + Sync + 'static,
53        T: 'static,
54    {
55        Self::try_new(Method::POST, path, routing::post(handler))
56    }
57
58    /// Creates a PUT route.
59    pub fn put<H, T>(path: impl Into<String>, handler: H) -> Self
60    where
61        H: Handler<T, ()> + Clone + Send + Sync + 'static,
62        T: 'static,
63    {
64        Self::try_put(path, handler).unwrap_or_else(|error| panic!("{error}"))
65    }
66
67    /// Tries to create a PUT route.
68    pub fn try_put<H, T>(path: impl Into<String>, handler: H) -> Result<Self, RoutePathError>
69    where
70        H: Handler<T, ()> + Clone + Send + Sync + 'static,
71        T: 'static,
72    {
73        Self::try_new(Method::PUT, path, routing::put(handler))
74    }
75
76    /// Creates a PATCH route.
77    pub fn patch<H, T>(path: impl Into<String>, handler: H) -> Self
78    where
79        H: Handler<T, ()> + Clone + Send + Sync + 'static,
80        T: 'static,
81    {
82        Self::try_patch(path, handler).unwrap_or_else(|error| panic!("{error}"))
83    }
84
85    /// Tries to create a PATCH route.
86    pub fn try_patch<H, T>(path: impl Into<String>, handler: H) -> Result<Self, RoutePathError>
87    where
88        H: Handler<T, ()> + Clone + Send + Sync + 'static,
89        T: 'static,
90    {
91        Self::try_new(Method::PATCH, path, routing::patch(handler))
92    }
93
94    /// Creates a DELETE route.
95    pub fn delete<H, T>(path: impl Into<String>, handler: H) -> Self
96    where
97        H: Handler<T, ()> + Clone + Send + Sync + 'static,
98        T: 'static,
99    {
100        Self::try_delete(path, handler).unwrap_or_else(|error| panic!("{error}"))
101    }
102
103    /// Tries to create a DELETE route.
104    pub fn try_delete<H, T>(path: impl Into<String>, handler: H) -> Result<Self, RoutePathError>
105    where
106        H: Handler<T, ()> + Clone + Send + Sync + 'static,
107        T: 'static,
108    {
109        Self::try_new(Method::DELETE, path, routing::delete(handler))
110    }
111
112    /// Returns the route path.
113    pub fn path(&self) -> &str {
114        &self.path
115    }
116
117    /// Returns the route method.
118    pub fn method(&self) -> &Method {
119        &self.method
120    }
121
122    pub(crate) fn mount(self, router: Router, full_path: String) -> Router {
123        router.route(&full_path, self.route)
124    }
125
126    fn try_new(
127        method: Method,
128        path: impl Into<String>,
129        route: routing::MethodRouter,
130    ) -> Result<Self, RoutePathError> {
131        Ok(Self {
132            method,
133            path: normalize_path(path.into())?,
134            route,
135        })
136    }
137}