hyper/service/
make.rs

1use std::error::Error as StdError;
2use std::fmt;
3
4use tokio::io::{AsyncRead, AsyncWrite};
5
6use super::{HttpService, Service};
7use crate::body::HttpBody;
8use crate::common::{task, Future, Poll};
9
10// The same "trait alias" as tower::MakeConnection, but inlined to reduce
11// dependencies.
12pub trait MakeConnection<Target>: self::sealed::Sealed<(Target,)> {
13    type Connection: AsyncRead + AsyncWrite;
14    type Error;
15    type Future: Future<Output = Result<Self::Connection, Self::Error>>;
16
17    fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
18    fn make_connection(&mut self, target: Target) -> Self::Future;
19}
20
21impl<S, Target> self::sealed::Sealed<(Target,)> for S where S: Service<Target> {}
22
23impl<S, Target> MakeConnection<Target> for S
24where
25    S: Service<Target>,
26    S::Response: AsyncRead + AsyncWrite,
27{
28    type Connection = S::Response;
29    type Error = S::Error;
30    type Future = S::Future;
31
32    fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
33        Service::poll_ready(self, cx)
34    }
35
36    fn make_connection(&mut self, target: Target) -> Self::Future {
37        Service::call(self, target)
38    }
39}
40
41// Just a sort-of "trait alias" of `MakeService`, not to be implemented
42// by anyone, only used as bounds.
43pub trait MakeServiceRef<Target, ReqBody>: self::sealed::Sealed<(Target, ReqBody)> {
44    type ResBody: HttpBody;
45    type Error: Into<Box<dyn StdError + Send + Sync>>;
46    type Service: HttpService<ReqBody, ResBody = Self::ResBody, Error = Self::Error>;
47    type MakeError: Into<Box<dyn StdError + Send + Sync>>;
48    type Future: Future<Output = Result<Self::Service, Self::MakeError>>;
49
50    // Acting like a #[non_exhaustive] for associated types of this trait.
51    //
52    // Basically, no one outside of hyper should be able to set this type
53    // or declare bounds on it, so it should prevent people from creating
54    // trait objects or otherwise writing code that requires using *all*
55    // of the associated types.
56    //
57    // Why? So we can add new associated types to this alias in the future,
58    // if necessary.
59    type __DontNameMe: self::sealed::CantImpl;
60
61    fn poll_ready_ref(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::MakeError>>;
62
63    fn make_service_ref(&mut self, target: &Target) -> Self::Future;
64}
65
66impl<T, Target, E, ME, S, F, IB, OB> MakeServiceRef<Target, IB> for T
67where
68    T: for<'a> Service<&'a Target, Error = ME, Response = S, Future = F>,
69    E: Into<Box<dyn StdError + Send + Sync>>,
70    ME: Into<Box<dyn StdError + Send + Sync>>,
71    S: HttpService<IB, ResBody = OB, Error = E>,
72    F: Future<Output = Result<S, ME>>,
73    IB: HttpBody,
74    OB: HttpBody,
75{
76    type Error = E;
77    type Service = S;
78    type ResBody = OB;
79    type MakeError = ME;
80    type Future = F;
81
82    type __DontNameMe = self::sealed::CantName;
83
84    fn poll_ready_ref(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::MakeError>> {
85        self.poll_ready(cx)
86    }
87
88    fn make_service_ref(&mut self, target: &Target) -> Self::Future {
89        self.call(target)
90    }
91}
92
93impl<T, Target, S, B1, B2> self::sealed::Sealed<(Target, B1)> for T
94where
95    T: for<'a> Service<&'a Target, Response = S>,
96    S: HttpService<B1, ResBody = B2>,
97    B1: HttpBody,
98    B2: HttpBody,
99{
100}
101
102/// Create a `MakeService` from a function.
103///
104/// # Example
105///
106/// ```
107/// # #[cfg(feature = "runtime")]
108/// # async fn run() {
109/// use std::convert::Infallible;
110/// use hyper::{Body, Request, Response, Server};
111/// use hyper::server::conn::AddrStream;
112/// use hyper::service::{make_service_fn, service_fn};
113///
114/// let addr = ([127, 0, 0, 1], 3000).into();
115///
116/// let make_svc = make_service_fn(|socket: &AddrStream| {
117///     let remote_addr = socket.remote_addr();
118///     async move {
119///         Ok::<_, Infallible>(service_fn(move |_: Request<Body>| async move {
120///             Ok::<_, Infallible>(
121///                 Response::new(Body::from(format!("Hello, {}!", remote_addr)))
122///             )
123///         }))
124///     }
125/// });
126///
127/// // Then bind and serve...
128/// let server = Server::bind(&addr)
129///     .serve(make_svc);
130///
131/// // Finally, spawn `server` onto an Executor...
132/// if let Err(e) = server.await {
133///     eprintln!("server error: {}", e);
134/// }
135/// # }
136/// # fn main() {}
137/// ```
138pub fn make_service_fn<F, Target, Ret>(f: F) -> MakeServiceFn<F>
139where
140    F: FnMut(&Target) -> Ret,
141    Ret: Future,
142{
143    MakeServiceFn { f }
144}
145
146/// `MakeService` returned from [`make_service_fn`]
147#[derive(Clone, Copy)]
148pub struct MakeServiceFn<F> {
149    f: F,
150}
151
152impl<'t, F, Ret, Target, Svc, MkErr> Service<&'t Target> for MakeServiceFn<F>
153where
154    F: FnMut(&Target) -> Ret,
155    Ret: Future<Output = Result<Svc, MkErr>>,
156    MkErr: Into<Box<dyn StdError + Send + Sync>>,
157{
158    type Error = MkErr;
159    type Response = Svc;
160    type Future = Ret;
161
162    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
163        Poll::Ready(Ok(()))
164    }
165
166    fn call(&mut self, target: &'t Target) -> Self::Future {
167        (self.f)(target)
168    }
169}
170
171impl<F> fmt::Debug for MakeServiceFn<F> {
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        f.debug_struct("MakeServiceFn").finish()
174    }
175}
176
177mod sealed {
178    pub trait Sealed<X> {}
179
180    #[allow(unreachable_pub)] // This is intentional.
181    pub trait CantImpl {}
182
183    #[allow(missing_debug_implementations)]
184    pub enum CantName {}
185
186    impl CantImpl for CantName {}
187}