1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
use crate::{async_trait, last, Context, Next, Result, State}; use std::future::Future; use std::sync::Arc; /// ### 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: /// /// ```rust /// 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: /// /// ```rust /// 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. /// /// ```rust /// 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`. /// /// ```rust /// 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); /// ``` #[async_trait(?Send)] pub trait Middleware<S: State>: 'static + Sync + Send { /// Handle context and next, then return a future to get status. async fn handle(self: Arc<Self>, ctx: Context<S>, next: Next) -> Result; /// Handle context as an endpoint. async fn end(self: Arc<Self>, ctx: Context<S>) -> Result { self.handle(ctx, last()).await } } #[async_trait(?Send)] impl<S, F, T> Middleware<S> for T where S: State, T: 'static + Sync + Send + Fn(Context<S>, Next) -> F, F: 'static + Future<Output = Result>, { #[inline] async fn handle(self: Arc<Self>, ctx: Context<S>, next: Next) -> Result { (self)(ctx, next).await } } #[async_trait(?Send)] impl<S, F> Middleware<S> for fn(Context<S>) -> F where S: State, F: 'static + Future<Output = Result>, { #[inline] async fn handle(self: Arc<Self>, ctx: Context<S>, _next: Next) -> Result { (self)(ctx).await } }