     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84

    use std::error::Error as StdError;
    use std::fmt;
    use std::marker::PhantomData;

    use crate::body::HttpBody;
    use crate::common::{task, Future, Poll};
    use crate::{Request, Response};

    /// Create a `Service` from a function.
    ///
    /// # Example
    ///
    /// ```
    /// use hyper::{Body, Request, Response, Version};
    /// use hyper::service::service_fn;
    ///
    /// let service = service_fn(|req: Request<Body>| async move {
    ///     if req.version() == Version::HTTP_11 {
    ///         Ok(Response::new(Body::from("Hello World")))
    ///     } else {
    ///         // Note: it's usually better to return a Response
    ///         // with an appropriate StatusCode instead of an Err.
    ///         Err("not HTTP/1.1, abort connection")
    ///     }
    /// });
    /// ```
    pub fn service_fn<F, R, S>(f: F) -> ServiceFn<F, R>
    where
        F: FnMut(Request<R>) -> S,
        S: Future,
    {
        ServiceFn {
            f,
            _req: PhantomData,
        }
    }

    /// Service returned by [`service_fn`]
    pub struct ServiceFn<F, R> {
        f: F,
        _req: PhantomData<fn(R)>,
    }

    impl<F, ReqBody, Ret, ResBody, E> tower_service::Service<crate::Request<ReqBody>>
        for ServiceFn<F, ReqBody>
    where
        F: FnMut(Request<ReqBody>) -> Ret,
        ReqBody: HttpBody,
        Ret: Future<Output = Result<Response<ResBody>, E>>,
        E: Into<Box<dyn StdError + Send + Sync>>,
        ResBody: HttpBody,
    {
        type Response = crate::Response<ResBody>;
        type Error = E;
        type Future = Ret;

        fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
            Poll::Ready(Ok(()))
        }

        fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
            (self.f)(req)
        }
    }

    impl<F, R> fmt::Debug for ServiceFn<F, R> {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            f.debug_struct("impl Service").finish()
        }
    }

    impl<F, R> Clone for ServiceFn<F, R>
    where
        F: Clone,
    {
        fn clone(&self) -> Self {
            ServiceFn {
                f: self.f.clone(),
                _req: PhantomData,
            }
        }
    }

    impl<F, R> Copy for ServiceFn<F, R> where F: Copy {}