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::{Capabilities, 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    fn get_capabilities() -> Capabilities;
32
33    /// 默认返回 401,表示该插件不处理鉴权(不会阻断责任链中的其它插件)。
34    fn authenticate(_headers: &[(String, String)]) -> VtxResult<UserContext> {
35        Err(VtxError::AuthDenied(401))
36    }
37}
38
39/// 将实现了 `VtxPlugin` 的类型导出为 WIT `world plugin` 的 Guest。
40///
41/// - `export_plugin!(MyPlugin)`:生成一个默认的 guest 适配类型并导出。
42/// - `export_plugin!(MyPlugin => MyGuest)`:自定义适配类型名(同一 crate 多次调用时避免命名冲突)。
43#[macro_export]
44macro_rules! export_plugin {
45    ($plugin:ty) => {
46        $crate::export_plugin!($plugin => __VtxSdkGuest);
47    };
48    ($plugin:ty => $guest:ident) => {
49        struct $guest;
50
51        impl $crate::bindings::Guest for $guest {
52            fn handle(req: $crate::http::Request) -> $crate::http::Response {
53                match <$plugin as $crate::plugin::VtxPlugin>::handle(req) {
54                    Ok(resp) => resp,
55                    Err(err) => $crate::http::ResponseBuilder::error(err),
56                }
57            }
58
59            fn handle_event(event: $crate::events::PluginEvent) -> Result<(), String> {
60                match <$plugin as $crate::plugin::VtxPlugin>::handle_event(event) {
61                    Ok(()) => Ok(()),
62                    Err(err) => Err(err.to_string()),
63                }
64            }
65
66            fn get_migrations() -> Vec<String> {
67                <$plugin as $crate::plugin::VtxPlugin>::get_migrations()
68            }
69
70            fn get_manifest() -> $crate::Manifest {
71                <$plugin as $crate::plugin::VtxPlugin>::get_manifest()
72            }
73
74            fn get_resources() -> Vec<String> {
75                <$plugin as $crate::plugin::VtxPlugin>::get_resources()
76            }
77
78            fn get_capabilities() -> $crate::Capabilities {
79                <$plugin as $crate::plugin::VtxPlugin>::get_capabilities()
80            }
81
82            fn authenticate(
83                headers: Vec<(String, String)>,
84            ) -> Result<$crate::UserContext, u16> {
85                use $crate::auth::IntoAuthResult as _;
86                <$plugin as $crate::plugin::VtxPlugin>::authenticate(&headers).into_auth_result()
87            }
88        }
89
90        $crate::export!($guest);
91    };
92}