1use crate::body::ResponseBody;
9use crate::fn_trait::FnTrait;
10
11use crate::responder::Responder;
12use crate::{OptionReqBody, RequestContext};
13use async_trait::async_trait;
14use http::Response;
15
16use crate::extract::FromRequest;
17use std::marker::PhantomData;
18
19#[async_trait]
24pub trait RequestHandler: Send + Sync {
25 async fn invoke<'server, 'req>(&self, req: &mut RequestContext<'server, 'req>, req_body: OptionReqBody) -> Response<ResponseBody>;
26}
27
28#[async_trait]
29impl<T> RequestHandler for Box<T>
30where
31 T: RequestHandler,
32{
33 async fn invoke<'server, 'req>(&self, req: &mut RequestContext<'server, 'req>, req_body: OptionReqBody) -> Response<ResponseBody> {
34 (**self).invoke(req, req_body).await
35 }
36}
37
38#[async_trait]
39impl RequestHandler for Box<dyn RequestHandler> {
40 async fn invoke<'server, 'req>(&self, req: &mut RequestContext<'server, 'req>, req_body: OptionReqBody) -> Response<ResponseBody> {
41 (**self).invoke(req, req_body).await
42 }
43}
44
45#[async_trait]
46impl RequestHandler for &dyn RequestHandler {
47 async fn invoke<'server, 'req>(&self, req: &mut RequestContext<'server, 'req>, req_body: OptionReqBody) -> Response<ResponseBody> {
48 (**self).invoke(req, req_body).await
49 }
50}
51
52pub struct FnHandler<F, Args> {
61 f: F,
62 _phantom: PhantomData<fn(Args)>,
63}
64
65impl<F, Args> FnHandler<F, Args>
66where
67 F: FnTrait<Args>,
68{
69 fn new(f: F) -> Self {
70 Self { f, _phantom: PhantomData }
71 }
72}
73
74pub fn handler_fn<F, Args>(f: F) -> FnHandler<F, Args>
78where
79 F: FnTrait<Args>,
80{
81 FnHandler::new(f)
82}
83
84#[async_trait]
85impl<F, Args> RequestHandler for FnHandler<F, Args>
86where
87 Args: FromRequest,
90 for<'r> F: FnTrait<Args::Output<'r>>,
93 for<'r> <F as FnTrait<Args::Output<'r>>>::Output: Responder,
96{
97 async fn invoke<'server, 'req>(&self, req: &mut RequestContext<'server, 'req>, req_body: OptionReqBody) -> Response<ResponseBody> {
98 let args = match Args::from_request(req, req_body.clone()).await {
99 Ok(args) => args,
100 Err(responder) => return responder.response_to(req),
101 };
102 let responder = self.f.call(args).await;
103 responder.response_to(req)
104 }
105}
106
107#[cfg(test)]
108mod test {
109 use crate::fn_trait::FnTrait;
110 use crate::handler::{FnHandler, RequestHandler};
111
112 use http::Method;
113
114 fn assert_is_fn_handler<H: FnTrait<Args>, Args>(_handler: &FnHandler<H, Args>) {
115 }
117
118 fn assert_is_handler<T: RequestHandler>(_handler: &T) {
119 }
121
122 #[test]
123 fn assert_fn_is_http_handler_1() {
124 async fn get(_header: Method) {}
125
126 let http_handler = FnHandler::new(get);
127 assert_is_fn_handler(&http_handler);
128 assert_is_handler(&http_handler);
129 }
130
131 #[test]
132 fn assert_fn_is_http_handler_2() {
133 async fn get(_header: &Method, _str: String) {}
134
135 let http_handler = FnHandler::new(get);
136 assert_is_fn_handler(&http_handler);
137 assert_is_handler(&http_handler);
138 }
139}