saphir/
handler.rs

1use futures::{Future, FutureExt};
2
3use crate::{
4    request::Request,
5    responder::{DynResponder, Responder},
6};
7use std::pin::Pin;
8
9/// Define a Handler of a potential http request
10///
11/// Implementing this trait on any type will allow the router to route request
12/// towards it. Implemented by default on Controllers and on any `async
13/// fn(Request<Body>) -> impl Responder`
14pub trait Handler<T> {
15    /// Responder returned by the handler
16    type Responder: Responder;
17    /// Specific future returning the responder
18    type Future: Future<Output = Self::Responder>;
19
20    /// Handle the http request, returning a future of a responder
21    fn handle(&self, req: Request<T>) -> Self::Future;
22}
23
24impl<T, Fun, Fut, R> Handler<T> for Fun
25where
26    Fun: Fn(Request<T>) -> Fut,
27    Fut: 'static + Future<Output = R> + Send,
28    R: Responder,
29{
30    type Future = Box<dyn Future<Output = Self::Responder> + Unpin + Send>;
31    type Responder = R;
32
33    #[inline]
34    fn handle(&self, req: Request<T>) -> Self::Future {
35        Box::new(Box::pin((*self)(req)))
36    }
37}
38
39#[doc(hidden)]
40pub trait DynHandler<T> {
41    fn dyn_handle(&self, req: Request<T>) -> Pin<Box<dyn Future<Output = Box<dyn DynResponder + Send>> + Unpin + Send>>;
42}
43
44impl<T, H, Fut, R> DynHandler<T> for H
45where
46    R: 'static + Responder + Send,
47    Fut: 'static + Future<Output = R> + Unpin + Send,
48    H: Handler<T, Future = Fut, Responder = R>,
49{
50    #[inline]
51    fn dyn_handle(&self, req: Request<T>) -> Pin<Box<dyn Future<Output = Box<dyn DynResponder + Send>> + Unpin + Send>> {
52        Box::pin(self.handle(req).map(|r| Box::new(Some(r)) as Box<dyn DynResponder + Send>))
53    }
54}