[][src]Trait roa::Middleware

pub trait Middleware<S>: 'static + Send + Sync where
    S: State
{ fn handle<'async_trait>(
        self: Arc<Self>,
        ctx: Context<S>,
        next: Pin<Box<dyn Future<Output = Result<(), Error>> + 'static>>
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'async_trait>>
    where
        Self: 'async_trait
; fn end<'async_trait>(
        self: Arc<Self>,
        ctx: Context<S>
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'async_trait>>
    where
        Self: 'async_trait
, { ... } }

Middleware

There are two kinds of middlewares, the one is functional middlewares, the another is trait middlewares.

Normal Functional Middlewares

A normal functional middleware is an object implements Fn trait:

use roa_core::{Context, Next, Result, State, Middleware};
use std::future::Future;

fn is_normal<S, F>(
    middleware: impl 'static + Send + Sync + Fn(Context<S>, Next) -> F
) -> impl Middleware<S>
where S: State,
      F: 'static + Future<Output=Result> {
    middleware
}

is_normal(|_ctx: Context<()>, next| next);

Both of function pointers and closures are middlewares:

use roa_core::{Middleware, Context, Next, Result, State};

fn is_middleware<S: State>(_: impl Middleware<S>) {}

async fn function_ptr(_ctx: Context<()>, next: Next) -> Result {
    next.await
}

// capture a variable to avoid matching lambda as function pointer.
let x = 0;
// moving is necessary to confirm closure is static.
let closure = move |ctx: Context<()>, next: Next| async move {
    let x = x;
    next.await
};

is_middleware(function_ptr);
is_middleware(closure);

Endpoints

Another kind of functional middlewares is endpoints, whose type is fn<S, F>(Context<S>) -> F where F: 'static + Send + Future<Output=Result>.

Endpoints never invoke next middleware.

use roa_core::{Middleware, Context, Result, State};
use std::future::Future;

fn is_middleware<S: State>(_: impl Middleware<S>) {}

async fn endpoint(_: Context<()>) -> Result {
    Ok(())
}
// `fn(Context<()>) -> impl 'static + Send + Future<Output=Result>` is a function pointer
// which returns value of a existential type.
//
// `fn<F>(Context<()>) -> F where F: 'static + Send + Future<Output=Result>` is a template.
//
// They are different!
//
// is_middleware(endpoint); compile fails!

fn to_middleware<F>(middleware: fn(Context<()>) -> F) -> impl Middleware<()>
where F: 'static + Future<Output=Result> {
    middleware
}

is_middleware(to_middleware(endpoint))

Trait Middlewares

A trait middleware is an object implementing trait Middleware.

use roa_core::{State, Middleware, Context, Next, Result, async_trait};
use async_std::sync::Arc;
use std::time::Instant;

fn is_middleware(_: impl Middleware<()>) {}

struct Logger;

#[async_trait(?Send)]
impl <S: State> Middleware<S> for Logger {
    async fn handle(self:Arc<Self>, ctx: Context<S>, next: Next) -> Result {
        let start = Instant::now();
        let result = next.await;
        println!("time elapsed: {}ms", start.elapsed().as_millis());
        result
    }
}

is_middleware(Logger);

Required methods

fn handle<'async_trait>(
    self: Arc<Self>,
    ctx: Context<S>,
    next: Pin<Box<dyn Future<Output = Result<(), Error>> + 'static>>
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'async_trait>> where
    Self: 'async_trait, 

Handle context and next, then return a future to get status.

Loading content...

Provided methods

fn end<'async_trait>(
    self: Arc<Self>,
    ctx: Context<S>
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'async_trait>> where
    Self: 'async_trait, 

Handle context as an endpoint.

Loading content...

Implementations on Foreign Types

impl<S, F> Middleware<S> for fn(Context<S>) -> F where
    F: 'static + Future<Output = Result<(), Error>>,
    S: State
[src]

impl<S> Middleware<S> for RouteEndpoint<S> where
    S: State

impl<F, S, Fut> Middleware<S> for Websocket<F, S, Fut> where
    F: 'static + Sync + Send + Fn(SyncContext<S>, WebSocketStream<Upgraded>) -> Fut,
    Fut: 'static + Send + Future<Output = ()>,
    S: State

Loading content...

Implementors

impl<S, F, T> Middleware<S> for T where
    F: 'static + Future<Output = Result<(), Error>>,
    S: State,
    T: 'static + Sync + Send + Fn(Context<S>, Pin<Box<dyn Future<Output = Result<(), Error>> + 'static>>) -> F, 
[src]

impl<S: State> Middleware<S> for Compress[src]

impl<S: State> Middleware<S> for Cors[src]

Loading content...