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§
Required Methods§
Provided Methods§
Sourcefn apply_to<Sf, Req>(
self,
factory: Sf,
) -> ServiceChainFactory<ApplyMiddleware<Self, Sf>, St, Req>
fn apply_to<Sf, Req>( self, factory: Sf, ) -> ServiceChainFactory<ApplyMiddleware<Self, Sf>, 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".