Skip to main content

nagisa_core/
middleware.rs

1//! 洋葱式中间件:在「整条事件分发」外层包一圈,可在 handler 前后做事、或直接拦截。
2//!
3//! 洋葱续延模型(`next()`):每个中间件做点事 → `await next.run(ctx)`
4//! → 再做点事;返回 [`Flow::Stop`](且不调用 `next`)即吞掉事件、终止传播。
5//! 限流、审计、「插件禁用」门、交互式 prompt 拦截都挂在这一层。
6use crate::ctx::Ctx;
7use crate::router::Router;
8use async_trait::async_trait;
9use std::future::Future;
10use std::pin::Pin;
11use std::sync::Arc;
12
13/// 中间件的传播控制。`Stop` = 吞掉本事件、不再下传。
14#[derive(Clone, Copy, PartialEq, Eq, Debug)]
15pub enum Flow {
16    Continue,
17    Stop,
18}
19
20/// 一个洋葱层。`handle` 内 `next.run(ctx)` 把控制权交给内层(其余中间件 + handler 循环)。
21#[async_trait]
22pub trait Middleware: Send + Sync + 'static {
23    async fn handle(&self, ctx: Arc<Ctx>, next: Next<'_>) -> Flow;
24}
25
26/// 指向「链条剩余部分」的续延:其余中间件 + 末端 handler 循环。
27pub struct Next<'a> {
28    pub(crate) remaining: &'a [Arc<dyn Middleware>],
29    pub(crate) terminal: &'a Router,
30}
31
32impl<'a> Next<'a> {
33    /// 把控制权交给内层。返回 boxed future 以打断异步递归的类型膨胀。
34    pub fn run(self, ctx: Arc<Ctx>) -> Pin<Box<dyn Future<Output = Flow> + Send + 'a>> {
35        Box::pin(async move {
36            match self.remaining.split_first() {
37                Some((mw, rest)) => {
38                    let next = Next { remaining: rest, terminal: self.terminal };
39                    mw.handle(ctx, next).await
40                }
41                None => {
42                    // 末端:跑既有的优先级 handler 循环。
43                    self.terminal.run_handlers(ctx).await;
44                    Flow::Continue
45                }
46            }
47        })
48    }
49}