pub struct ServiceBuilder<L> { /* private fields */ }
Expand description

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.

Implementations§

source§

impl ServiceBuilder<Identity>

source

pub fn new() -> Self

Create a new ServiceBuilder.

source§

impl<L> ServiceBuilder<L>

source

pub fn layer<T>(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.

source

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

Available on crate feature util only.

Optionally add a new layer T into the ServiceBuilder.

// Apply a timeout if configured
ServiceBuilder::new()
    .option_layer(timeout.map(TimeoutLayer::new))
    .service(svc)
source

pub fn layer_fn<F>(self, f: F) -> ServiceBuilder<Stack<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.

source

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

Available on crate feature retry only.

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.

source

pub fn timeout( self, timeout: Duration ) -> ServiceBuilder<Stack<TimeoutLayer, L>>

Available on crate feature timeout only.

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.

source

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

Available on crate feature filter only.

Conditionally reject requests based on predicate.

predicate must implement the Predicate trait.

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

source

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

Available on crate feature filter only.

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.

source

pub fn limit<P>(self, policy: P) -> ServiceBuilder<Stack<LimitLayer<P>, L>>

Available on crate feature limit only.

Limit the number of in-flight requests.

This wraps the inner service with an instance of the Limit middleware. The policy determines how to handle requests sent to the inner service when the limit has been reached.

source

pub fn map_request<F, R1, R2>( self, f: F ) -> ServiceBuilder<Stack<MapRequestLayer<F>, L>>where F: Fn(R1) -> R2 + Clone,

Available on crate feature util only.

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_async::ServiceBuilder;
use tower_async::ServiceExt;

// Suppose we have some `Service` whose request type is `String`:
let string_svc = tower_async::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?;

Modifying the request value:

use tower_async::ServiceBuilder;
use tower_async::ServiceExt;

// A service that takes a number and returns it:
let svc = tower_async::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);
source

pub fn map_response<F>( self, f: F ) -> ServiceBuilder<Stack<MapResponseLayer<F>, L>>

Available on crate feature util only.

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.

source

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

Available on crate feature util only.

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.

source

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

Available on crate feature util only.

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.

source

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

Available on crate feature util only.

Executes a new future after this service’s future resolves.

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.

source

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

Available on crate feature util only.

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.

source

pub fn into_inner(self) -> L

Returns the underlying Layer implementation.

source

pub fn service<S>(&self, service: S) -> L::Servicewhere L: Layer<S>,

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

source

pub fn service_fn<F>(self, f: F) -> L::Servicewhere L: Layer<ServiceFn<F>>,

Available on crate feature util only.

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:

ServiceBuilder::new()
    // ...
    .service(service_fn(handler_fn))
Example
use std::time::Duration;
use tower_async::{ServiceBuilder, ServiceExt, BoxError, service_fn};

async fn handle(request: &'static str) -> Result<&'static str, BoxError> {
   Ok(request)
}

let svc = ServiceBuilder::new()
    .timeout(Duration::from_secs(10))
    .service_fn(handle);

let response = svc.oneshot("foo").await?;

assert_eq!(response, "foo");
source

pub fn check_clone(self) -> Selfwhere 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_async::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
    });
source

pub fn check_service_clone<S>(self) -> Selfwhere L: Layer<S>, L::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_async::ServiceBuilder;

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
    });
source

pub fn check_service<S, T, U, E>(self) -> Selfwhere L: Layer<S>, L::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_async::ServiceBuilder;
use std::task::{Poll, Context};
use tower_async::{Service, ServiceExt};

// An example service
struct MyService;

impl Service<Request> for MyService {
  type Response = Response;
  type Error = Error;

  async fn call(&self, request: Request) -> Result<Self::Response, Self::Error> {
      // ...
  }
}

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, _>();

Trait Implementations§

source§

impl<L: Clone> Clone for ServiceBuilder<L>

source§

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

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

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

source§

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

Formats the value using the given formatter. Read more
source§

impl Default for ServiceBuilder<Identity>

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

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

§

type Service = <L as Layer<S>>::Service

The wrapped service
source§

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

Wrap the given service with the middleware, returning a new service that has been decorated with the middleware.

Auto Trait Implementations§

§

impl<L> RefUnwindSafe for ServiceBuilder<L>where L: RefUnwindSafe,

§

impl<L> Send for ServiceBuilder<L>where L: Send,

§

impl<L> Sync for ServiceBuilder<L>where L: Sync,

§

impl<L> Unpin for ServiceBuilder<L>where L: Unpin,

§

impl<L> UnwindSafe for ServiceBuilder<L>where L: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

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

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

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

source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

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

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

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

Performs the conversion.