Skip to main content

Middleware

Trait Middleware 

Source
pub trait Middleware<S, St> {
    type Service;

    // Required method
    fn create(&self, st: &St, service: S) -> Self::Service;

    // Provided method
    fn apply_to<Sf, Req>(
        self,
        factory: Sf,
    ) -> ServiceChainFactory<ApplyMiddleware<Self, Sf>, St, Req>
       where Sf: ServiceFactory<St, Req, Service = S>,
             Self: Sized,
             Self::Service: Service<St, Req> { ... }
}
Expand description

Wraps an inner service during service construction.

Middleware can run before and after the inner service, and can modify requests, responses, or errors.

For example, timeout middleware:

use ntex_service::{Ctx, Service};
use ntex::{time::sleep, util::Either, util::select};

pub struct Timeout<S> {
    service: S,
    timeout: std::time::Duration,
}

pub enum TimeoutError<E> {
   Service(E),
   Timeout,
}

impl<S, R> Service<(), R> for Timeout<S>
where
    S: Service<(), R>,
{
    type Res = S::Res;
    type Error = TimeoutError<S::Error>;

    async fn ready(&self, ctx: Ctx<'_, Self>) -> Result<(), Self::Error> {
        ctx.ready(&self.service).await.map_err(TimeoutError::Service)
    }

    async fn call(&self, req: R, ctx: Ctx<'_, Self>) -> Result<Self::Res, Self::Error> {
        match select(sleep(self.timeout), ctx.call(&self.service, req)).await {
            Either::Left(_) => Err(TimeoutError::Timeout),
            Either::Right(res) => res.map_err(TimeoutError::Service),
        }
    }
}

The timeout service is independent of the wrapped service implementation and can be applied to any compatible service.

A middleware factory for Timeout could look like this:

pub struct TimeoutMiddleware {
    timeout: std::time::Duration,
}

impl<S> Middleware<S, ()> for TimeoutMiddleware
{
    type Service = Timeout<S>;

    fn create(&self, _: &(), service: S) -> Self::Service {
        Timeout {
            service,
            timeout: self.timeout,
        }
    }
}

Required Associated Types§

Source

type Service

Service created by this middleware.

Required Methods§

Source

fn create(&self, st: &St, service: S) -> Self::Service

Creates and returns a new middleware service.

Provided Methods§

Source

fn apply_to<Sf, Req>( self, factory: Sf, ) -> ServiceChainFactory<ApplyMiddleware<Self, Sf>, St, Req>
where Sf: ServiceFactory<St, Req, Service = S>, Self: Sized, Self::Service: Service<St, Req>,

Creates a service factory that instantiates a service and applies the current middleware to it.

This is equivalent to apply(self, factory).

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<M, S, St> Middleware<S, St> for Rc<M>
where M: Middleware<S, St>,

Source§

type Service = <M as Middleware<S, St>>::Service

Source§

fn create(&self, st: &St, service: S) -> M::Service

Implementors§

Source§

impl<F, S, St, Req, In, Out, Err> Middleware<S, St> for FnMiddleware<F, S, St, Req, In, Out, Err>
where S: Service<St, Req>, F: AsyncFn(In, &ApplyCtx<'_, S, St, Req>) -> Result<Out, Err> + Clone, Err: From<S::Error>,

Source§

type Service = Apply<S, St, Req, F, In, Out, Err>

Source§

impl<S, St, Inner, Outer> Middleware<S, St> for Stack<Inner, Outer>
where Inner: Middleware<S, St>, Outer: Middleware<Inner::Service, St>,

Source§

type Service = <Outer as Middleware<<Inner as Middleware<S, St>>::Service, St>>::Service

Source§

impl<S, St> Middleware<S, St> for Identity