vtx_sdk/plugin/
mod.rs

1//! Low-boilerplate plugin exports.
2
3use crate::error::{VtxError, VtxResult};
4use crate::events::PluginEvent;
5use crate::http::{Request, Response, ResponseBuilder};
6use crate::{Manifest, UserContext};
7
8/// 更低样板的插件入口 Trait。
9///
10/// `wit-bindgen` 生成的 `bindings::Guest` 要求实现所有导出函数;
11/// 此 Trait 为常见方法提供默认实现,并允许在 `handle`/`handle_event` 中直接返回 `VtxResult`。
12pub trait VtxPlugin {
13    fn handle(_req: Request) -> VtxResult<Response> {
14        Ok(ResponseBuilder::not_found())
15    }
16
17    fn handle_event(_event: PluginEvent) -> VtxResult<()> {
18        Ok(())
19    }
20
21    fn get_migrations() -> Vec<String> {
22        Vec::new()
23    }
24
25    fn get_manifest() -> Manifest;
26
27    fn get_resources() -> Vec<String> {
28        Vec::new()
29    }
30
31    /// 默认返回 401,表示该插件不处理鉴权(不会阻断责任链中的其它插件)。
32    fn authenticate(_headers: &[(String, String)]) -> VtxResult<UserContext> {
33        Err(VtxError::AuthDenied(401))
34    }
35}
36
37/// 将实现了 `VtxPlugin` 的类型导出为 WIT `world plugin` 的 Guest。
38///
39/// - `export_plugin!(MyPlugin)`:生成一个默认的 guest 适配类型并导出。
40/// - `export_plugin!(MyPlugin => MyGuest)`:自定义适配类型名(同一 crate 多次调用时避免命名冲突)。
41#[macro_export]
42macro_rules! export_plugin {
43    ($plugin:ty) => {
44        $crate::export_plugin!($plugin => __VtxSdkGuest);
45    };
46    ($plugin:ty => $guest:ident) => {
47        struct $guest;
48
49        impl $crate::bindings::Guest for $guest {
50            fn handle(req: $crate::http::Request) -> $crate::http::Response {
51                match <$plugin as $crate::plugin::VtxPlugin>::handle(req) {
52                    Ok(resp) => resp,
53                    Err(err) => $crate::http::ResponseBuilder::error(err),
54                }
55            }
56
57            fn handle_event(event: $crate::events::PluginEvent) -> Result<(), String> {
58                match <$plugin as $crate::plugin::VtxPlugin>::handle_event(event) {
59                    Ok(()) => Ok(()),
60                    Err(err) => Err(err.to_string()),
61                }
62            }
63
64            fn get_migrations() -> Vec<String> {
65                <$plugin as $crate::plugin::VtxPlugin>::get_migrations()
66            }
67
68            fn get_manifest() -> $crate::Manifest {
69                <$plugin as $crate::plugin::VtxPlugin>::get_manifest()
70            }
71
72            fn get_resources() -> Vec<String> {
73                <$plugin as $crate::plugin::VtxPlugin>::get_resources()
74            }
75
76            fn authenticate(
77                headers: Vec<(String, String)>,
78            ) -> Result<$crate::UserContext, u16> {
79                use $crate::auth::IntoAuthResult as _;
80                <$plugin as $crate::plugin::VtxPlugin>::authenticate(&headers).into_auth_result()
81            }
82        }
83
84        $crate::export!($guest);
85    };
86}