axum_codec/
routing.rs

1use std::convert::Infallible;
2
3use axum::routing;
4
5use crate::{
6	handler::{CodecHandlerFn, Input},
7	CodecHandler, IntoCodecResponse,
8};
9
10/// A light wrapper around axum's [`MethodRouter`](axum::routing::MethodRouter)
11/// (or [`ApiMethodRouter`](aide::axum::routing::ApiMethodRouter) if the `aide`
12/// feature is enabled).
13///
14/// However, responses are expected to be [`IntoCodecResponse`] (instead of
15/// [`IntoResponse`](axum::response::IntoResponse)), as they are automatically
16/// converted to the appropriate response type when appropriate.
17pub struct MethodRouter<S = (), E = Infallible> {
18	#[cfg(not(feature = "aide"))]
19	inner: routing::MethodRouter<S, E>,
20	#[cfg(feature = "aide")]
21	inner: aide::axum::routing::ApiMethodRouter<S, E>,
22}
23
24impl<S, E> Clone for MethodRouter<S, E> {
25	fn clone(&self) -> Self {
26		Self {
27			inner: self.inner.clone(),
28		}
29	}
30}
31
32#[cfg(not(feature = "aide"))]
33impl<S, E> From<MethodRouter<S, E>> for routing::MethodRouter<S, E> {
34	fn from(router: MethodRouter<S, E>) -> Self {
35		router.inner
36	}
37}
38
39#[cfg(not(feature = "aide"))]
40impl<S, E> From<routing::MethodRouter<S, E>> for MethodRouter<S, E> {
41	fn from(router: routing::MethodRouter<S, E>) -> Self {
42		Self { inner: router }
43	}
44}
45
46#[cfg(feature = "aide")]
47impl<S, E> From<routing::MethodRouter<S, E>> for MethodRouter<S, E> {
48	fn from(router: routing::MethodRouter<S, E>) -> Self {
49		Self {
50			inner: router.into(),
51		}
52	}
53}
54
55#[cfg(feature = "aide")]
56impl<S, E> From<MethodRouter<S, E>> for routing::MethodRouter<S, E> {
57	fn from(router: MethodRouter<S, E>) -> Self {
58		router.inner.into()
59	}
60}
61
62#[cfg(feature = "aide")]
63impl<S, E> From<aide::axum::routing::ApiMethodRouter<S, E>> for MethodRouter<S, E> {
64	fn from(router: aide::axum::routing::ApiMethodRouter<S, E>) -> Self {
65		Self { inner: router }
66	}
67}
68
69#[cfg(feature = "aide")]
70impl<S, E> From<MethodRouter<S, E>> for aide::axum::routing::ApiMethodRouter<S, E> {
71	fn from(router: MethodRouter<S, E>) -> Self {
72		router.inner
73	}
74}
75
76#[cfg(not(feature = "aide"))]
77macro_rules! method_router_chain_method {
78	($name:ident, $with:ident) => {
79		#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::MethodRouter::", stringify!($name) , "`] for more details.")]
80		#[must_use]
81		pub fn $name<T, H, I, D>(mut self, handler: H) -> Self
82		where
83			H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
84			I: Input + Send + Sync + 'static,
85			D: IntoCodecResponse + Send + 'static,
86			S: Clone + Send + Sync + 'static,
87			T: Sync + 'static
88		{
89			self.inner = self.inner.$name(CodecHandlerFn::new(handler));
90			self
91		}
92  };
93}
94
95#[cfg(feature = "aide")]
96macro_rules! method_router_chain_method {
97	($name:ident, $with:ident) => {
98		#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::MethodRouter::", stringify!($name) , "`] for more details.")]
99		#[must_use]
100		pub fn $name<T, H, I, D>(mut self, handler: H) -> Self
101		where
102			H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
103			I: Input + Send + Sync + 'static,
104			D: IntoCodecResponse + Send + 'static,
105			S: Clone + Send + Sync + 'static,
106			T: Sync + 'static,
107		{
108			self.inner = self.inner.$name(CodecHandlerFn::<H, I, D>::new(handler));
109			self
110		}
111
112		#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::MethodRouter::", stringify!($name) , "`] for more details.")]
113		#[must_use]
114		pub fn $with<T, H, I, D, F>(mut self, handler: H, transform: F) -> Self
115		where
116			H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
117			I: Input + Send + Sync + 'static,
118			D: IntoCodecResponse + Send + 'static,
119			S: Clone + Send + Sync + 'static,
120			T: Sync + 'static,
121			F: FnOnce(aide::transform::TransformOperation) -> aide::transform::TransformOperation,
122		{
123			self.inner = self.inner.$with(CodecHandlerFn::<H, I, D>::new(handler), transform);
124			self
125		}
126  };
127}
128
129impl<S> MethodRouter<S, Infallible>
130where
131	S: Clone + Send + Sync + 'static,
132{
133	method_router_chain_method!(delete, delete_with);
134
135	method_router_chain_method!(get, get_with);
136
137	method_router_chain_method!(head, head_with);
138
139	method_router_chain_method!(options, options_with);
140
141	method_router_chain_method!(patch, patch_with);
142
143	method_router_chain_method!(post, post_with);
144
145	method_router_chain_method!(put, put_with);
146
147	method_router_chain_method!(trace, trace_with);
148}
149
150#[cfg(not(feature = "aide"))]
151macro_rules! method_router_top_level {
152	($name:ident, $with:ident) => {
153		#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::", stringify!($name) , "`] for more details.")]
154		pub fn $name<T, H, I, D, S>(handler: H) -> MethodRouter<S, Infallible>
155		where
156			H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
157			I: Input + Send + Sync + 'static,
158			D: IntoCodecResponse + Send + 'static,
159			S: Clone + Send + Sync + 'static,
160			T: Sync + 'static
161		{
162			MethodRouter::from(routing::$name(CodecHandlerFn::new(handler)))
163		}
164	};
165}
166
167#[cfg(feature = "aide")]
168macro_rules! method_router_top_level {
169	($name:ident, $with:ident) => {
170		#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::", stringify!($name) , "`] for more details.")]
171		pub fn $name<T, H, I, D, S>(handler: H) -> MethodRouter<S, Infallible>
172		where
173			H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
174			I: Input + Send + Sync + 'static,
175			D: IntoCodecResponse + Send + 'static,
176			S: Clone + Send + Sync + 'static,
177			T: Sync + 'static,
178		{
179			MethodRouter::from(aide::axum::routing::$name(
180				CodecHandlerFn::<H, I, D>::new(handler),
181			))
182		}
183
184		#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::", stringify!($name) , "`] for more details.")]
185		#[must_use]
186		pub fn $with<T, H, I, D, S, F>(handler: H, transform: F) -> MethodRouter<S, Infallible>
187		where
188			H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
189			I: Input + Send + Sync + 'static,
190			D: IntoCodecResponse + Send + 'static,
191			S: Clone + Send + Sync + 'static,
192			T: Sync + 'static,
193			F: FnOnce(aide::transform::TransformOperation) -> aide::transform::TransformOperation,
194		{
195			MethodRouter::from(aide::axum::routing::$with(CodecHandlerFn::<H, I, D>::new(handler), transform))
196		}
197	};
198}
199
200method_router_top_level!(delete, delete_with);
201method_router_top_level!(get, get_with);
202method_router_top_level!(head, head_with);
203method_router_top_level!(options, options_with);
204method_router_top_level!(patch, patch_with);
205method_router_top_level!(post, post_with);
206method_router_top_level!(put, put_with);
207method_router_top_level!(trace, trace_with);