1use std::future::Future;
2use std::pin::Pin;
3use crate::{Request, Response};
4
5pub trait Handler<T>: Clone + Send + Sync + 'static {
7 type Future: Future<Output = Response> + Send + 'static;
9
10 fn call(&self, req: Request) -> Self::Future;
12}
13
14pub type HandlerFn = std::sync::Arc<
16 dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send + 'static>>
17 + Send
18 + Sync
19 + 'static,
20>;
21
22impl<F, Fut> Handler<()> for F
24where
25 F: Fn(Request) -> Fut + Clone + Send + Sync + 'static,
26 Fut: Future<Output = Response> + Send + 'static,
27{
28 type Future = Fut;
29
30 fn call(&self, req: Request) -> Self::Future {
31 self(req)
32 }
33}
34
35impl<F> Handler<((),)> for F
37where
38 F: Fn(Request) -> Response + Clone + Send + Sync + 'static,
39{
40 type Future = Pin<Box<dyn Future<Output = Response> + Send + 'static>>;
41
42 fn call(&self, req: Request) -> Self::Future {
43 let response = self(req);
44 Box::pin(async move { response })
45 }
46}
47
48pub fn into_handler_fn<H, T>(handler: H) -> HandlerFn
50where
51 H: Handler<T>,
52{
53 std::sync::Arc::new(move |req| Box::pin(handler.call(req)))
54}
55
56#[macro_export]
58macro_rules! handler {
59 ($body:expr) => {
60 |_req: $crate::Request| async move { $body }
61 };
62 ($req:ident => $body:expr) => {
63 |$req: $crate::Request| async move { $body }
64 };
65}
66
67#[cfg(disabled_for_now)]
68mod tests {
69 use super::*;
70 use crate::Response;
71
72 #[tokio::test]
73 async fn test_async_handler() {
74 let handler = |_req: Request| async {
75 Response::ok().body("Hello from async handler")
76 };
77
78 let req = Request::from_hyper(
79 http::Request::builder()
80 .method("GET")
81 .uri("/")
82 .body(())
83 .unwrap()
84 .into_parts()
85 .0,
86 Vec::new(),
87 )
88 .await
89 .unwrap();
90
91 let response = handler.call(req).await;
92 assert_eq!(response.body_data(), b"Hello from async handler");
93 }
94
95 #[tokio::test]
96 async fn test_sync_handler() {
97 let handler = |_req: Request| Response::ok().body("Hello from sync handler");
98
99 let req = Request::from_hyper(
100 http::Request::builder()
101 .method("GET")
102 .uri("/")
103 .body(())
104 .unwrap()
105 .into_parts()
106 .0,
107 Vec::new(),
108 )
109 .await
110 .unwrap();
111
112 let response = handler.call(req).await;
113 assert_eq!(response.body_data(), b"Hello from sync handler");
114 }
115
116 #[test]
117 fn test_handler_macro() {
118 let _handler1 = handler!(Response::ok().body("Simple response"));
119 let _handler2 = handler!(req => {
120 Response::ok().body(format!("Path: {}", req.path()))
121 });
122 }
123}