rust_webx_host/
pipeline.rs1use rust_webx_core::error::Result;
8use rust_webx_core::http::IHttpContext;
9use rust_webx_core::middleware::IMiddleware;
10use std::future::Future;
11use std::pin::Pin;
12use std::sync::Arc;
13
14pub type HandlerFn = Arc<
16 dyn for<'a> Fn(
17 &'a mut dyn IHttpContext,
18 ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>
19 + Send
20 + Sync,
21>;
22
23pub struct MiddlewarePipeline {
24 middlewares: Vec<Arc<dyn IMiddleware>>,
25}
26
27impl MiddlewarePipeline {
28 pub fn new() -> Self {
29 Self {
30 middlewares: Vec::new(),
31 }
32 }
33
34 pub fn add_middleware(&mut self, middleware: Arc<dyn IMiddleware>) {
35 self.middlewares.push(middleware);
36 }
37
38 pub async fn execute(
44 &self,
45 ctx: &mut dyn IHttpContext,
46 final_handler: HandlerFn,
47 ) -> Result<()> {
48 use std::ops::ControlFlow;
49
50 let mut executed: Vec<Arc<dyn IMiddleware>> = Vec::new();
51 let mut short_circuited = false;
52
53 for middleware in &self.middlewares {
55 match middleware.invoke(ctx).await? {
56 ControlFlow::Continue(()) => executed.push(Arc::clone(middleware)),
57 ControlFlow::Break(()) => {
58 short_circuited = true;
59 break;
60 }
61 }
62 }
63
64 if !short_circuited {
66 final_handler(ctx).await?;
67 }
68
69 for middleware in executed.into_iter().rev() {
71 middleware.after(ctx).await?;
72 }
73
74 Ok(())
75 }
76}
77
78impl Default for MiddlewarePipeline {
79 fn default() -> Self {
80 Self::new()
81 }
82}