Type Definition roa::Next

source · []
pub type Next<'a> = &'a mut (dyn Future<Output = Result<(), Status>> + Unpin + 'a);
Expand description

Type of the second parameter in a middleware, an alias for &mut (dyn Unpin + Future<Output = Result>)

Developer of middleware can jump to next middleware by calling next.await.

Example

use roa_core::{App, Context, Result, Status, MiddlewareExt, Next};
use roa_core::http::StatusCode;

let app = App::new()
    .gate(first)
    .gate(second)
    .gate(third)
    .end(end);
async fn first(ctx: &mut Context, next: Next<'_>) -> Result {
    assert!(ctx.store("id", "1").is_none());
    next.await?;
    assert_eq!("5", *ctx.load::<&'static str>("id").unwrap());
    Ok(())
}
async fn second(ctx: &mut Context, next: Next<'_>) -> Result {
    assert_eq!("1", *ctx.load::<&'static str>("id").unwrap());
    assert_eq!("1", *ctx.store("id", "2").unwrap());
    next.await?;
    assert_eq!("4", *ctx.store("id", "5").unwrap());
    Ok(())
}
async fn third(ctx: &mut Context, next: Next<'_>) -> Result {
    assert_eq!("2", *ctx.store("id", "3").unwrap());
    next.await?; // next is none; do nothing
    assert_eq!("3", *ctx.store("id", "4").unwrap());
    Ok(())
}

async fn end(ctx: &mut Context) -> Result {
    assert_eq!("3", *ctx.load::<&'static str>("id").unwrap());
    Ok(())
}

Error Handling

You can catch or straightly throw a Error returned by next.

use roa_core::{App, Context, Result, Status, MiddlewareExt, Next, status};
use roa_core::http::StatusCode;
         
let app = App::new()
    .gate(catch)
    .gate(gate)
    .end(status!(StatusCode::IM_A_TEAPOT, "I'm a teapot!"));

async fn catch(ctx: &mut Context, next: Next<'_>) -> Result {
    // catch
    if let Err(err) = next.await {
        // teapot is ok
        if err.status_code != StatusCode::IM_A_TEAPOT {
            return Err(err);
        }
    }
    Ok(())
}
async fn gate(ctx: &mut Context, next: Next<'_>) -> Result {
    next.await?; // just throw
    unreachable!()
}