Skip to content

Commit

Permalink
util: unify and rename combinators (#499)
Browse files Browse the repository at this point in the history
Currently, the `ServiceExt` trait has `with` and `try_with` methods for
composing a `Service` with functions that modify the request type, and
`map_err` and `map_ok` methods for composing a service with functions
that modify the response type. Meanwhile, `ServiceBuilder` has
`map_request` for composing a service with a request mapping function,
and `map_response` for composing a service with a response-mapping
function. These combinators are very similar in purpose, but are
implemented using different middleware types that essentially duplicate
the same behavior.

Before releasing 0.4, we should probably unify these APIs. In
particular, it would be good to de-duplicate the middleware service
types, and to unify the naming.

This commit makes the following changes:
- Rename the `ServiceExt::with` and `ServiceExt::try_with` combinators
  to `map_request` and `try_map_request`
  - Rename the `ServiceExt::map_ok` combinator to `map_response`
- Unify the `ServiceBuilder::map_request` and `ServiceExt::map_request`
  combinators to use the same `Service` type
- Unify the `ServiceBuilder::map_response` and
  `ServiceExt::map_response` combinators to use the same `Service` type
- Unify the `ServiceBuilder::map_err` and `ServiceExt::map_err`
  combinators to use the same `Service` type
- Only take `FnOnce + Clone` when in response/err combinators, which
  require cloning into the future type. `MapRequest` and `TryMapRequest`
  now take `FnMut(Request)`s and don't clone them every time they're
  called
- Reexport future types for combinators where it makes sense.
- Add a `try_map_request` method to `ServiceBuilder`

Closes #498

Signed-off-by: Eliza Weisman <[email protected]>
  • Loading branch information
hawkw authored Jan 4, 2021
1 parent 0100800 commit 878b10f
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 336 deletions.
20 changes: 19 additions & 1 deletion tower/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,23 @@ impl<L> ServiceBuilder<L> {
f: F,
) -> ServiceBuilder<Stack<crate::util::MapRequestLayer<F>, L>>
where
F: Fn(R1) -> R2,
F: FnMut(R1) -> R2 + Clone,
{
self.layer(crate::util::MapRequestLayer::new(f))
}

/// Fallibly one request type to another, or to an error.
#[cfg(feature = "util")]
pub fn try_map_request<F, R1, R2, E>(
self,
f: F,
) -> ServiceBuilder<Stack<crate::util::TryMapRequestLayer<F>, L>>
where
F: FnMut(R1) -> Result<R2, E> + Clone,
{
self.layer(crate::util::TryMapRequestLayer::new(f))
}

/// Map one response type to another.
#[cfg(feature = "util")]
pub fn map_response<F>(
Expand All @@ -211,6 +223,12 @@ impl<L> ServiceBuilder<L> {
self.layer(crate::util::MapResponseLayer::new(f))
}

/// Map one error type to another.
#[cfg(feature = "util")]
pub fn map_err<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapErrLayer<F>, L>> {
self.layer(crate::util::MapErrLayer::new(f))
}

/// Obtains the underlying `Layer` implementation.
pub fn into_inner(self) -> L {
self.layer
Expand Down
7 changes: 0 additions & 7 deletions tower/src/util/map/mod.rs

This file was deleted.

70 changes: 0 additions & 70 deletions tower/src/util/map/request.rs

This file was deleted.

118 changes: 0 additions & 118 deletions tower/src/util/map/response.rs

This file was deleted.

25 changes: 15 additions & 10 deletions tower/src/util/map_err.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use futures_util::{future::MapErr as MapErrFut, TryFutureExt};
use futures_util::TryFutureExt;
use std::task::{Context, Poll};
use tower_layer::Layer;
use tower_service::Service;

#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
pub use futures_util::future::MapErr as MapErrFuture;

/// Service returned by the [`map_err`] combinator.
///
/// [`map_err`]: crate::util::ServiceExt::map_err
Expand All @@ -12,6 +15,14 @@ pub struct MapErr<S, F> {
f: F,
}

/// A [`Layer`] that produces a [`MapErr`] service.
///
/// [`Layer`]: tower_layer::Layer
#[derive(Debug)]
pub struct MapErrLayer<F> {
f: F,
}

impl<S, F> MapErr<S, F> {
/// Creates a new [`MapErr`] service.
pub fn new(inner: S, f: F) -> Self {
Expand All @@ -26,25 +37,19 @@ where
{
type Response = S::Response;
type Error = Error;
type Future = MapErrFut<S::Future, F>;
type Future = MapErrFuture<S::Future, F>;

#[inline]
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx).map_err(self.f.clone())
}

#[inline]
fn call(&mut self, request: Request) -> Self::Future {
self.inner.call(request).map_err(self.f.clone())
}
}

/// A [`Layer`] that produces a [`MapErr`] service.
///
/// [`Layer`]: tower_layer::Layer
#[derive(Debug)]
pub struct MapErrLayer<F> {
f: F,
}

impl<F> MapErrLayer<F> {
/// Creates a new [`MapErrLayer`].
pub fn new(f: F) -> Self {
Expand Down
67 changes: 0 additions & 67 deletions tower/src/util/map_ok.rs

This file was deleted.

Loading

0 comments on commit 878b10f

Please sign in to comment.