Struct ServiceBuilder

struct ServiceBuilder<L> { ... }

Declaratively construct Service values.

ServiceBuilder provides a builder-like interface for composing layers to be applied to a Service.

Service

A Service is a trait representing an asynchronous function of a request to a response. It is similar to async fn(Request) -> Result<Response, Error>.

A Service is typically bound to a single transport, such as a TCP connection. It defines how all inbound or outbound requests are handled by that connection.

Order

The order in which layers are added impacts how requests are handled. Layers that are added first will be called with the request first. The argument to service will be last to see the request.

# // this (and other) doctest is ignored because we don't have a way
# // to say that it should only be run with cfg(feature = "...")
# use tower::Service;
# use tower::builder::ServiceBuilder;
# #[cfg(all(feature = "buffer", feature = "limit"))]
# async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
ServiceBuilder::new()
    .buffer(100)
    .concurrency_limit(10)
    .service(svc)
# ;
# }

In the above example, the buffer layer receives the request first followed by concurrency_limit. buffer enables up to 100 request to be in-flight on top of the requests that have already been forwarded to the next layer. Combined with concurrency_limit, this allows up to 110 requests to be in-flight.

# use tower::Service;
# use tower::builder::ServiceBuilder;
# #[cfg(all(feature = "buffer", feature = "limit"))]
# async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
ServiceBuilder::new()
    .concurrency_limit(10)
    .buffer(100)
    .service(svc)
# ;
# }

The above example is similar, but the order of layers is reversed. Now, concurrency_limit applies first and only allows 10 requests to be in-flight total.

Examples

A Service stack with a single layer:

# use tower::Service;
# use tower::builder::ServiceBuilder;
# #[cfg(feature = "limit")]
# use tower::limit::concurrency::ConcurrencyLimitLayer;
# #[cfg(feature = "limit")]
# async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
ServiceBuilder::new()
    .concurrency_limit(5)
    .service(svc);
# ;
# }

A Service stack with multiple layers that contain rate limiting, in-flight request limits, and a channel-backed, clonable Service:

# use tower::Service;
# use tower::builder::ServiceBuilder;
# use std::time::Duration;
# #[cfg(all(feature = "buffer", feature = "limit"))]
# async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
ServiceBuilder::new()
    .buffer(5)
    .concurrency_limit(5)
    .rate_limit(5, Duration::from_secs(1))
    .service(svc);
# ;
# }

Implementations

impl ServiceBuilder<tower_layer::Identity>

const fn new() -> Self

Create a new ServiceBuilder.

impl<L> ServiceBuilder<L>

fn layer<T>(self: Self, layer: T) -> ServiceBuilder<Stack<T, L>>

Add a new layer T into the ServiceBuilder.

This wraps the inner service with the service provided by a user-defined Layer. The provided layer must implement the Layer trait.

fn option_layer<T>(self: Self, layer: Option<T>) -> ServiceBuilder<Stack<crate::util::Either<T, Identity>, L>>

Optionally add a new layer T into the ServiceBuilder.

# use std::time::Duration;
# use tower::Service;
# use tower::builder::ServiceBuilder;
# use tower::timeout::TimeoutLayer;
# async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
# let timeout = Some(Duration::new(10, 0));
// Apply a timeout if configured
ServiceBuilder::new()
    .option_layer(timeout.map(TimeoutLayer::new))
    .service(svc)
# ;
# }
fn layer_fn<F>(self: Self, f: F) -> ServiceBuilder<Stack<crate::layer::LayerFn<F>, L>>

Add a Layer built from a function that accepts a service and returns another service.

See the documentation for layer_fn for more details.

fn buffer<Request>(self: Self, bound: usize) -> ServiceBuilder<Stack<crate::buffer::BufferLayer<Request>, L>>

Buffer requests when the next layer is not ready.

This wraps the inner service with an instance of the Buffer middleware.

fn concurrency_limit(self: Self, max: usize) -> ServiceBuilder<Stack<crate::limit::ConcurrencyLimitLayer, L>>

Limit the max number of in-flight requests.

A request is in-flight from the time the request is received until the response future completes. This includes the time spent in the next layers.

This wraps the inner service with an instance of the ConcurrencyLimit middleware.

fn load_shed(self: Self) -> ServiceBuilder<Stack<crate::load_shed::LoadShedLayer, L>>

Drop requests when the next layer is unable to respond to requests.

Usually, when a service or middleware does not have capacity to process a request (i.e., poll_ready returns Pending), the caller waits until capacity becomes available.

LoadShed immediately responds with an error when the next layer is out of capacity.

This wraps the inner service with an instance of the LoadShed middleware.

fn rate_limit(self: Self, num: u64, per: std::time::Duration) -> ServiceBuilder<Stack<crate::limit::RateLimitLayer, L>>

Limit requests to at most num per the given duration.

This wraps the inner service with an instance of the RateLimit middleware.

fn retry<P>(self: Self, policy: P) -> ServiceBuilder<Stack<crate::retry::RetryLayer<P>, L>>

Retry failed requests according to the given retry policy.

policy determines which failed requests will be retried. It must implement the retry::Policy trait.

This wraps the inner service with an instance of the Retry middleware.

fn timeout(self: Self, timeout: std::time::Duration) -> ServiceBuilder<Stack<crate::timeout::TimeoutLayer, L>>

Fail requests that take longer than timeout.

If the next layer takes more than timeout to respond to a request, processing is terminated and an error is returned.

This wraps the inner service with an instance of the timeout middleware.

fn filter<P>(self: Self, predicate: P) -> ServiceBuilder<Stack<crate::filter::FilterLayer<P>, L>>

Conditionally reject requests based on predicate.

predicate must implement the Predicate trait.

This wraps the inner service with an instance of the Filter middleware.

fn filter_async<P>(self: Self, predicate: P) -> ServiceBuilder<Stack<crate::filter::AsyncFilterLayer<P>, L>>

Conditionally reject requests based on an asynchronous predicate.

predicate must implement the AsyncPredicate trait.

This wraps the inner service with an instance of the AsyncFilter middleware.

fn map_request<F, R1, R2>(self: Self, f: F) -> ServiceBuilder<Stack<crate::util::MapRequestLayer<F>, L>>
where
    F: FnMut(R1) -> R2 + Clone

Map one request type to another.

This wraps the inner service with an instance of the MapRequest middleware.

Examples

Changing the type of a request:

use tower::ServiceBuilder;
use tower::ServiceExt;

# #[tokio::main]
# async fn main() -> Result<(), ()> {
// Suppose we have some `Service` whose request type is `String`:
let string_svc = tower::service_fn(|request: String| async move {
    println!("request: {}", request);
    Ok(())
});

// ...but we want to call that service with a `usize`. What do we do?

let usize_svc = ServiceBuilder::new()
     // Add a middleware that converts the request type to a `String`:
    .map_request(|request: usize| format!("{}", request))
    // ...and wrap the string service with that middleware:
    .service(string_svc);

// Now, we can call that service with a `usize`:
usize_svc.oneshot(42).await?;
# Ok(())
# }

Modifying the request value:

use tower::ServiceBuilder;
use tower::ServiceExt;

# #[tokio::main]
# async fn main() -> Result<(), ()> {
// A service that takes a number and returns it:
let svc = tower::service_fn(|request: usize| async move {
   Ok(request)
});

let svc = ServiceBuilder::new()
     // Add a middleware that adds 1 to each request
    .map_request(|request: usize| request + 1)
    .service(svc);

let response = svc.oneshot(1).await?;
assert_eq!(response, 2);
# Ok(())
# }
fn map_response<F>(self: Self, f: F) -> ServiceBuilder<Stack<crate::util::MapResponseLayer<F>, L>>

Map one response type to another.

This wraps the inner service with an instance of the MapResponse middleware.

See the documentation for the map_response combinator for details.

fn map_err<F>(self: Self, f: F) -> ServiceBuilder<Stack<crate::util::MapErrLayer<F>, L>>

Map one error type to another.

This wraps the inner service with an instance of the MapErr middleware.

See the documentation for the map_err combinator for details.

fn map_future<F>(self: Self, f: F) -> ServiceBuilder<Stack<crate::util::MapFutureLayer<F>, L>>

Composes a function that transforms futures produced by the service.

This wraps the inner service with an instance of the MapFutureLayer middleware.

See the documentation for the map_future combinator for details.

fn then<F>(self: Self, f: F) -> ServiceBuilder<Stack<crate::util::ThenLayer<F>, L>>

Apply an asynchronous function after the service, regardless of whether the future succeeds or fails.

This wraps the inner service with an instance of the Then middleware.

This is similar to the map_response and map_err functions, except that the same function is invoked when the service's future completes, whether it completes successfully or fails. This function takes the Result returned by the service's future, and returns a Result.

See the documentation for the then combinator for details.

fn and_then<F>(self: Self, f: F) -> ServiceBuilder<Stack<crate::util::AndThenLayer<F>, L>>

Executes a new future after this service's future resolves. This does not alter the behaviour of the poll_ready method.

This method can be used to change the Response type of the service into a different type. You can use this method to chain along a computation once the service's response has been resolved.

This wraps the inner service with an instance of the AndThen middleware.

See the documentation for the and_then combinator for details.

fn map_result<F>(self: Self, f: F) -> ServiceBuilder<Stack<crate::util::MapResultLayer<F>, L>>

Maps this service's result type (Result<Self::Response, Self::Error>) to a different value, regardless of whether the future succeeds or fails.

This wraps the inner service with an instance of the MapResult middleware.

See the documentation for the map_result combinator for details.

fn into_inner(self: Self) -> L

Returns the underlying Layer implementation.

fn service<S>(self: &Self, service: S) -> <L as >::Service
where
    L: Layer<S>

Wrap the service S with the middleware provided by this ServiceBuilder's Layer's, returning a new Service.

fn service_fn<F>(self: Self, f: F) -> <L as >::Service
where
    L: Layer<crate::util::ServiceFn<F>>

Wrap the async function F with the middleware provided by this ServiceBuilder's Layers, returning a new Service.

This is a convenience method which is equivalent to calling ServiceBuilder::service with a service_fn, like this:

# use tower::{ServiceBuilder, service_fn};
# async fn handler_fn(_: ()) -> Result<(), ()> { Ok(()) }
# let _ = {
ServiceBuilder::new()
    // ...
    .service(service_fn(handler_fn))
# };

Example

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(())
# }
fn check_clone(self: Self) -> Self
where
    Self: Clone

Check that the builder implements Clone.

This can be useful when debugging type errors in ServiceBuilders with lots of layers.

Doesn't actually change the builder but serves as a type check.

Example

use tower::ServiceBuilder;

let builder = ServiceBuilder::new()
    // Do something before processing the request
    .map_request(|request: String| {
        println!("got request!");
        request
    })
    // Ensure our `ServiceBuilder` can be cloned
    .check_clone()
    // Do something after processing the request
    .map_response(|response: String| {
        println!("got response!");
        response
    });
fn check_service_clone<S>(self: Self) -> Self
where
    L: Layer<S>,
    <L as >::Service: Clone

Check that the builder when given a service of type S produces a service that implements Clone.

This can be useful when debugging type errors in ServiceBuilders with lots of layers.

Doesn't actually change the builder but serves as a type check.

Example

use tower::ServiceBuilder;

# #[derive(Clone)]
# struct MyService;
#
let builder = ServiceBuilder::new()
    // Do something before processing the request
    .map_request(|request: String| {
        println!("got request!");
        request
    })
    // Ensure that the service produced when given a `MyService` implements
    .check_service_clone::<MyService>()
    // Do something after processing the request
    .map_response(|response: String| {
        println!("got response!");
        response
    });
fn check_service<S, T, U, E>(self: Self) -> Self
where
    L: Layer<S>,
    <L as >::Service: Service<T, Response = U, Error = E>

Check that the builder when given a service of type S produces a service with the given request, response, and error types.

This can be useful when debugging type errors in ServiceBuilders with lots of layers.

Doesn't actually change the builder but serves as a type check.

Example

use tower::ServiceBuilder;
use std::task::{Poll, Context};
use tower::{Service, ServiceExt};

// An example service
struct MyService;

impl Service<Request> for MyService {
  type Response = Response;
  type Error = Error;
  type Future = futures_util::future::Ready<Result<Response, Error>>;

  fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
      // ...
      # todo!()
  }

  fn call(&mut self, request: Request) -> Self::Future {
      // ...
      # todo!()
  }
}

struct Request;
struct Response;
struct Error;

struct WrappedResponse(Response);

let builder = ServiceBuilder::new()
    // At this point in the builder if given a `MyService` it produces a service that
    // accepts `Request`s, produces `Response`s, and fails with `Error`s
    .check_service::<MyService, Request, Response, Error>()
    // Wrap responses in `WrappedResponse`
    .map_response(|response: Response| WrappedResponse(response))
    // Now the response type will be `WrappedResponse`
    .check_service::<MyService, _, WrappedResponse, _>();
fn boxed<S, R>(self: Self) -> ServiceBuilder<Stack<tower_layer::LayerFn<fn(_: <L as >::Service) -> crate::util::BoxService<R, <<L as >::Service as Service<R>>::Response, <<L as >::Service as Service<R>>::Error>>, L>>
where
    L: Layer<S>,
    <L as >::Service: Service<R> + Send + 'static,
    <<L as >::Service as Service<R>>::Future: Send + 'static

This wraps the inner service with the Layer returned by BoxService::layer().

See that method for more details.

Example

use tower::{Service, ServiceBuilder, BoxError, util::BoxService};
use std::time::Duration;
#
# struct Request;
# struct Response;
# impl Response {
#     fn new() -> Self { Self }
# }

let service: BoxService<Request, Response, BoxError> = ServiceBuilder::new()
    .boxed()
    .load_shed()
    .concurrency_limit(64)
    .timeout(Duration::from_secs(10))
    .service_fn(|req: Request| async {
        Ok::<_, BoxError>(Response::new())
    });
# let service = assert_service(service);
# fn assert_service<S, R>(svc: S) -> S
# where S: Service<R> { svc }
fn boxed_clone<S, R>(self: Self) -> ServiceBuilder<Stack<tower_layer::LayerFn<fn(_: <L as >::Service) -> crate::util::BoxCloneService<R, <<L as >::Service as Service<R>>::Response, <<L as >::Service as Service<R>>::Error>>, L>>
where
    L: Layer<S>,
    <L as >::Service: Service<R> + Clone + Send + 'static,
    <<L as >::Service as Service<R>>::Future: Send + 'static

This wraps the inner service with the Layer returned by BoxCloneService::layer().

This is similar to the boxed method, but it requires that Self implement Clone, and the returned boxed service implements Clone.

See BoxCloneService for more details.

Example

use tower::{Service, ServiceBuilder, BoxError, util::BoxCloneService};
use std::time::Duration;
#
# struct Request;
# struct Response;
# impl Response {
#     fn new() -> Self { Self }
# }

let service: BoxCloneService<Request, Response, BoxError> = ServiceBuilder::new()
    .boxed_clone()
    .load_shed()
    .concurrency_limit(64)
    .timeout(Duration::from_secs(10))
    .service_fn(|req: Request| async {
        Ok::<_, BoxError>(Response::new())
    });
# let service = assert_service(service);

// The boxed service can still be cloned.
service.clone();
# fn assert_service<S, R>(svc: S) -> S
# where S: Service<R> { svc }

impl Default for ServiceBuilder<tower_layer::Identity>

fn default() -> Self

impl<L> Freeze for ServiceBuilder<L>

impl<L> RefUnwindSafe for ServiceBuilder<L>

impl<L> Send for ServiceBuilder<L>

impl<L> Sync for ServiceBuilder<L>

impl<L> Unpin for ServiceBuilder<L>

impl<L> UnwindSafe for ServiceBuilder<L>

impl<L: $crate::clone::Clone> Clone for ServiceBuilder<L>

fn clone(self: &Self) -> ServiceBuilder<L>

impl<L: fmt::Debug> Debug for ServiceBuilder<L>

fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> fmt::Result

impl<S, L> Layer for ServiceBuilder<L>

fn layer(self: &Self, inner: S) -> <Self as >::Service

impl<T> Any for ServiceBuilder<L>

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for ServiceBuilder<L>

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for ServiceBuilder<L>

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> CloneToUninit for ServiceBuilder<L>

unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)

impl<T> From for ServiceBuilder<L>

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> Instrument for ServiceBuilder<L>

impl<T> ToOwned for ServiceBuilder<L>

fn to_owned(self: &Self) -> T
fn clone_into(self: &Self, target: &mut T)

impl<T> WithSubscriber for ServiceBuilder<L>

impl<T, U> Into for ServiceBuilder<L>

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom for ServiceBuilder<L>

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for ServiceBuilder<L>

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>