tower/util/service_fn.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
use std::fmt;
use std::future::Future;
use std::task::{Context, Poll};
use tower_service::Service;
/// Returns a new [`ServiceFn`] with the given closure.
///
/// This lets you build a [`Service`] from an async function that returns a [`Result`].
///
/// # Example
///
/// ```
/// use tower::{service_fn, Service, ServiceExt, BoxError};
/// # struct Request;
/// # impl Request {
/// # fn new() -> Self { Self }
/// # }
/// # struct Response(&'static str);
/// # impl Response {
/// # fn new(body: &'static str) -> Self {
/// # Self(body)
/// # }
/// # fn into_body(self) -> &'static str { self.0 }
/// # }
///
/// # #[tokio::main]
/// # async fn main() -> Result<(), BoxError> {
/// async fn handle(request: Request) -> Result<Response, BoxError> {
/// let response = Response::new("Hello, World!");
/// Ok(response)
/// }
///
/// let mut service = service_fn(handle);
///
/// let response = service
/// .ready()
/// .await?
/// .call(Request::new())
/// .await?;
///
/// assert_eq!("Hello, World!", response.into_body());
/// #
/// # Ok(())
/// # }
/// ```
pub fn service_fn<T>(f: T) -> ServiceFn<T> {
ServiceFn { f }
}
/// A [`Service`] implemented by a closure.
///
/// See [`service_fn`] for more details.
#[derive(Copy, Clone)]
pub struct ServiceFn<T> {
f: T,
}
impl<T> fmt::Debug for ServiceFn<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ServiceFn")
.field("f", &format_args!("{}", std::any::type_name::<T>()))
.finish()
}
}
impl<T, F, Request, R, E> Service<Request> for ServiceFn<T>
where
T: FnMut(Request) -> F,
F: Future<Output = Result<R, E>>,
{
type Response = R;
type Error = E;
type Future = F;
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), E>> {
Ok(()).into()
}
fn call(&mut self, req: Request) -> Self::Future {
(self.f)(req)
}
}