1pub mod wasm_types;
13
14mod macros;
15mod plugin_ctx;
16mod wasm_ctx;
17
18pub use crate::plugin_ctx::{
19 FormPart, HttpRequest, HttpRequestBuilder, HttpResponse, LOG_DEBUG, LOG_ERROR, LOG_INFO,
20 LOG_TRACE, LOG_WARN, PluginContext,
21};
22use aiway_protocol::context::http::{request, response};
23pub use async_trait::async_trait;
24pub use bytes::Bytes;
25pub use http;
26pub use semver::Version;
27pub use serde_json;
28use serde_json::Value;
29pub use wasm_ctx::WasmHttpContext;
30#[derive(Debug)]
32pub enum PluginError {
33 ExecuteError(String),
35 NotFound(String),
37 LoadError(String),
39 SerializeError(String),
41 HttpError(String),
43 Reject(u16, String),
48}
49
50impl std::fmt::Display for PluginError {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 match self {
53 PluginError::ExecuteError(msg) => write!(f, "{}", msg),
54 PluginError::NotFound(msg) => write!(f, "{}", msg),
55 PluginError::LoadError(msg) => write!(f, "{}", msg),
56 PluginError::SerializeError(msg) => write!(f, "{}", msg),
57 PluginError::HttpError(msg) => write!(f, "{}", msg),
58 PluginError::Reject(status, message) => write!(f, "[{}] {}", status, message),
59 }
60 }
61}
62
63#[async_trait]
68pub trait Plugin: Send + Sync {
69 fn name(&self) -> &str;
71 fn info(&self) -> PluginInfo;
73
74 async fn on_request(
76 &self,
77 _config: &Value,
78 _head: &mut request::Parts,
79 _ctx: &mut dyn PluginContext,
80 ) -> Result<(), PluginError> {
81 Ok(())
82 }
83
84 async fn on_request_body(
86 &self,
87 _config: &Value,
88 _body: &mut Option<Bytes>,
89 _ctx: &mut dyn PluginContext,
90 ) -> Result<(), PluginError> {
91 Ok(())
92 }
93
94 async fn on_response(
96 &self,
97 _config: &Value,
98 _head: &mut response::Parts,
99 _ctx: &mut dyn PluginContext,
100 ) -> Result<(), PluginError> {
101 Ok(())
102 }
103
104 async fn on_response_body(
106 &self,
107 _config: &Value,
108 _body: &mut Option<Bytes>,
109 _ctx: &mut dyn PluginContext,
110 ) -> Result<(), PluginError> {
111 Ok(())
112 }
113
114 async fn on_logging(&self, _: &Value, _: &mut dyn PluginContext) {}
116}
117
118#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
120pub struct PluginInfo {
121 pub version: Version,
123 pub default_config: Value,
125 pub description: String,
127 pub readme: Option<String>,
129}
130
131pub fn block_on<F: Future>(f: F) -> F::Output {
136 use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
137
138 fn noop_clone(_: *const ()) -> RawWaker {
139 RawWaker::new(std::ptr::null(), &VTABLE)
140 }
141 fn noop(_: *const ()) {}
142 static VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
143
144 let raw_waker = RawWaker::new(std::ptr::null(), &VTABLE);
145 let waker = unsafe { Waker::from_raw(raw_waker) };
146 let mut cx = Context::from_waker(&waker);
147
148 let mut f = std::pin::pin!(f);
149 match f.as_mut().poll(&mut cx) {
150 Poll::Ready(val) => val,
151 Poll::Pending => panic!(
152 "plugin future returned Pending in WASM context; \
153 WASM plugins must not perform real async I/O"
154 ),
155 }
156}