1#![allow(non_snake_case)]
4
5use core::{convert::Infallible, marker::PhantomData, net::SocketAddr};
6
7use xitca_service::{Service, pipeline::PipelineE};
8
9use crate::http::{BorrowReq, Extensions, HeaderMap, Method, Request, RequestExt, Uri};
10
11pub fn handler_service<F, T>(func: F) -> HandlerService<F, T, marker::BuilderMark>
17where
18 F: AsyncFn2<T> + Clone,
19{
20 HandlerService::new(func)
21}
22
23pub struct HandlerService<F, T, M> {
24 func: F,
25 _p: PhantomData<fn(T, M)>,
26}
27
28mod marker {
30 pub struct BuilderMark;
31 pub struct ServiceMark;
32}
33
34impl<F, T, M> HandlerService<F, T, M> {
35 pub const fn new(func: F) -> Self {
36 Self { func, _p: PhantomData }
37 }
38}
39
40impl<F, T, M> Clone for HandlerService<F, T, M>
41where
42 F: Clone,
43{
44 fn clone(&self) -> Self {
45 Self::new(self.func.clone())
46 }
47}
48
49impl<F, T> Service for HandlerService<F, T, marker::BuilderMark>
50where
51 F: Clone,
52{
53 type Response = HandlerService<F, T, marker::ServiceMark>;
54 type Error = Infallible;
55
56 async fn call(&self, _: ()) -> Result<Self::Response, Self::Error> {
57 Ok(HandlerService::new(self.func.clone()))
58 }
59}
60
61impl<F, Req, T, O> Service<Req> for HandlerService<F, T, marker::ServiceMark>
62where
63 T: FromRequest<'static, Req>,
65 F: AsyncFn2<T>,
67 F: for<'a> AsyncFn2<T::Type<'a>, Output = O>,
68 O: Responder<Req>,
69 T::Error: From<O::Error>,
70{
71 type Response = O::Response;
72 type Error = T::Error;
73
74 #[inline]
75 async fn call(&self, req: Req) -> Result<Self::Response, Self::Error> {
76 let extract = T::Type::<'_>::from_request(&req).await?;
77 let res = self.func.call(extract).await;
78 res.respond(req).await.map_err(Into::into)
79 }
80}
81
82#[diagnostic::on_unimplemented(
115 message = "`{Self}` does not impl FromRequest trait",
116 label = "handler function arguments must impl FromRequest trait",
117 note = "consider add `impl FromRequest<_> for {Self}`"
118)]
119pub trait FromRequest<'a, Req>: Sized {
120 type Type<'b>: FromRequest<'b, Req, Error = Self::Error>;
122 type Error;
123
124 fn from_request(req: &'a Req) -> impl Future<Output = Result<Self, Self::Error>>;
125}
126
127macro_rules! from_req_impl {
128 ($req0: ident, $($req: ident,)*) => {
129 impl<'a, Req, $req0, $($req,)*> FromRequest<'a, Req> for ($req0, $($req,)*)
130 where
131 $req0: FromRequest<'a, Req>,
132 $(
133 $req: FromRequest<'a, Req>,
134 $req0::Error: From<$req::Error>,
135 )*
136 {
137 type Type<'r> = ($req0::Type<'r>, $($req::Type<'r>,)*);
138 type Error = $req0::Error;
139
140 #[inline]
141 async fn from_request(req: &'a Req) -> Result<Self, Self::Error> {
142 Ok((
143 $req0::from_request(req).await?,
144 $($req::from_request(req).await?,)*
145 ))
146 }
147 }
148 }
149}
150
151from_req_impl! { A, }
152from_req_impl! { A, B, }
153from_req_impl! { A, B, C, }
154from_req_impl! { A, B, C, D, }
155from_req_impl! { A, B, C, D, E, }
156from_req_impl! { A, B, C, D, E, F, }
157from_req_impl! { A, B, C, D, E, F, G, }
158from_req_impl! { A, B, C, D, E, F, G, H, }
159from_req_impl! { A, B, C, D, E, F, G, H, I, }
160
161#[diagnostic::on_unimplemented(
164 message = "`{Self}` does not impl Responder trait",
165 label = "handler function return type must impl Responder trait",
166 note = "consider add `impl Responder<_> for {Self}`"
167)]
168pub trait Responder<Req> {
169 type Response;
170 type Error;
171
172 fn respond(self, req: Req) -> impl Future<Output = Result<Self::Response, Self::Error>>;
174
175 fn map(self, res: Self::Response) -> Result<Self::Response, Self::Error>
178 where
179 Self: Sized,
180 {
181 Ok(res)
182 }
183}
184
185macro_rules! responder_impl {
186 ($res0: ident, $($res: ident,)*) => {
187 #[allow(non_snake_case)]
188 impl<Req, $res0, $($res,)*> Responder<Req> for ($res0, $($res,)*)
189 where
190 $res0: Responder<Req>,
191 $(
192 $res: Responder<Req, Response = $res0::Response>,
193 $res0::Error: From<$res::Error>,
194 )*
195 {
196 type Response = $res0::Response;
197 type Error = $res0::Error;
198
199 async fn respond(self, req: Req) -> Result<Self::Response, Self::Error> {
200 let ($res0, $($res,)*) = self;
201
202 let res = $res0.respond(req).await?;
203 $(
204 let res = $res.map(res)?;
205 )*
206
207 Ok(res)
208 }
209
210 fn map(self, mut res: Self::Response) -> Result<Self::Response, Self::Error> {
211 let ($res0, $($res,)*) = self;
212
213 res = $res0.map(res)?;
214 $(
215 res = $res.map(res)?;
216 )*
217
218 Ok(res)
219 }
220 }
221 }
222}
223
224responder_impl! { A, }
225responder_impl! { A, B, }
226responder_impl! { A, B, C, }
227responder_impl! { A, B, C, D, }
228responder_impl! { A, B, C, D, E, }
229responder_impl! { A, B, C, D, E, F, }
230
231impl<R, F, S> Responder<R> for PipelineE<F, S>
232where
233 F: Responder<R>,
234 S: Responder<R, Response = F::Response>,
235 F::Error: From<S::Error>,
236{
237 type Response = F::Response;
238 type Error = F::Error;
239
240 #[inline]
241 async fn respond(self, req: R) -> Result<Self::Response, Self::Error> {
242 match self {
243 Self::First(f) => f.respond(req).await,
244 Self::Second(s) => s.respond(req).await.map_err(From::from),
245 }
246 }
247
248 #[inline]
249 fn map(self, res: Self::Response) -> Result<Self::Response, Self::Error>
250 where
251 Self: Sized,
252 {
253 match self {
254 Self::First(f) => f.map(res),
255 Self::Second(s) => s.map(res).map_err(From::from),
256 }
257 }
258}
259
260macro_rules! borrow_req_impl {
261 ($tt: tt) => {
262 impl<'a, Ext> FromRequest<'a, Request<Ext>> for &'a $tt {
263 type Type<'b> = &'b $tt;
264 type Error = Infallible;
265
266 #[inline]
267 async fn from_request(req: &'a Request<Ext>) -> Result<Self, Self::Error> {
268 Ok(req.borrow())
269 }
270 }
271 };
272}
273
274borrow_req_impl!(Method);
275borrow_req_impl!(Uri);
276borrow_req_impl!(HeaderMap);
277borrow_req_impl!(Extensions);
278
279impl<'a, Ext> FromRequest<'a, Request<Ext>> for &'a Request<Ext>
280where
281 Ext: 'static,
282{
283 type Type<'b> = &'b Request<Ext>;
284 type Error = Infallible;
285
286 #[inline]
287 async fn from_request(req: &'a Request<Ext>) -> Result<Self, Self::Error> {
288 Ok(req)
289 }
290}
291
292impl<'a, B> FromRequest<'a, Request<RequestExt<B>>> for &'a SocketAddr {
293 type Type<'b> = &'b SocketAddr;
294 type Error = Infallible;
295
296 #[inline]
297 async fn from_request(req: &'a Request<RequestExt<B>>) -> Result<Self, Self::Error> {
298 Ok(req.borrow())
299 }
300}
301
302pub trait AsyncFn2<Arg> {
307 type Output;
308 type Future: Future<Output = Self::Output>;
309
310 fn call(&self, arg: Arg) -> Self::Future;
311}
312
313macro_rules! async_fn_impl {
314 ($($arg: ident),*) => {
315 impl<Func, Fut, $($arg,)*> AsyncFn2<($($arg,)*)> for Func
316 where
317 Func: Fn($($arg),*) -> Fut,
318 Fut: Future,
319 {
320 type Output = Fut::Output;
321 type Future = Fut;
322
323 #[inline]
324 fn call(&self, ($($arg,)*): ($($arg,)*)) -> Self::Future {
325 self($($arg,)*)
326 }
327 }
328 }
329}
330
331async_fn_impl! {}
332async_fn_impl! { A }
333async_fn_impl! { A, B }
334async_fn_impl! { A, B, C }
335async_fn_impl! { A, B, C, D }
336async_fn_impl! { A, B, C, D, E }
337async_fn_impl! { A, B, C, D, E, F }
338async_fn_impl! { A, B, C, D, E, F, G }
339async_fn_impl! { A, B, C, D, E, F, G, H }
340async_fn_impl! { A, B, C, D, E, F, G, H, I }
341
342#[cfg(test)]
343mod test {
344 use xitca_service::ServiceExt;
345 use xitca_unsafe_collection::futures::NowOrPanic;
346
347 use crate::{
348 http::{Response, StatusCode},
349 unspecified_socket_addr,
350 };
351
352 use super::*;
353
354 async fn handler(
355 method: &Method,
356 addr: &SocketAddr,
357 uri: &Uri,
358 headers: &HeaderMap,
359 (_, ext): (&Request<RequestExt<()>>, &Extensions),
360 ) -> StatusCode {
361 assert_eq!(method, Method::GET);
362 assert_eq!(*addr, unspecified_socket_addr());
363 assert_eq!(uri.path(), "/");
364 assert!(headers.is_empty());
365 assert!(ext.is_empty());
366
367 StatusCode::MULTI_STATUS
368 }
369
370 impl Responder<Request<RequestExt<()>>> for StatusCode {
371 type Response = Response<()>;
372 type Error = Infallible;
373
374 async fn respond(self, _: Request<RequestExt<()>>) -> Result<Self::Response, Self::Error> {
375 let mut res = Response::new(());
376 *res.status_mut() = self;
377 Ok(res)
378 }
379 }
380
381 #[test]
382 fn concurrent_extract_with_enclosed_fn() {
383 async fn enclosed<S, Req>(service: &S, req: Req) -> Result<S::Response, S::Error>
384 where
385 S: Service<Req>,
386 {
387 service.call(req).await
388 }
389
390 let res = handler_service(handler)
391 .enclosed_fn(enclosed)
392 .call(())
393 .now_or_panic()
394 .unwrap()
395 .call(Request::default())
396 .now_or_panic()
397 .unwrap();
398
399 assert_eq!(res.status(), StatusCode::MULTI_STATUS);
400 }
401
402 #[cfg(feature = "router")]
403 #[test]
404 fn handler_in_router() {
405 use crate::util::service::{Router, route::get};
406
407 let res = Router::new()
408 .insert("/", get(handler_service(handler)))
409 .call(())
410 .now_or_panic()
411 .unwrap()
412 .call(Request::default())
413 .now_or_panic()
414 .unwrap();
415
416 assert_eq!(res.status(), StatusCode::MULTI_STATUS);
417 }
418}