pub mod wasm_types;
mod macros;
mod plugin_ctx;
mod wasm_ctx;
pub use crate::plugin_ctx::{
FormPart, HttpRequest, HttpRequestBuilder, HttpResponse, LOG_DEBUG, LOG_ERROR, LOG_INFO,
LOG_TRACE, LOG_WARN, PluginContext,
};
use aiway_protocol::context::http::{request, response};
pub use async_trait::async_trait;
pub use bytes::Bytes;
pub use http;
pub use semver::Version;
pub use serde_json;
use serde_json::Value;
pub use wasm_ctx::WasmHttpContext;
#[derive(Debug)]
pub enum PluginError {
ExecuteError(String),
NotFound(String),
LoadError(String),
SerializeError(String),
HttpError(String),
}
impl std::fmt::Display for PluginError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PluginError::ExecuteError(msg) => write!(f, "{}", msg),
PluginError::NotFound(msg) => write!(f, "{}", msg),
PluginError::LoadError(msg) => write!(f, "{}", msg),
PluginError::SerializeError(msg) => write!(f, "{}", msg),
PluginError::HttpError(msg) => write!(f, "{}", msg),
}
}
}
#[async_trait]
pub trait Plugin: Send + Sync {
fn name(&self) -> &str;
fn info(&self) -> PluginInfo;
async fn on_request(
&self,
_config: &Value,
_head: &mut request::Parts,
_ctx: &mut dyn PluginContext,
) -> Result<(), PluginError> {
Ok(())
}
async fn on_request_body(
&self,
_config: &Value,
_body: &mut Option<Bytes>,
_ctx: &mut dyn PluginContext,
) -> Result<(), PluginError> {
Ok(())
}
async fn on_response(
&self,
_config: &Value,
_head: &mut response::Parts,
_ctx: &mut dyn PluginContext,
) -> Result<(), PluginError> {
Ok(())
}
fn on_response_body(
&self,
_config: &Value,
_body: &mut Option<Bytes>,
_ctx: &mut dyn PluginContext,
) -> Result<(), PluginError> {
Ok(())
}
async fn on_logging(&self, _: &Value, _: &mut dyn PluginContext) {}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PluginInfo {
pub version: Version,
pub default_config: Value,
pub description: String,
pub readme: Option<String>,
}
pub fn block_on<F: Future>(f: F) -> F::Output {
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
fn noop_clone(_: *const ()) -> RawWaker {
RawWaker::new(std::ptr::null(), &VTABLE)
}
fn noop(_: *const ()) {}
static VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
let raw_waker = RawWaker::new(std::ptr::null(), &VTABLE);
let waker = unsafe { Waker::from_raw(raw_waker) };
let mut cx = Context::from_waker(&waker);
let mut f = std::pin::pin!(f);
match f.as_mut().poll(&mut cx) {
Poll::Ready(val) => val,
Poll::Pending => panic!(
"plugin future returned Pending in WASM context; \
WASM plugins must not perform real async I/O"
),
}
}