1use super::handler::RouteHandler;
2use super::path::normalize_prefix;
3use super::route::RouteDefinition;
4use crate::pipeline::PipelineComponents;
5use crate::{BootRequest, ExceptionFilter, Guard, Interceptor, Pipe, Result, SseEvent};
6use futures_core::Stream;
7use serde::de::DeserializeOwned;
8use serde::Serialize;
9use std::future::Future;
10
11#[derive(Clone)]
13pub struct ControllerDefinition {
14 prefix: String,
15 routes: Vec<RouteDefinition>,
16 pipeline: PipelineComponents,
17}
18
19impl ControllerDefinition {
20 pub fn new(prefix: impl Into<String>) -> Result<Self> {
21 let prefix = normalize_prefix(&prefix.into())?;
22 Ok(Self {
23 prefix,
24 routes: Vec::new(),
25 pipeline: PipelineComponents::default(),
26 })
27 }
28
29 pub fn route(mut self, route: RouteDefinition) -> Result<Self> {
30 self.routes.push(
31 route
32 .with_prefix(&self.prefix)?
33 .with_pipeline_prefix(&self.pipeline),
34 );
35 Ok(self)
36 }
37
38 pub fn with_pipe<P>(mut self, pipe: P) -> Self
39 where
40 P: Pipe,
41 {
42 self.pipeline.push_pipe(pipe);
43 self
44 }
45
46 pub fn with_guard<G>(mut self, guard: G) -> Self
47 where
48 G: Guard,
49 {
50 self.pipeline.push_guard(guard);
51 self
52 }
53
54 pub fn with_interceptor<I>(mut self, interceptor: I) -> Self
55 where
56 I: Interceptor,
57 {
58 self.pipeline.push_interceptor(interceptor);
59 self
60 }
61
62 pub fn with_filter<F>(mut self, filter: F) -> Self
63 where
64 F: ExceptionFilter,
65 {
66 self.pipeline.push_filter(filter);
67 self
68 }
69
70 pub fn get<H>(self, path: impl Into<String>, handler: H) -> Result<Self>
71 where
72 H: RouteHandler,
73 {
74 self.route(RouteDefinition::get(path, handler)?)
75 }
76
77 pub fn get_json<H, Fut, R>(self, path: impl Into<String>, handler: H) -> Result<Self>
78 where
79 H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
80 Fut: Future<Output = Result<R>> + Send + 'static,
81 R: Serialize + Send + 'static,
82 {
83 self.get_json_with_status(path, 200, handler)
84 }
85
86 pub fn get_json_with_status<H, Fut, R>(
87 self,
88 path: impl Into<String>,
89 status: u16,
90 handler: H,
91 ) -> Result<Self>
92 where
93 H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
94 Fut: Future<Output = Result<R>> + Send + 'static,
95 R: Serialize + Send + 'static,
96 {
97 self.route(RouteDefinition::get_json_with_status(
98 path, status, handler,
99 )?)
100 }
101
102 pub fn sse<H, Fut, S>(self, path: impl Into<String>, handler: H) -> Result<Self>
103 where
104 H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
105 Fut: Future<Output = Result<S>> + Send + 'static,
106 S: Stream<Item = Result<SseEvent>> + Send + 'static,
107 {
108 self.route(RouteDefinition::sse(path, handler)?)
109 }
110
111 pub fn post<H>(self, path: impl Into<String>, handler: H) -> Result<Self>
112 where
113 H: RouteHandler,
114 {
115 self.route(RouteDefinition::post(path, handler)?)
116 }
117
118 pub fn post_json<T, H, Fut, R>(self, path: impl Into<String>, handler: H) -> Result<Self>
119 where
120 T: DeserializeOwned + Send + 'static,
121 H: Fn(T) -> Fut + Send + Sync + 'static,
122 Fut: Future<Output = Result<R>> + Send + 'static,
123 R: Serialize + Send + 'static,
124 {
125 self.post_json_with_status(path, 200, handler)
126 }
127
128 pub fn post_json_with_status<T, H, Fut, R>(
129 self,
130 path: impl Into<String>,
131 status: u16,
132 handler: H,
133 ) -> Result<Self>
134 where
135 T: DeserializeOwned + Send + 'static,
136 H: Fn(T) -> Fut + Send + Sync + 'static,
137 Fut: Future<Output = Result<R>> + Send + 'static,
138 R: Serialize + Send + 'static,
139 {
140 self.route(RouteDefinition::post_json_with_status(
141 path, status, handler,
142 )?)
143 }
144
145 pub fn put<H>(self, path: impl Into<String>, handler: H) -> Result<Self>
146 where
147 H: RouteHandler,
148 {
149 self.route(RouteDefinition::put(path, handler)?)
150 }
151
152 pub fn put_json<T, H, Fut, R>(self, path: impl Into<String>, handler: H) -> Result<Self>
153 where
154 T: DeserializeOwned + Send + 'static,
155 H: Fn(T) -> Fut + Send + Sync + 'static,
156 Fut: Future<Output = Result<R>> + Send + 'static,
157 R: Serialize + Send + 'static,
158 {
159 self.put_json_with_status(path, 200, handler)
160 }
161
162 pub fn put_json_with_status<T, H, Fut, R>(
163 self,
164 path: impl Into<String>,
165 status: u16,
166 handler: H,
167 ) -> Result<Self>
168 where
169 T: DeserializeOwned + Send + 'static,
170 H: Fn(T) -> Fut + Send + Sync + 'static,
171 Fut: Future<Output = Result<R>> + Send + 'static,
172 R: Serialize + Send + 'static,
173 {
174 self.route(RouteDefinition::put_json_with_status(
175 path, status, handler,
176 )?)
177 }
178
179 pub fn patch_json<T, H, Fut, R>(self, path: impl Into<String>, handler: H) -> Result<Self>
180 where
181 T: DeserializeOwned + Send + 'static,
182 H: Fn(T) -> Fut + Send + Sync + 'static,
183 Fut: Future<Output = Result<R>> + Send + 'static,
184 R: Serialize + Send + 'static,
185 {
186 self.patch_json_with_status(path, 200, handler)
187 }
188
189 pub fn patch_json_with_status<T, H, Fut, R>(
190 self,
191 path: impl Into<String>,
192 status: u16,
193 handler: H,
194 ) -> Result<Self>
195 where
196 T: DeserializeOwned + Send + 'static,
197 H: Fn(T) -> Fut + Send + Sync + 'static,
198 Fut: Future<Output = Result<R>> + Send + 'static,
199 R: Serialize + Send + 'static,
200 {
201 self.route(RouteDefinition::patch_json_with_status(
202 path, status, handler,
203 )?)
204 }
205
206 pub fn patch<H>(self, path: impl Into<String>, handler: H) -> Result<Self>
207 where
208 H: RouteHandler,
209 {
210 self.route(RouteDefinition::patch(path, handler)?)
211 }
212
213 pub fn delete<H>(self, path: impl Into<String>, handler: H) -> Result<Self>
214 where
215 H: RouteHandler,
216 {
217 self.route(RouteDefinition::delete(path, handler)?)
218 }
219
220 pub fn delete_json<H, Fut, R>(self, path: impl Into<String>, handler: H) -> Result<Self>
221 where
222 H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
223 Fut: Future<Output = Result<R>> + Send + 'static,
224 R: Serialize + Send + 'static,
225 {
226 self.delete_json_with_status(path, 200, handler)
227 }
228
229 pub fn delete_json_with_status<H, Fut, R>(
230 self,
231 path: impl Into<String>,
232 status: u16,
233 handler: H,
234 ) -> Result<Self>
235 where
236 H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
237 Fut: Future<Output = Result<R>> + Send + 'static,
238 R: Serialize + Send + 'static,
239 {
240 self.route(RouteDefinition::delete_json_with_status(
241 path, status, handler,
242 )?)
243 }
244
245 pub fn options<H>(self, path: impl Into<String>, handler: H) -> Result<Self>
246 where
247 H: RouteHandler,
248 {
249 self.route(RouteDefinition::options(path, handler)?)
250 }
251
252 pub fn head<H>(self, path: impl Into<String>, handler: H) -> Result<Self>
253 where
254 H: RouteHandler,
255 {
256 self.route(RouteDefinition::head(path, handler)?)
257 }
258
259 pub fn prefix(&self) -> &str {
260 &self.prefix
261 }
262
263 pub fn routes(&self) -> &[RouteDefinition] {
264 &self.routes
265 }
266
267 pub(crate) fn into_routes(self) -> Vec<RouteDefinition> {
268 self.routes
269 }
270}