| //! Contains [`MakeService`] which is a trait alias for a [`Service`] of [`Service`]s. | |
| use crate::sealed::Sealed; | |
| use std::fmt; | |
| use std::future::Future; | |
| use std::marker::PhantomData; | |
| use std::task::{Context, Poll}; | |
| use tower_service::Service; | |
| pub(crate) mod shared; | |
| /// Creates new [`Service`] values. | |
| /// | |
| /// Acts as a service factory. This is useful for cases where new [`Service`] | |
| /// values must be produced. One case is a TCP server listener. The listener | |
| /// accepts new TCP streams, obtains a new [`Service`] value using the | |
| /// [`MakeService`] trait, and uses that new [`Service`] value to process inbound | |
| /// requests on that new TCP stream. | |
| /// | |
| /// This is essentially a trait alias for a [`Service`] of [`Service`]s. | |
| pub trait MakeService<Target, Request>: Sealed<(Target, Request)> { | |
| /// Responses given by the service | |
| type Response; | |
| /// Errors produced by the service | |
| type Error; | |
| /// The [`Service`] value created by this factory | |
| type Service: Service<Request, Response = Self::Response, Error = Self::Error>; | |
| /// Errors produced while building a service. | |
| type MakeError; | |
| /// The future of the [`Service`] instance. | |
| type Future: Future<Output = Result<Self::Service, Self::MakeError>>; | |
| /// Returns [`Poll::Ready`] when the factory is able to create more services. | |
| /// | |
| /// If the service is at capacity, then [`Poll::Pending`] is returned and the task | |
| /// is notified when the service becomes ready again. This function is | |
| /// expected to be called while on a task. | |
| /// | |
| /// [`Poll::Ready`]: std::task::Poll::Ready | |
| /// [`Poll::Pending`]: std::task::Poll::Pending | |
| fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>>; | |
| /// Create and return a new service value asynchronously. | |
| fn make_service(&mut self, target: Target) -> Self::Future; | |
| /// Consume this [`MakeService`] and convert it into a [`Service`]. | |
| /// | |
| /// # Example | |
| /// ``` | |
| /// use std::convert::Infallible; | |
| /// use tower::Service; | |
| /// use tower::make::MakeService; | |
| /// use tower::service_fn; | |
| /// | |
| /// # fn main() { | |
| /// # async { | |
| /// // A `MakeService` | |
| /// let make_service = service_fn(|make_req: ()| async { | |
| /// Ok::<_, Infallible>(service_fn(|req: String| async { | |
| /// Ok::<_, Infallible>(req) | |
| /// })) | |
| /// }); | |
| /// | |
| /// // Convert the `MakeService` into a `Service` | |
| /// let mut svc = make_service.into_service(); | |
| /// | |
| /// // Make a new service | |
| /// let mut new_svc = svc.call(()).await.unwrap(); | |
| /// | |
| /// // Call the service | |
| /// let res = new_svc.call("foo".to_string()).await.unwrap(); | |
| /// # }; | |
| /// # } | |
| /// ``` | |
| fn into_service(self) -> IntoService<Self, Request> | |
| where | |
| Self: Sized, | |
| { | |
| IntoService { | |
| make: self, | |
| _marker: PhantomData, | |
| } | |
| } | |
| /// Convert this [`MakeService`] into a [`Service`] without consuming the original [`MakeService`]. | |
| /// | |
| /// # Example | |
| /// ``` | |
| /// use std::convert::Infallible; | |
| /// use tower::Service; | |
| /// use tower::make::MakeService; | |
| /// use tower::service_fn; | |
| /// | |
| /// # fn main() { | |
| /// # async { | |
| /// // A `MakeService` | |
| /// let mut make_service = service_fn(|make_req: ()| async { | |
| /// Ok::<_, Infallible>(service_fn(|req: String| async { | |
| /// Ok::<_, Infallible>(req) | |
| /// })) | |
| /// }); | |
| /// | |
| /// // Convert the `MakeService` into a `Service` | |
| /// let mut svc = make_service.as_service(); | |
| /// | |
| /// // Make a new service | |
| /// let mut new_svc = svc.call(()).await.unwrap(); | |
| /// | |
| /// // Call the service | |
| /// let res = new_svc.call("foo".to_string()).await.unwrap(); | |
| /// | |
| /// // The original `MakeService` is still accessible | |
| /// let new_svc = make_service.make_service(()).await.unwrap(); | |
| /// # }; | |
| /// # } | |
| /// ``` | |
| fn as_service(&mut self) -> AsService<Self, Request> | |
| where | |
| Self: Sized, | |
| { | |
| AsService { | |
| make: self, | |
| _marker: PhantomData, | |
| } | |
| } | |
| } | |
| impl<M, S, Target, Request> Sealed<(Target, Request)> for M | |
| where | |
| M: Service<Target, Response = S>, | |
| S: Service<Request>, | |
| { | |
| } | |
| impl<M, S, Target, Request> MakeService<Target, Request> for M | |
| where | |
| M: Service<Target, Response = S>, | |
| S: Service<Request>, | |
| { | |
| type Response = S::Response; | |
| type Error = S::Error; | |
| type Service = S; | |
| type MakeError = M::Error; | |
| type Future = M::Future; | |
| fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>> { | |
| Service::poll_ready(self, cx) | |
| } | |
| fn make_service(&mut self, target: Target) -> Self::Future { | |
| Service::call(self, target) | |
| } | |
| } | |
| /// Service returned by [`MakeService::into_service`][into]. | |
| /// | |
| /// See the documentation on [`into_service`][into] for details. | |
| /// | |
| /// [into]: MakeService::into_service | |
| pub struct IntoService<M, Request> { | |
| make: M, | |
| _marker: PhantomData<Request>, | |
| } | |
| impl<M, Request> Clone for IntoService<M, Request> | |
| where | |
| M: Clone, | |
| { | |
| fn clone(&self) -> Self { | |
| Self { | |
| make: self.make.clone(), | |
| _marker: PhantomData, | |
| } | |
| } | |
| } | |
| impl<M, Request> fmt::Debug for IntoService<M, Request> | |
| where | |
| M: fmt::Debug, | |
| { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| f.debug_struct("IntoService") | |
| .field("make", &self.make) | |
| .finish() | |
| } | |
| } | |
| impl<M, S, Target, Request> Service<Target> for IntoService<M, Request> | |
| where | |
| M: Service<Target, Response = S>, | |
| S: Service<Request>, | |
| { | |
| type Response = M::Response; | |
| type Error = M::Error; | |
| type Future = M::Future; | |
| #[inline] | |
| fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { | |
| self.make.poll_ready(cx) | |
| } | |
| #[inline] | |
| fn call(&mut self, target: Target) -> Self::Future { | |
| self.make.make_service(target) | |
| } | |
| } | |
| /// Service returned by [`MakeService::as_service`][as]. | |
| /// | |
| /// See the documentation on [`as_service`][as] for details. | |
| /// | |
| /// [as]: MakeService::as_service | |
| pub struct AsService<'a, M, Request> { | |
| make: &'a mut M, | |
| _marker: PhantomData<Request>, | |
| } | |
| impl<M, Request> fmt::Debug for AsService<'_, M, Request> | |
| where | |
| M: fmt::Debug, | |
| { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| f.debug_struct("AsService") | |
| .field("make", &self.make) | |
| .finish() | |
| } | |
| } | |
| impl<M, S, Target, Request> Service<Target> for AsService<'_, M, Request> | |
| where | |
| M: Service<Target, Response = S>, | |
| S: Service<Request>, | |
| { | |
| type Response = M::Response; | |
| type Error = M::Error; | |
| type Future = M::Future; | |
| #[inline] | |
| fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { | |
| self.make.poll_ready(cx) | |
| } | |
| #[inline] | |
| fn call(&mut self, target: Target) -> Self::Future { | |
| self.make.make_service(target) | |
| } | |
| } |