hyper/service/
make.rs

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