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!()
}