tower/make/make_service/shared.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
use std::convert::Infallible;
use std::task::{Context, Poll};
use tower_service::Service;
/// A [`MakeService`] that produces services by cloning an inner service.
///
/// [`MakeService`]: super::MakeService
///
/// # Example
///
/// ```
/// # use std::task::{Context, Poll};
/// # use std::pin::Pin;
/// # use std::convert::Infallible;
/// use tower::make::{MakeService, Shared};
/// use tower::buffer::Buffer;
/// use tower::Service;
/// use futures::future::{Ready, ready};
///
/// // An example connection type
/// struct Connection {}
///
/// // An example request type
/// struct Request {}
///
/// // An example response type
/// struct Response {}
///
/// // Some service that doesn't implement `Clone`
/// struct MyService;
///
/// impl Service<Request> for MyService {
/// type Response = Response;
/// type Error = Infallible;
/// type Future = Ready<Result<Response, Infallible>>;
///
/// fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
/// Poll::Ready(Ok(()))
/// }
///
/// fn call(&mut self, req: Request) -> Self::Future {
/// ready(Ok(Response {}))
/// }
/// }
///
/// // Example function that runs a service by accepting new connections and using
/// // `Make` to create new services that might be bound to the connection.
/// //
/// // This is similar to what you might find in hyper.
/// async fn serve_make_service<Make>(make: Make)
/// where
/// Make: MakeService<Connection, Request>
/// {
/// // ...
/// }
///
/// # async {
/// // Our service
/// let svc = MyService;
///
/// // Make it `Clone` by putting a channel in front
/// let buffered = Buffer::new(svc, 1024);
///
/// // Convert it into a `MakeService`
/// let make = Shared::new(buffered);
///
/// // Run the service and just ignore the `Connection`s as `MyService` doesn't need them
/// serve_make_service(make).await;
/// # };
/// ```
#[derive(Debug, Clone, Copy)]
pub struct Shared<S> {
service: S,
}
impl<S> Shared<S> {
/// Create a new [`Shared`] from a service.
pub fn new(service: S) -> Self {
Self { service }
}
}
impl<S, T> Service<T> for Shared<S>
where
S: Clone,
{
type Response = S;
type Error = Infallible;
type Future = SharedFuture<S>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _target: T) -> Self::Future {
SharedFuture::new(futures_util::future::ready(Ok(self.service.clone())))
}
}
opaque_future! {
/// Response future from [`Shared`] services.
pub type SharedFuture<S> = futures_util::future::Ready<Result<S, Infallible>>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::make::MakeService;
use crate::service_fn;
use futures::future::poll_fn;
async fn echo<R>(req: R) -> Result<R, Infallible> {
Ok(req)
}
#[tokio::test]
async fn as_make_service() {
let mut shared = Shared::new(service_fn(echo::<&'static str>));
poll_fn(|cx| MakeService::<(), _>::poll_ready(&mut shared, cx))
.await
.unwrap();
let mut svc = shared.make_service(()).await.unwrap();
poll_fn(|cx| svc.poll_ready(cx)).await.unwrap();
let res = svc.call("foo").await.unwrap();
assert_eq!(res, "foo");
}
#[tokio::test]
async fn as_make_service_into_service() {
let shared = Shared::new(service_fn(echo::<&'static str>));
let mut shared = MakeService::<(), _>::into_service(shared);
poll_fn(|cx| Service::<()>::poll_ready(&mut shared, cx))
.await
.unwrap();
let mut svc = shared.call(()).await.unwrap();
poll_fn(|cx| svc.poll_ready(cx)).await.unwrap();
let res = svc.call("foo").await.unwrap();
assert_eq!(res, "foo");
}
}