use std::error::Error as StdError; use std::fmt; use tokio::io::{AsyncRead, AsyncWrite}; use super::{HttpService, Service}; use crate::body::HttpBody; use crate::common::{task, Future, Poll}; // The same "trait alias" as tower::MakeConnection, but inlined to reduce // dependencies. pub trait MakeConnection: self::sealed::Sealed<(Target,)> { type Connection: AsyncRead + AsyncWrite; type Error; type Future: Future>; fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll>; fn make_connection(&mut self, target: Target) -> Self::Future; } impl self::sealed::Sealed<(Target,)> for S where S: Service {} impl MakeConnection for S where S: Service, S::Response: AsyncRead + AsyncWrite, { type Connection = S::Response; type Error = S::Error; type Future = S::Future; fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll> { Service::poll_ready(self, cx) } fn make_connection(&mut self, target: Target) -> Self::Future { Service::call(self, target) } } // Just a sort-of "trait alias" of `MakeService`, not to be implemented // by anyone, only used as bounds. pub trait MakeServiceRef: self::sealed::Sealed<(Target, ReqBody)> { type ResBody: HttpBody; type Error: Into>; type Service: HttpService; type MakeError: Into>; type Future: Future>; // Acting like a #[non_exhaustive] for associated types of this trait. // // Basically, no one outside of hyper should be able to set this type // or declare bounds on it, so it should prevent people from creating // trait objects or otherwise writing code that requires using *all* // of the associated types. // // Why? So we can add new associated types to this alias in the future, // if necessary. type __DontNameMe: self::sealed::CantImpl; fn poll_ready_ref(&mut self, cx: &mut task::Context<'_>) -> Poll>; fn make_service_ref(&mut self, target: &Target) -> Self::Future; } impl MakeServiceRef for T where T: for<'a> Service<&'a Target, Error = ME, Response = S, Future = F>, E: Into>, ME: Into>, S: HttpService, F: Future>, IB: HttpBody, OB: HttpBody, { type Error = E; type Service = S; type ResBody = OB; type MakeError = ME; type Future = F; type __DontNameMe = self::sealed::CantName; fn poll_ready_ref(&mut self, cx: &mut task::Context<'_>) -> Poll> { self.poll_ready(cx) } fn make_service_ref(&mut self, target: &Target) -> Self::Future { self.call(target) } } impl self::sealed::Sealed<(Target, B1)> for T where T: for<'a> Service<&'a Target, Response = S>, S: HttpService, B1: HttpBody, B2: HttpBody, { } /// Create a `MakeService` from a function. /// /// # Example /// /// ``` /// # #[cfg(feature = "runtime")] /// # async fn run() { /// use std::convert::Infallible; /// use hyper::{Body, Request, Response, Server}; /// use hyper::server::conn::AddrStream; /// use hyper::service::{make_service_fn, service_fn}; /// /// let addr = ([127, 0, 0, 1], 3000).into(); /// /// let make_svc = make_service_fn(|socket: &AddrStream| { /// let remote_addr = socket.remote_addr(); /// async move { /// Ok::<_, Infallible>(service_fn(move |_: Request| async move { /// Ok::<_, Infallible>( /// Response::new(Body::from(format!("Hello, {}!", remote_addr))) /// ) /// })) /// } /// }); /// /// // Then bind and serve... /// let server = Server::bind(&addr) /// .serve(make_svc); /// /// // Finally, spawn `server` onto an Executor... /// if let Err(e) = server.await { /// eprintln!("server error: {}", e); /// } /// # } /// # fn main() {} /// ``` pub fn make_service_fn(f: F) -> MakeServiceFn where F: FnMut(&Target) -> Ret, Ret: Future, { MakeServiceFn { f } } /// `MakeService` returned from [`make_service_fn`] #[derive(Clone, Copy)] pub struct MakeServiceFn { f: F, } impl<'t, F, Ret, Target, Svc, MkErr> Service<&'t Target> for MakeServiceFn where F: FnMut(&Target) -> Ret, Ret: Future>, MkErr: Into>, { type Error = MkErr; type Response = Svc; type Future = Ret; fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, target: &'t Target) -> Self::Future { (self.f)(target) } } impl fmt::Debug for MakeServiceFn { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MakeServiceFn").finish() } } mod sealed { pub trait Sealed {} #[allow(unreachable_pub)] // This is intentional. pub trait CantImpl {} #[allow(missing_debug_implementations)] pub enum CantName {} impl CantImpl for CantName {} }