Skip to main content

Service

Trait Service 

Source
pub trait Service<St, Req> {
    type Res;
    type Error;

    // Required method
    async fn call(
        &self,
        req: Req,
        ctx: Ctx<'_, Self, St>,
    ) -> Result<Self::Res, Self::Error>;

    // Provided methods
    async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), Self::Error> { ... }
    async fn shutdown(&self, ctx: Ctx<'_, Self, St>) { ... }
    fn map<F, Res>(self, f: F) -> ServiceChain<Map<F, Self, Res>, St, Req>
       where Self: Sized,
             F: Fn(Self::Res) -> Res { ... }
    fn map_err<F, E>(self, f: F) -> ServiceChain<MapErr<F, Self, E>, St, Req>
       where Self: Sized,
             F: Fn(Self::Error) -> E { ... }
    fn and_then<Next, F>(
        self,
        f: F,
    ) -> ServiceChain<AndThen<Self, Next>, St, Req>
       where Self: Sized,
             Next: Service<St, Self::Res, Error = Self::Error>,
             F: IntoService<Next, St, Self::Res> { ... }
    fn pipeline(self, st: St) -> Pipeline<Req, Self::Res, Self::Error>
       where Self: Sized + 'static,
             St: 'static,
             Req: 'static { ... }
}
Expand description

An asynchronous operation from a request to a response.

A service receives requests and asynchronously produces responses. Conceptually, it is similar to:

ⓘ
async fn(Request) -> Result<Response, Error>

The request and pipeline-state types are generic parameters. The response and error types are associated types, allowing one service type to implement Service for multiple request types.

Methods take &self, so implementations that mutate internal state must use interior mutability such as Cell, RefCell, or a synchronization primitive when appropriate.

The same abstraction can represent client- and server-side operations. Services focus on transformation, making them straightforward to test and compose.

A service call requires a Ctx and therefore runs through a Pipeline or from another service. The pipeline coordinates readiness across a composed service chain before dispatching a request.


struct MyService;

impl Service<(), u8> for MyService {
    type Res = u64;
    type Error = Infallible;

    async fn call(&self, req: u8, ctx: Ctx<'_, Self>) -> Result<Self::Res, Self::Error> {
        Ok(req as u64)
    }
}

Simple services do not need a manual trait implementation. The example above can be expressed with fn_service:

let service = fn_service(|req: u8| async move {
    Ok::<_, Infallible>(u64::from(req))
});
let pipeline = Pipeline::new((), service);

assert_eq!(pipeline.call(10).await?, 10);

Required Associated Types§

Source

type Res

Response produced by the service.

Source

type Error

Error produced while checking readiness or processing a request.

Required Methods§

Source

async fn call( &self, req: Req, ctx: Ctx<'_, Self, St>, ) -> Result<Self::Res, Self::Error>

Processes a request and asynchronously returns the response.

The enclosing pipeline checks readiness before invoking this method. Implementations should not call their own ready method. A composed service can use ctx to call an inner service.

Provided Methods§

Source

async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), Self::Error>

Waits until the service is ready to process a request.

If the service is at capacity, the returned future remains pending until capacity becomes available.

Pipeline readiness is coordinated across all services in a composed chain. A request is dispatched only when the chain is ready.

Source

async fn shutdown(&self, ctx: Ctx<'_, Self, St>)

Shuts down the service.

Returns when the service has been properly shut down.

Source

fn map<F, Res>(self, f: F) -> ServiceChain<Map<F, Self, Res>, St, Req>
where Self: Sized, F: Fn(Self::Res) -> Res,

Maps this service’s output to a different type, returning a new service.

This is similar to Option::map or Iterator::map, changing the output type of the underlying service.

This function consumes the original service and returns a wrapped version, following the pattern of standard library map methods.

Source

fn map_err<F, E>(self, f: F) -> ServiceChain<MapErr<F, Self, E>, St, Req>
where Self: Sized, F: Fn(Self::Error) -> E,

Maps this service’s error to a different type, returning a new service.

This is similar to Result::map_err, changing the error type of the underlying service. It is useful, for example, to ensure multiple services have the same error type.

This function consumes the original service and returns a wrapped version.

Source

fn and_then<Next, F>(self, f: F) -> ServiceChain<AndThen<Self, Next>, St, Req>
where Self: Sized, Next: Service<St, Self::Res, Error = Self::Error>, F: IntoService<Next, St, Self::Res>,

Calls another service after this service completes successfully.

The first service’s response becomes the second service’s request. If the first service returns an error, the second service is not called.

Source

fn pipeline(self, st: St) -> Pipeline<Req, Self::Res, Self::Error>
where Self: Sized + 'static, St: 'static, Req: 'static,

Wraps this service and its state in a Pipeline.

Dyn Compatibility§

This trait is not dyn compatible.

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

Implementations on Foreign Types§

§

impl<A, S> Service<SharedCfg, A> for Connector<A, S>
where A: Address, S: Service<SharedCfg, Connect<A>, Error = Error<ConnectError>>, IoBoxed: From<<S as Service<SharedCfg, Connect<A>>>::Res>,

§

async fn call( &self, req: A, ctx: Ctx<'_, Connector<A, S>, SharedCfg>, ) -> Result<<Connector<A, S> as Service<SharedCfg, A>>::Res, <Connector<A, S> as Service<SharedCfg, A>>::Error>

Connects to an HTTP/2 server.

§

type Res = SimpleClient

§

type Error = Error<ClientError>

§

async fn ready( &self, ctx: Ctx<'_, Connector<A, S>, SharedCfg>, ) -> Result<(), <Connector<A, S> as Service<SharedCfg, A>>::Error>

§

async fn shutdown(&self, ctx: Ctx<'_, Connector<A, S>, SharedCfg>)

Source§

impl<S, St, Req> Service<St, Req> for &S
where S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

async fn ready( &self, ctx: Ctx<'_, &S, St>, ) -> Result<(), <S as Service<St, Req>>::Error>

Source§

async fn call( &self, req: Req, ctx: Ctx<'_, &S, St>, ) -> Result<<S as Service<St, Req>>::Res, <S as Service<St, Req>>::Error>

Source§

async fn shutdown(&self, ctx: Ctx<'_, &S, St>)

Source§

impl<S, St, Req> Service<St, Req> for Box<S>
where S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

async fn ready( &self, ctx: Ctx<'_, Box<S>, St>, ) -> Result<(), <S as Service<St, Req>>::Error>

Source§

async fn call( &self, req: Req, ctx: Ctx<'_, Box<S>, St>, ) -> Result<<S as Service<St, Req>>::Res, <S as Service<St, Req>>::Error>

Source§

async fn shutdown(&self, ctx: Ctx<'_, Box<S>, St>)

Source§

impl<S, St, Req> Service<St, Req> for Rc<S>
where S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

async fn ready( &self, ctx: Ctx<'_, Rc<S>, St>, ) -> Result<(), <S as Service<St, Req>>::Error>

Source§

async fn call( &self, req: Req, ctx: Ctx<'_, Rc<S>, St>, ) -> Result<<S as Service<St, Req>>::Res, <S as Service<St, Req>>::Error>

Source§

async fn shutdown(&self, ctx: Ctx<'_, Rc<S>, St>)

§

impl<St, Req, PErr, Err> Service<St, Req> for Server<Req, PErr, Err>
where St: 'static, Req: RequestState<IoBoxed>, <Req as RequestState<IoBoxed>>::State: Clone, PErr: Debug + 'static, Err: 'static,

§

type Res = ()

§

type Error = ServerError<Err>

§

async fn call( &self, req: Req, _: Ctx<'_, Server<Req, PErr, Err>, St>, ) -> Result<(), <Server<Req, PErr, Err> as Service<St, Req>>::Error>

Implementors§

Source§

impl<A, B, St, Req> Service<St, Req> for AndThen<A, B>
where A: Service<St, Req>, B: Service<St, <A as Service<St, Req>>::Res, Error = <A as Service<St, Req>>::Error>,

Source§

type Res = <B as Service<St, <A as Service<St, Req>>::Res>>::Res

Source§

type Error = <A as Service<St, Req>>::Error

Source§

impl<A, B, St, Req> Service<St, Req> for Either<A, B>
where A: Service<St, Req>, B: Service<St, Req, Res = <A as Service<St, Req>>::Res, Error = <A as Service<St, Req>>::Error>,

Source§

type Res = <A as Service<St, Req>>::Res

Source§

type Error = <A as Service<St, Req>>::Error

Source§

impl<A, B, St, Req> Service<St, Req> for Then<A, B>
where A: Service<St, Req>, B: Service<St, Result<<A as Service<St, Req>>::Res, <A as Service<St, Req>>::Error>, Error = <A as Service<St, Req>>::Error>,

Source§

type Res = <B as Service<St, Result<<A as Service<St, Req>>::Res, <A as Service<St, Req>>::Error>>>::Res

Source§

type Error = <B as Service<St, Result<<A as Service<St, Req>>::Res, <A as Service<St, Req>>::Error>>>::Error

Source§

impl<A> Service<SharedCfg, Connect<A>> for ntex::connect::Connector<A>
where A: Address,

Source§

impl<F, A, S> Service<SharedCfg, Connect<A>> for SslConnector<S>
where F: Filter, A: Address, S: Service<SharedCfg, Connect<A>, Res = Io<F>, Error = Error<ConnectError>>,

Source§

impl<F, A, S> Service<SharedCfg, Connect<A>> for TlsConnector<S>
where F: Filter, A: Address, S: Service<SharedCfg, Connect<A>, Res = Io<F>, Error = Error<ConnectError>>,

Source§

impl<F, E, St, Req> Service<St, Req> for KeepAliveService<F, E>
where F: Fn() -> E,

Source§

type Res = Req

Source§

type Error = E

Source§

impl<F, S, St, Req, E> Service<St, Req> for MapErr<F, S, E>
where S: Service<St, Req>, F: Fn(<S as Service<St, Req>>::Error) -> E,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = E

Source§

impl<F, S, St, Req, Res> Service<St, Req> for Map<F, S, Res>
where S: Service<St, Req>, F: Fn(<S as Service<St, Req>>::Res) -> Res,

Source§

type Res = Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

impl<F, St, Req, Err> Service<St, Req> for FnReadiness<F, Err>
where F: AsyncFn(&St) -> Result<(), Err> + Clone,

Source§

type Res = Req

Source§

type Error = Err

Source§

impl<F, St, Req, Err> Service<St, Req> for FnShutdown<F, Err>
where F: AsyncFnOnce(&St),

Source§

type Res = Req

Source§

type Error = Err

Source§

impl<F, St, Req, Res, Err> Service<St, Req> for FnService<F, Req, Res, Err>
where F: AsyncFn(Req) -> Result<Res, Err>,

Source§

type Res = Res

Source§

type Error = Err

Source§

impl<F, St, Req, Res, Err> Service<St, Req> for FnServiceSt<F, St, Req, Res, Err>
where F: AsyncFn(&St, Req) -> Result<Res, Err>,

Source§

type Res = Res

Source§

type Error = Err

Source§

impl<F, St> Service<St, Io<F>> for SslAcceptor
where F: Filter,

Source§

impl<F, St> Service<St, Io<F>> for TlsAcceptor
where F: Filter,

Source§

impl<F: Filter> Service<(), Io<F>> for WsTransportService

Source§

impl<OtSt, S, St, Req> Service<OtSt, Req> for MapState<S, St>
where S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

impl<P, S, St, Req> Service<St, Req> for RetryService<P, S>
where P: Policy<S, St, Req>, S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

impl<S, St, In> Service<St, WebRequest<In>> for WebMiddleware<S, St>
where S: Service<St, WebRequest<In>, Res = WebResponse>, S::Error: WebResponseError<St, St::Error>, St: State,

Source§

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

Source§

type Res = Out

Source§

type Error = Err

Source§

impl<S, St, Req> Service<St, Req> for InFlightService<S>
where S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

impl<S, St, Req> Service<St, Req> for OneRequestService<S>
where S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

impl<S, St, Req> Service<St, Req> for ServiceChain<S, St, Req>
where S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = <S as Service<St, Req>>::Error

Source§

impl<S, St, Req> Service<St, Req> for TimeoutService<S, St>
where S: Service<St, Req>,

Source§

type Res = <S as Service<St, Req>>::Res

Source§

type Error = TimeoutError<<S as Service<St, Req>>::Error>

Source§

impl<St, E: Debug> Service<St, Control<E>> for ntex::http::h2::DefaultControlService

Source§

impl<St, F, Err> Service<St, Control<F, Err>> for ntex::http::h1::DefaultControlService
where F: Filter, Err: ResponseError,

Source§

impl<St, F, Req, Err> Service<St, Req> for H1Service<F, Req, Err>
where F: Filter, Req: RequestState<Io<F>>, Req::State: Clone, Err: ResponseError + 'static,

Source§

impl<St, F, Req, Err> Service<St, Req> for H2Service<F, Req, Err>
where F: Filter, Req: RequestState<Io<F>>, Req::State: Clone, Err: ResponseError + 'static,

Source§

impl<St, F, Req, Err> Service<St, Req> for HttpService<F, Req, Err>
where F: Filter + 'static, Req: RequestState<Io<F>>, Req::State: Clone, Err: ResponseError + 'static,

Source§

impl<St, F> Service<St, Request> for AppService<St, F>
where St: State, F: Service<St, WebRequest<()>, Res = WebResponse, Error = WebError<St, St::Error>>,

Source§

impl<St, Req, Res, Err> Service<St, Req> for BoxService<St, Req, Res, Err>

Source§

type Res = Res

Source§

type Error = Err

Source§

impl<St, Req, Res, Err> Service<St, Req> for BufferService<St, Req, Res, Err>
where St: Clone + 'static, Req: 'static, Res: 'static, Err: 'static,

Source§

impl<St: State, In> Service<St, WebRequest<In>> for Filter<St, In>

Source§

type Res = WebRequest<In>

Source§

type Error = WebError<St, <St as State>::Error>