vtx_sdk/
plugin.rs

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