1 | use std::error::Error as StdError; |
2 | use std::fmt; |
3 | use std::marker::PhantomData; |
4 | |
5 | use crate::body::HttpBody; |
6 | use crate::common::{task, Future, Poll}; |
7 | use crate::{Request, Response}; |
8 | |
9 | /// Create a `Service` from a function. |
10 | /// |
11 | /// # Example |
12 | /// |
13 | /// ``` |
14 | /// use hyper::{Body, Request, Response, Version}; |
15 | /// use hyper::service::service_fn; |
16 | /// |
17 | /// let service = service_fn(|req: Request<Body>| async move { |
18 | /// if req.version() == Version::HTTP_11 { |
19 | /// Ok(Response::new(Body::from("Hello World" ))) |
20 | /// } else { |
21 | /// // Note: it's usually better to return a Response |
22 | /// // with an appropriate StatusCode instead of an Err. |
23 | /// Err("not HTTP/1.1, abort connection" ) |
24 | /// } |
25 | /// }); |
26 | /// ``` |
27 | pub fn service_fn<F, R, S>(f: F) -> ServiceFn<F, R> |
28 | where |
29 | F: FnMut(Request<R>) -> S, |
30 | S: Future, |
31 | { |
32 | ServiceFn { |
33 | f, |
34 | _req: PhantomData, |
35 | } |
36 | } |
37 | |
38 | /// Service returned by [`service_fn`] |
39 | pub struct ServiceFn<F, R> { |
40 | f: F, |
41 | _req: PhantomData<fn(R)>, |
42 | } |
43 | |
44 | impl<F, ReqBody, Ret, ResBody, E> tower_service::Service<crate::Request<ReqBody>> |
45 | for ServiceFn<F, ReqBody> |
46 | where |
47 | F: FnMut(Request<ReqBody>) -> Ret, |
48 | ReqBody: HttpBody, |
49 | Ret: Future<Output = Result<Response<ResBody>, E>>, |
50 | E: Into<Box<dyn StdError + Send + Sync>>, |
51 | ResBody: HttpBody, |
52 | { |
53 | type Response = crate::Response<ResBody>; |
54 | type Error = E; |
55 | type Future = Ret; |
56 | |
57 | fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> { |
58 | Poll::Ready(Ok(())) |
59 | } |
60 | |
61 | fn call(&mut self, req: Request<ReqBody>) -> Self::Future { |
62 | (self.f)(req) |
63 | } |
64 | } |
65 | |
66 | impl<F, R> fmt::Debug for ServiceFn<F, R> { |
67 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
68 | f.debug_struct(name:"impl Service" ).finish() |
69 | } |
70 | } |
71 | |
72 | impl<F, R> Clone for ServiceFn<F, R> |
73 | where |
74 | F: Clone, |
75 | { |
76 | fn clone(&self) -> Self { |
77 | ServiceFn { |
78 | f: self.f.clone(), |
79 | _req: PhantomData, |
80 | } |
81 | } |
82 | } |
83 | |
84 | impl<F, R> Copy for ServiceFn<F, R> where F: Copy {} |
85 | |