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