Trait tarpc::server::Serve

source ·
pub trait Serve {
    type Req;
    type Resp;

    // Required method
    async fn serve(
        self,
        ctx: Context,
        req: Self::Req
    ) -> Result<Self::Resp, ServerError>;

    // Provided methods
    fn method(&self, _request: &Self::Req) -> Option<&'static str> { ... }
    fn before<Hook>(self, hook: Hook) -> BeforeRequestHook<Self, Hook>
       where Hook: BeforeRequest<Self::Req>,
             Self: Sized { ... }
    fn after<Hook>(self, hook: Hook) -> AfterRequestHook<Self, Hook>
       where Hook: AfterRequest<Self::Resp>,
             Self: Sized { ... }
    fn before_and_after<Hook>(
        self,
        hook: Hook
    ) -> BeforeAndAfterRequestHook<Self::Req, Self::Resp, Self, Hook>
       where Hook: BeforeRequest<Self::Req> + AfterRequest<Self::Resp>,
             Self: Sized { ... }
}
Expand description

Equivalent to a FnOnce(Req) -> impl Future<Output = Resp>.

Required Associated Types§

source

type Req

Type of request.

source

type Resp

Type of response.

Required Methods§

source

async fn serve( self, ctx: Context, req: Self::Req ) -> Result<Self::Resp, ServerError>

Responds to a single request.

Provided Methods§

source

fn method(&self, _request: &Self::Req) -> Option<&'static str>

Extracts a method name from the request.

source

fn before<Hook>(self, hook: Hook) -> BeforeRequestHook<Self, Hook>
where Hook: BeforeRequest<Self::Req>, Self: Sized,

Runs a hook before execution of the request.

If the hook returns an error, the request will not be executed and the error will be returned instead.

The hook can also modify the request context. This could be used, for example, to enforce a maximum deadline on all requests.

Any type that implements BeforeRequest can be used as the hook. Types that implement FnMut(&mut Context, &RequestType) -> impl Future<Output = Result<(), ServerError>> can also be used.

Example
use futures::{executor::block_on, future};
use tarpc::{context, ServerError, server::{Serve, serve}};
use std::io;

let serve = serve(|_ctx, i| async move { Ok(i + 1) })
    .before(|_ctx: &mut context::Context, req: &i32| {
        future::ready(
            if *req == 1 {
                Err(ServerError::new(
                    io::ErrorKind::Other,
                    format!("I don't like {req}")))
            } else {
                Ok(())
            })
    });
let response = serve.serve(context::current(), 1);
assert!(block_on(response).is_err());
source

fn after<Hook>(self, hook: Hook) -> AfterRequestHook<Self, Hook>
where Hook: AfterRequest<Self::Resp>, Self: Sized,

Runs a hook after completion of a request.

The hook can modify the request context and the response.

Any type that implements AfterRequest can be used as the hook. Types that implement FnMut(&mut Context, &mut Result<ResponseType, ServerError>) -> impl Future<Output = ()> can also be used.

Example
use futures::{executor::block_on, future};
use tarpc::{context, ServerError, server::{Serve, serve}};
use std::io;

let serve = serve(
    |_ctx, i| async move {
        if i == 1 {
            Err(ServerError::new(
                io::ErrorKind::Other,
                format!("{i} is the loneliest number")))
        } else {
            Ok(i + 1)
        }
    })
    .after(|_ctx: &mut context::Context, resp: &mut Result<i32, ServerError>| {
        if let Err(e) = resp {
            eprintln!("server error: {e:?}");
        }
        future::ready(())
    });

let response = serve.serve(context::current(), 1);
assert!(block_on(response).is_err());
source

fn before_and_after<Hook>( self, hook: Hook ) -> BeforeAndAfterRequestHook<Self::Req, Self::Resp, Self, Hook>
where Hook: BeforeRequest<Self::Req> + AfterRequest<Self::Resp>, Self: Sized,

Runs a hook before and after execution of the request.

If the hook returns an error, the request will not be executed and the error will be returned instead.

The hook can also modify the request context and the response. This could be used, for example, to enforce a maximum deadline on all requests.

Example
use futures::{executor::block_on, future};
use tarpc::{
    context, ServerError, server::{Serve, serve, request_hook::{BeforeRequest, AfterRequest}}
};
use std::{io, time::Instant};

struct PrintLatency(Instant);

impl<Req> BeforeRequest<Req> for PrintLatency {
    async fn before(&mut self, _: &mut context::Context, _: &Req) -> Result<(), ServerError> {
        self.0 = Instant::now();
        Ok(())
    }
}

impl<Resp> AfterRequest<Resp> for PrintLatency {
    async fn after(
        &mut self,
        _: &mut context::Context,
        _: &mut Result<Resp, ServerError>,
    ) {
        tracing::info!("Elapsed: {:?}", self.0.elapsed());
    }
}

let serve = serve(|_ctx, i| async move {
        Ok(i + 1)
    }).before_and_after(PrintLatency(Instant::now()));
let response = serve.serve(context::current(), 1);
assert!(block_on(response).is_ok());

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<Req, Resp, Fut, F> Serve for ServeFn<Req, Resp, F>
where F: FnOnce(Context, Req) -> Fut, Fut: Future<Output = Result<Resp, ServerError>>,

§

type Req = Req

§

type Resp = Resp

source§

impl<Req, Resp, Serv, Hook> Serve for BeforeAndAfterRequestHook<Req, Resp, Serv, Hook>
where Serv: Serve<Req = Req, Resp = Resp>, Hook: BeforeRequest<Req> + AfterRequest<Resp>,

§

type Req = Req

§

type Resp = Resp

source§

impl<Serv, Hook> Serve for AfterRequestHook<Serv, Hook>
where Serv: Serve, Hook: AfterRequest<Serv::Resp>,

§

type Req = <Serv as Serve>::Req

§

type Resp = <Serv as Serve>::Resp

source§

impl<Serv, Hook> Serve for BeforeRequestHook<Serv, Hook>
where Serv: Serve, Hook: BeforeRequest<Serv::Req>,

§

type Req = <Serv as Serve>::Req

§

type Resp = <Serv as Serve>::Resp