-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: initial implementation for wasm plugins
- Loading branch information
1 parent
974bb0f
commit 8cf2076
Showing
7 changed files
with
179 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,20 @@ | ||
use plugins_api::{register_plugin, Plugin}; | ||
|
||
pub struct RequestIdPlugin {} | ||
|
||
impl Plugin for RequestIdPlugin { | ||
fn new() -> Self { | ||
Self {} | ||
} | ||
fn new_ctx(&self, _: String) -> String { | ||
String::from("Adds request Id to every request") | ||
} | ||
|
||
fn on_request_filter(&self, session: &plugins_api::Session, _ctx: String) -> Result<bool, ()> { | ||
let v = session.get_header("test"); | ||
println!("test: {:?}", v); | ||
Ok(true) | ||
} | ||
} | ||
|
||
register_plugin!(RequestIdPlugin); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,59 @@ | ||
#[allow(clippy::wildcard_imports)] | ||
use wit::*; | ||
|
||
#[derive(Clone, Debug, PartialEq, Ord, Eq, PartialOrd, Hash)] | ||
pub struct Context {} | ||
|
||
#[derive(Clone, Debug, PartialEq, Ord, Eq, PartialOrd, Hash)] | ||
pub struct Session {} | ||
impl Session { | ||
#[must_use] | ||
pub fn get_header(&self, _key: &str) -> Option<&str> { | ||
unimplemented!() | ||
} | ||
|
||
#[must_use] | ||
pub fn req_header() -> Option<bool> { | ||
unimplemented!() | ||
} | ||
} | ||
pub use wit::Session; | ||
|
||
pub trait Plugin: Send + Sync { | ||
fn new_ctx(ctx: String) -> String; | ||
|
||
#[must_use] | ||
fn on_request_filter( | ||
_session: Session, | ||
_ctx: Context, | ||
) -> impl std::future::Future<Output = Result<bool, ()>> { | ||
async { Ok(true) } | ||
fn new() -> Self | ||
where | ||
Self: Sized; | ||
fn new_ctx(&self, ctx: String) -> String; | ||
|
||
fn on_request_filter(&self, _session: &Session, _ctx: String) -> Result<bool, ()> { | ||
Ok(true) | ||
} | ||
} | ||
|
||
mod wit { | ||
wit_bindgen::generate!({ | ||
world: "plugin" | ||
world: "plugin", | ||
skip: ["init-plugin"] | ||
}); | ||
} | ||
|
||
wit::export!(Component); | ||
|
||
/// Registers the provided type as a Proksi plugin. | ||
#[macro_export] | ||
macro_rules! register_plugin { | ||
($plugin_type:ty) => { | ||
#[export_name = "init-plugin"] | ||
pub extern "C" fn __init_plugin() { | ||
std::env::set_current_dir(std::env::var("PWD").unwrap()).unwrap(); | ||
plugins_api::register_plugin(|| Box::new(<$plugin_type as Plugin>::new())); | ||
} | ||
}; | ||
} | ||
|
||
#[doc(hidden)] | ||
pub fn register_plugin(build_plugin: fn() -> Box<dyn Plugin>) { | ||
unsafe { PLUGIN = Some((build_plugin)()) } | ||
} | ||
|
||
fn plugin() -> &'static mut dyn Plugin { | ||
unsafe { PLUGIN.as_deref_mut().unwrap() } | ||
} | ||
|
||
static mut PLUGIN: Option<Box<dyn Plugin>> = None; | ||
|
||
struct Component; | ||
|
||
impl wit::Guest for Component { | ||
fn new_ctx(_ctx: String) -> String { | ||
String::from("hello") | ||
String::from("hello from wit") | ||
} | ||
|
||
fn on_request_filter(_session: &wit::Session, _ctx: String) -> Result<bool, ()> { | ||
Ok(true) | ||
fn on_request_filter(session: &wit::Session, ctx: String) -> Result<bool, ()> { | ||
plugin().on_request_filter(session, ctx) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,134 @@ | ||
// use std::sync::Arc; | ||
|
||
// // use wasmer::{imports, Instance, Module, Store, ValueType}; | ||
// use wasmtime::{Engine, Linker, Store}; | ||
// use wasmtime_wasi::{ | ||
// preview1::{self, WasiP1Ctx}, | ||
// WasiCtxBuilder, | ||
// }; | ||
use wasmtime::{ | ||
component::{Linker, Resource}, | ||
Engine, Store, | ||
}; | ||
use wasmtime_wasi::{add_to_linker_async, preview1::WasiP1Ctx, WasiCtxBuilder, WasiView}; | ||
|
||
// wasmtime::component::bindgen!({ | ||
// path: "../plugins_api/wit/plugin.wit", | ||
// with: { | ||
// "session": SessionTest, | ||
// } | ||
// }); | ||
|
||
#[allow(dead_code)] | ||
struct SessionTest {} | ||
#[derive(Clone)] | ||
pub struct SessionTest {} | ||
|
||
impl SessionTest { | ||
#[allow(dead_code)] | ||
pub fn new() -> Self { | ||
Self {} | ||
} | ||
#[allow(dead_code)] | ||
pub fn get_header(_key: &str) -> String { | ||
pub fn get_header(&self, _key: String) -> String { | ||
String::from("test") | ||
} | ||
} | ||
|
||
// #[allow(dead_code)] | ||
// pub async fn load_plugin() -> anyhow::Result<()> { | ||
// let mut config = wasmtime::Config::new(); | ||
// config.wasm_reference_types(true); | ||
// config.debug_info(false); | ||
// config.async_support(true); | ||
|
||
// let engine = Engine::new(&config)?; | ||
// let wasi_ctx = WasiCtxBuilder::new() | ||
// .inherit_stdio() | ||
// .inherit_stdout() | ||
// .build_p1(); | ||
|
||
// let mut linker: Linker<WasiP1Ctx> = Linker::new(&engine); | ||
// preview1::add_to_linker_async(&mut linker, |t| t)?; | ||
// let mut store = Store::new(&engine, wasi_ctx); | ||
|
||
// let module = wasmtime::Module::from_binary( | ||
// &engine, | ||
// include_bytes!("../../../../mid-test/target/wasm32-wasip1/release/mid_test.wasm"), | ||
// )?; | ||
|
||
// // instance | ||
|
||
// let instance = linker.instantiate_async(&mut store, &module).await?; | ||
|
||
// let req_filter_fn = instance.get_func(&mut store, "on_request_filter").unwrap(); | ||
|
||
// let scope = wasmtime::RootScope::new(&mut store); | ||
// let session = wasmtime::ExternRef::new(scope, Arc::new(SessionTest::new()))?; | ||
|
||
// // call function with ref | ||
// let mut ret: Vec<wasmtime::Val> = vec![wasmtime::Val::I32(0)]; | ||
// req_filter_fn | ||
// .call_async(&mut store, &[session.into()], &mut ret) | ||
// .await?; | ||
|
||
// Ok(()) | ||
// } | ||
#[allow(dead_code)] | ||
pub async fn load_plugin(path: &[u8]) -> anyhow::Result<()> { | ||
let mut config = wasmtime::Config::new(); | ||
config.wasm_reference_types(true); | ||
config.debug_info(false); | ||
config.async_support(true); | ||
|
||
let engine = Engine::new(&config)?; | ||
let wasi_ctx = WasiCtxBuilder::new() | ||
.inherit_stdio() | ||
.inherit_stdout() | ||
.build_p1(); | ||
|
||
let mut linker: Linker<WasiP1Ctx> = wasmtime::component::Linker::new(&engine); | ||
|
||
let session_now = SessionTest::new(); | ||
// let mut abc = wasmtime_wasi::ResourceTable::new(); | ||
// let res = wasi_ctx.table().push(session_now.clone())?; | ||
|
||
add_to_linker_async(&mut linker)?; | ||
let mut store = Store::new(&engine, wasi_ctx); | ||
let resource = store.data_mut().table().push(session_now.clone())?; | ||
let resource_id = resource.rep(); | ||
let module = wasmtime::component::Component::from_binary(&engine, path)?; | ||
|
||
// instance | ||
|
||
let ty = wasmtime::component::ResourceType::host::<SessionTest>(); | ||
linker.root().resource("session", ty, |mut storex, rep| { | ||
storex | ||
.data_mut() | ||
.table() | ||
.delete::<SessionTest>(Resource::new_own(rep)); | ||
Ok(()) | ||
})?; | ||
|
||
// let res_before_move: Resource<SessionTest> = | ||
// wasmtime::component::Resource::new_own(resource.rep()); | ||
|
||
// let into_any = res.try_into_resource_any(&mut store)?; | ||
|
||
// linker | ||
// .root() | ||
// .func_wrap("[method]session.get-header", |mut st, (input,)| { | ||
// let result = 1; | ||
|
||
// Ok(()) | ||
// }); | ||
// linker.root().func_new( | ||
// "[method]session.get-header", | ||
// move |mut storex, params, results| { | ||
// // in resources, the first param is the resource (self) | ||
// // let input = match params[1].clone() { | ||
// // wasmtime::component::Val::String(v) => v, | ||
// // _ => panic!("invalid input"), | ||
// // }; | ||
// // let ss = storex.data_mut().table().get(&resource)?; | ||
// // let v = ss.get_header(input); | ||
// results[0] = wasmtime::component::Val::Option(Some(Box::new( | ||
// wasmtime::component::Val::String("123".into()), | ||
// ))); | ||
|
||
// // storex.data_mut().table().delete(resource)?; | ||
|
||
// Ok(()) | ||
// }, | ||
// )?; | ||
|
||
let instance = linker.instantiate_async(&mut store, &module).await?; | ||
let req_filter_fn = instance | ||
.get_typed_func::<(Resource<SessionTest>, String), (Result<bool, ()>,)>( | ||
&mut store, | ||
"on-request-filter", | ||
) | ||
.unwrap(); | ||
|
||
let resource = store.data_mut().table().push(session_now.clone())?; | ||
|
||
let ret = req_filter_fn | ||
.call_async( | ||
&mut store, | ||
(Resource::new_own(resource.rep()), String::from("hello")), | ||
) | ||
.await?; | ||
|
||
req_filter_fn.post_return(store)?; | ||
|
||
println!("ret: {:?}", ret); | ||
Ok(()) | ||
} | ||
|
||
// #[cfg(test)] | ||
// mod tests { | ||
// use super::*; | ||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
// #[tokio::test] | ||
// async fn test_load_plugin() { | ||
// load_plugin().await.unwrap(); | ||
#[tokio::test] | ||
async fn test_load_plugin() { | ||
load_plugin(include_bytes!( | ||
"../../../../target/wasm32-wasip2/debug/plugin_request_id.wasm" | ||
)) | ||
.await | ||
.unwrap(); | ||
|
||
// assert_eq!(1, 1) | ||
// } | ||
// } | ||
assert_eq!(1, 1) | ||
} | ||
} |