From 7461abc6b591bf1b1878f53edd4c4f7aa42db7ea Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Thu, 25 Feb 2021 22:52:37 +0100 Subject: [PATCH] builder: Add `ServiceBuilder::service_fn` (#564) * builder: Add `ServiceBuilder::service_fn` A small convenience for doing `.service(service_fn(handler_function))`. * Docs tweaks * Apply suggestions from code review Co-authored-by: Eliza Weisman * Fix Co-authored-by: Eliza Weisman --- tower/CHANGELOG.md | 2 ++ tower/src/builder/mod.rs | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/tower/CHANGELOG.md b/tower/CHANGELOG.md index ca97e67e..fcf5402d 100644 --- a/tower/CHANGELOG.md +++ b/tower/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **builder**: Add `ServiceBuilder::layer_fn` to add a layer built from a function. - **builder**: Add `ServiceBuilder::map_future` for transforming the futures produced by a service. +- **builder**: Add `ServiceBuilder::service_fn` for applying `Layer`s to an + async function using `util::service_fn`. - **util**: Add example for `service_fn`. # 0.4.5 (February 10, 2021) diff --git a/tower/src/builder/mod.rs b/tower/src/builder/mod.rs index f733861d..b21ccbe5 100644 --- a/tower/src/builder/mod.rs +++ b/tower/src/builder/mod.rs @@ -468,6 +468,58 @@ impl ServiceBuilder { { self.layer.layer(service) } + + /// Wrap the async function `F` with the middleware provided by this [`ServiceBuilder`]'s + /// [`Layer`]s, returning a new [`Service`]. + /// + /// This is a convenience method which is equivalent to calling + /// [`ServiceBuilder::service`] with a [`service_fn`], like this: + /// + /// ```rust + /// # use tower::{ServiceBuilder, service_fn}; + /// # async fn handler_fn(_: ()) -> Result<(), ()> { Ok(()) } + /// # let _ = { + /// ServiceBuilder::new() + /// // ... + /// .service(service_fn(handler_fn)) + /// # }; + /// ``` + /// + /// # Example + /// + /// ```rust + /// use std::time::Duration; + /// use tower::{ServiceBuilder, ServiceExt, BoxError, service_fn}; + /// + /// # #[tokio::main] + /// # async fn main() -> Result<(), BoxError> { + /// async fn handle(request: &'static str) -> Result<&'static str, BoxError> { + /// Ok(request) + /// } + /// + /// let svc = ServiceBuilder::new() + /// .buffer(1024) + /// .timeout(Duration::from_secs(10)) + /// .service_fn(handle); + /// + /// let response = svc.oneshot("foo").await?; + /// + /// assert_eq!(response, "foo"); + /// # Ok(()) + /// # } + /// ``` + /// + /// [`Layer`]: crate::Layer + /// [`Service`]: crate::Service + /// [`service_fn`]: crate::service_fn + #[cfg(feature = "util")] + #[cfg_attr(docsrs, doc(cfg(feature = "util")))] + pub fn service_fn(self, f: F) -> L::Service + where + L: Layer>, + { + self.service(crate::util::service_fn(f)) + } } impl fmt::Debug for ServiceBuilder {