1use crate::extract::FromRequest;
58use crate::request::Request;
59use crate::response::{IntoResponse, Response};
60use rustapi_openapi::{Operation, OperationModifier, ResponseModifier};
61use std::future::Future;
62use std::marker::PhantomData;
63use std::pin::Pin;
64
65mod sealed {
66 pub trait Sealed {}
67
68 impl<T> Sealed for T where T: Clone + Send + Sync + Sized + 'static {}
69}
70
71pub trait Handler<T>: sealed::Sealed + Clone + Send + Sync + Sized + 'static {
73 type Future: Future<Output = Response> + Send + 'static;
75
76 fn call(self, req: Request) -> Self::Future;
78
79 fn update_operation(op: &mut Operation);
81
82 fn register_components(spec: &mut rustapi_openapi::OpenApiSpec);
84}
85
86pub struct HandlerService<H, T> {
88 handler: H,
89 _marker: PhantomData<fn() -> T>,
90}
91
92impl<H, T> HandlerService<H, T> {
93 pub fn new(handler: H) -> Self {
94 Self {
95 handler,
96 _marker: PhantomData,
97 }
98 }
99}
100
101impl<H: Clone, T> Clone for HandlerService<H, T> {
102 fn clone(&self) -> Self {
103 Self {
104 handler: self.handler.clone(),
105 _marker: PhantomData,
106 }
107 }
108}
109
110impl<F, Fut, Res> Handler<()> for F
114where
115 F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
116 Fut: Future<Output = Res> + Send + 'static,
117 Res: IntoResponse + ResponseModifier,
118{
119 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
120
121 fn call(self, _req: Request) -> Self::Future {
122 Box::pin(async move { self().await.into_response() })
123 }
124
125 fn update_operation(op: &mut Operation) {
126 Res::update_response(op);
127 }
128
129 fn register_components(spec: &mut rustapi_openapi::OpenApiSpec) {
130 Res::register_components(spec);
131 }
132}
133
134impl<F, Fut, Res, T1> Handler<(T1,)> for F
136where
137 F: FnOnce(T1) -> Fut + Clone + Send + Sync + 'static,
138 Fut: Future<Output = Res> + Send + 'static,
139 Res: IntoResponse + ResponseModifier,
140 T1: FromRequest + OperationModifier + Send + 'static,
141{
142 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
143
144 fn call(self, mut req: Request) -> Self::Future {
145 Box::pin(async move {
146 let t1 = match T1::from_request(&mut req).await {
147 Ok(v) => v,
148 Err(e) => return e.into_response(),
149 };
150 self(t1).await.into_response()
151 })
152 }
153
154 fn update_operation(op: &mut Operation) {
155 T1::update_operation(op);
156 Res::update_response(op);
157 }
158
159 fn register_components(spec: &mut rustapi_openapi::OpenApiSpec) {
160 T1::register_components(spec);
161 Res::register_components(spec);
162 }
163}
164
165impl<F, Fut, Res, T1, T2> Handler<(T1, T2)> for F
167where
168 F: FnOnce(T1, T2) -> Fut + Clone + Send + Sync + 'static,
169 Fut: Future<Output = Res> + Send + 'static,
170 Res: IntoResponse + ResponseModifier,
171 T1: FromRequest + OperationModifier + Send + 'static,
172 T2: FromRequest + OperationModifier + Send + 'static,
173{
174 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
175
176 fn call(self, mut req: Request) -> Self::Future {
177 Box::pin(async move {
178 let t1 = match T1::from_request(&mut req).await {
179 Ok(v) => v,
180 Err(e) => return e.into_response(),
181 };
182 let t2 = match T2::from_request(&mut req).await {
183 Ok(v) => v,
184 Err(e) => return e.into_response(),
185 };
186 self(t1, t2).await.into_response()
187 })
188 }
189
190 fn update_operation(op: &mut Operation) {
191 T1::update_operation(op);
192 T2::update_operation(op);
193 Res::update_response(op);
194 }
195
196 fn register_components(spec: &mut rustapi_openapi::OpenApiSpec) {
197 T1::register_components(spec);
198 T2::register_components(spec);
199 Res::register_components(spec);
200 }
201}
202
203impl<F, Fut, Res, T1, T2, T3> Handler<(T1, T2, T3)> for F
205where
206 F: FnOnce(T1, T2, T3) -> Fut + Clone + Send + Sync + 'static,
207 Fut: Future<Output = Res> + Send + 'static,
208 Res: IntoResponse + ResponseModifier,
209 T1: FromRequest + OperationModifier + Send + 'static,
210 T2: FromRequest + OperationModifier + Send + 'static,
211 T3: FromRequest + OperationModifier + Send + 'static,
212{
213 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
214
215 fn call(self, mut req: Request) -> Self::Future {
216 Box::pin(async move {
217 let t1 = match T1::from_request(&mut req).await {
218 Ok(v) => v,
219 Err(e) => return e.into_response(),
220 };
221 let t2 = match T2::from_request(&mut req).await {
222 Ok(v) => v,
223 Err(e) => return e.into_response(),
224 };
225 let t3 = match T3::from_request(&mut req).await {
226 Ok(v) => v,
227 Err(e) => return e.into_response(),
228 };
229 self(t1, t2, t3).await.into_response()
230 })
231 }
232
233 fn update_operation(op: &mut Operation) {
234 T1::update_operation(op);
235 T2::update_operation(op);
236 T3::update_operation(op);
237 Res::update_response(op);
238 }
239
240 fn register_components(spec: &mut rustapi_openapi::OpenApiSpec) {
241 T1::register_components(spec);
242 T2::register_components(spec);
243 T3::register_components(spec);
244 Res::register_components(spec);
245 }
246}
247
248impl<F, Fut, Res, T1, T2, T3, T4> Handler<(T1, T2, T3, T4)> for F
250where
251 F: FnOnce(T1, T2, T3, T4) -> Fut + Clone + Send + Sync + 'static,
252 Fut: Future<Output = Res> + Send + 'static,
253 Res: IntoResponse + ResponseModifier,
254 T1: FromRequest + OperationModifier + Send + 'static,
255 T2: FromRequest + OperationModifier + Send + 'static,
256 T3: FromRequest + OperationModifier + Send + 'static,
257 T4: FromRequest + OperationModifier + Send + 'static,
258{
259 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
260
261 fn call(self, mut req: Request) -> Self::Future {
262 Box::pin(async move {
263 let t1 = match T1::from_request(&mut req).await {
264 Ok(v) => v,
265 Err(e) => return e.into_response(),
266 };
267 let t2 = match T2::from_request(&mut req).await {
268 Ok(v) => v,
269 Err(e) => return e.into_response(),
270 };
271 let t3 = match T3::from_request(&mut req).await {
272 Ok(v) => v,
273 Err(e) => return e.into_response(),
274 };
275 let t4 = match T4::from_request(&mut req).await {
276 Ok(v) => v,
277 Err(e) => return e.into_response(),
278 };
279 self(t1, t2, t3, t4).await.into_response()
280 })
281 }
282
283 fn update_operation(op: &mut Operation) {
284 T1::update_operation(op);
285 T2::update_operation(op);
286 T3::update_operation(op);
287 T4::update_operation(op);
288 Res::update_response(op);
289 }
290
291 fn register_components(spec: &mut rustapi_openapi::OpenApiSpec) {
292 T1::register_components(spec);
293 T2::register_components(spec);
294 T3::register_components(spec);
295 T4::register_components(spec);
296 Res::register_components(spec);
297 }
298}
299
300impl<F, Fut, Res, T1, T2, T3, T4, T5> Handler<(T1, T2, T3, T4, T5)> for F
302where
303 F: FnOnce(T1, T2, T3, T4, T5) -> Fut + Clone + Send + Sync + 'static,
304 Fut: Future<Output = Res> + Send + 'static,
305 Res: IntoResponse + ResponseModifier,
306 T1: FromRequest + OperationModifier + Send + 'static,
307 T2: FromRequest + OperationModifier + Send + 'static,
308 T3: FromRequest + OperationModifier + Send + 'static,
309 T4: FromRequest + OperationModifier + Send + 'static,
310 T5: FromRequest + OperationModifier + Send + 'static,
311{
312 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
313
314 fn call(self, mut req: Request) -> Self::Future {
315 Box::pin(async move {
316 let t1 = match T1::from_request(&mut req).await {
317 Ok(v) => v,
318 Err(e) => return e.into_response(),
319 };
320 let t2 = match T2::from_request(&mut req).await {
321 Ok(v) => v,
322 Err(e) => return e.into_response(),
323 };
324 let t3 = match T3::from_request(&mut req).await {
325 Ok(v) => v,
326 Err(e) => return e.into_response(),
327 };
328 let t4 = match T4::from_request(&mut req).await {
329 Ok(v) => v,
330 Err(e) => return e.into_response(),
331 };
332 let t5 = match T5::from_request(&mut req).await {
333 Ok(v) => v,
334 Err(e) => return e.into_response(),
335 };
336 self(t1, t2, t3, t4, t5).await.into_response()
337 })
338 }
339
340 fn update_operation(op: &mut Operation) {
341 T1::update_operation(op);
342 T2::update_operation(op);
343 T3::update_operation(op);
344 T4::update_operation(op);
345 T5::update_operation(op);
346 Res::update_response(op);
347 }
348
349 fn register_components(spec: &mut rustapi_openapi::OpenApiSpec) {
350 T1::register_components(spec);
351 T2::register_components(spec);
352 T3::register_components(spec);
353 T4::register_components(spec);
354 T5::register_components(spec);
355 Res::register_components(spec);
356 }
357}
358
359pub(crate) type BoxedHandler =
361 std::sync::Arc<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync>;
362
363pub(crate) fn into_boxed_handler<H, T>(handler: H) -> BoxedHandler
365where
366 H: Handler<T>,
367 T: 'static,
368{
369 std::sync::Arc::new(move |req| {
370 let handler = handler.clone();
371 Box::pin(async move { handler.call(req).await })
372 })
373}
374
375pub trait RouteHandler<T>: Handler<T> {
380 const PATH: &'static str;
382 const METHOD: &'static str;
384}
385
386pub struct Route {
388 pub(crate) path: &'static str,
389 pub(crate) method: &'static str,
390 pub(crate) handler: BoxedHandler,
391 pub(crate) operation: Operation,
392 pub(crate) component_registrar: fn(&mut rustapi_openapi::OpenApiSpec),
393 pub(crate) param_schemas: std::collections::BTreeMap<String, String>,
396 pub(crate) error_responses: Vec<(u16, String)>,
398}
399
400impl Route {
401 pub fn new<H, T>(path: &'static str, method: &'static str, handler: H) -> Self
403 where
404 H: Handler<T>,
405 T: 'static,
406 {
407 let mut operation = Operation::new();
408 H::update_operation(&mut operation);
409
410 Self {
411 path,
412 method,
413 handler: into_boxed_handler(handler),
414 operation,
415 component_registrar: <H as Handler<T>>::register_components,
416 param_schemas: std::collections::BTreeMap::new(),
417 error_responses: Vec::new(),
418 }
419 }
420 pub fn summary(mut self, summary: impl Into<String>) -> Self {
422 self.operation = self.operation.summary(summary);
423 self
424 }
425
426 pub fn description(mut self, description: impl Into<String>) -> Self {
428 self.operation = self.operation.description(description);
429 self
430 }
431
432 pub fn tag(mut self, tag: impl Into<String>) -> Self {
434 self.operation.tags.push(tag.into());
435 self
436 }
437
438 pub fn path(&self) -> &str {
440 self.path
441 }
442
443 pub fn method(&self) -> &str {
445 self.method
446 }
447
448 pub fn param(mut self, name: impl Into<String>, schema_type: impl Into<String>) -> Self {
472 self.param_schemas.insert(name.into(), schema_type.into());
473 self
474 }
475
476 pub fn param_schemas(&self) -> &std::collections::BTreeMap<String, String> {
478 &self.param_schemas
479 }
480
481 pub fn error_response(mut self, status: u16, description: impl Into<String>) -> Self {
499 let desc = description.into();
500 self.error_responses.push((status, desc.clone()));
501
502 let mut content = std::collections::BTreeMap::new();
504 content.insert(
505 "application/json".to_string(),
506 rustapi_openapi::MediaType {
507 schema: Some(rustapi_openapi::SchemaRef::Ref {
508 reference: "#/components/schemas/ErrorSchema".to_string(),
509 }),
510 example: None,
511 },
512 );
513
514 self.operation.responses.insert(
515 status.to_string(),
516 rustapi_openapi::ResponseSpec {
517 description: desc,
518 content,
519 headers: std::collections::BTreeMap::new(),
520 },
521 );
522
523 self
524 }
525
526 pub fn error_responses(&self) -> &[(u16, String)] {
528 &self.error_responses
529 }
530}
531
532#[macro_export]
534macro_rules! route {
535 ($handler:ident) => {{
536 $crate::Route::new($handler::PATH, $handler::METHOD, $handler)
537 }};
538}
539
540pub fn get_route<H, T>(path: &'static str, handler: H) -> Route
542where
543 H: Handler<T>,
544 T: 'static,
545{
546 Route::new(path, "GET", handler)
547}
548
549pub fn post_route<H, T>(path: &'static str, handler: H) -> Route
551where
552 H: Handler<T>,
553 T: 'static,
554{
555 Route::new(path, "POST", handler)
556}
557
558pub fn put_route<H, T>(path: &'static str, handler: H) -> Route
560where
561 H: Handler<T>,
562 T: 'static,
563{
564 Route::new(path, "PUT", handler)
565}
566
567pub fn patch_route<H, T>(path: &'static str, handler: H) -> Route
569where
570 H: Handler<T>,
571 T: 'static,
572{
573 Route::new(path, "PATCH", handler)
574}
575
576pub fn delete_route<H, T>(path: &'static str, handler: H) -> Route
578where
579 H: Handler<T>,
580 T: 'static,
581{
582 Route::new(path, "DELETE", handler)
583}