diff --git a/cli/README.md b/cli/README.md index 64c200a..518fcdc 100644 --- a/cli/README.md +++ b/cli/README.md @@ -51,7 +51,7 @@ with wasm modules: | `wasmo config set` | path | server | clientId | clientSecret | Globally configure the CLI with the path where the configuration file will be stored and the server to reach during the build. These parameters are optional and can be passed when running the build command. | | `wasmo config get` | | Get the configuration from the configured path file or from `$HOME/.wasmo` | | `wasmo config reset` | | Clean configuration and reset to default settings. The default file path configuration will be `$HOME/.wasmo` || -| `wasmo init` | template | name | path | Initialize a WASM plugin to the specific path. You can choose between many templates, javascript/typescript (js/ts), Open Policy Agent (opa), Rust or Golang (go). | +| `wasmo init` | language | product | product_template | template | name | path | Initialize a WASM plugin to the specific path. You can choose between many templates, javascript/typescript (js/ts), Open Policy Agent (opa), Rust or Golang (go). | | `wasmo build` | path | host | server | clientId | clientSecret | Build the plugin by sending the contents to the remote or local Wasmo server. As soon as the build is complete, the WASM binary is donwloaded and saved in the plugin folder. | # Quick start @@ -63,7 +63,38 @@ wasmo build --host=OneShotDocker --path=my-first-plugin Then open the content of your `my-first-plugin` folder. You should find the generated WASM binary named `my-first-plugin-1.0.0.wasm`. -## Selecting a template +## Specifying language, product and product_template to create a plugin + +With the newer version, you should create a plugin by specifying the language to be used, the target product, and the template. + +``` +wasmo init --name=my-first-plugin --language=js --product=otoroshi --product_template=ACCESS_CONTROL +``` + +The product template parameter accepts multiple values: + - REQUEST_TRANSFORMER: Transform the content of the request with a wasm plugin + - RESPONSE_TRANSFORMER: Transform the content of a response with a wasm plugin + - ACCESS_CONTROL: Delegate route access to a wasm plugin + - BACKEND: This plugin can be used to use a wasm plugin as backend + - ROUTE_MATCHER: This plugin can be used to use a wasm plugin as route matcher + - SINK: Handle unmatched requests with a wasm plugin + - PRE_ROUTE: This plugin can be used to use a wasm plugin as in pre-route phase + +You can also create a Izanami plugin + +``` +wasmo init --name=my-first-plugin --language=js --product=izanami +``` + +For the moment, Izanami doesn't provide any templates. + +If you want to start from scratch, without targeting any products + +``` +wasmo init --name=my-first-plugin --language=js +``` + +## Or selecting a template You can now optionally start a new plugin from a template by appending `--template=[template-name]` to the creation command. diff --git a/cli/src/bin.rs b/cli/src/bin.rs index a662956..0a9e5ac 100644 --- a/cli/src/bin.rs +++ b/cli/src/bin.rs @@ -13,12 +13,10 @@ use core::panic; use hyper::{Body, Client, Method, Request}; use serde::Deserialize; use std::{ - collections::HashMap, - fs::{self, File}, - io::Write, - path::{PathBuf, Path}, str::FromStr, + collections::HashMap, fs::{self, File}, io::Write, path::{Path, PathBuf}, str::FromStr }; + use dirs; const WASMO_SERVER: &str = "WASMO_SERVER"; @@ -43,7 +41,73 @@ const OTOROSHI_ZIP_JS: &[u8] = include_bytes!("../templates/otoroshi/js.zip"); const OTOROSHI_ZIP_OPA: &[u8] = include_bytes!("../templates/otoroshi/opa.zip"); const OTOROSHI_ZIP_RUST: &[u8] = include_bytes!("../templates/otoroshi/rust.zip"); const OTOROSHI_ZIP_TS: &[u8] = include_bytes!("../templates/otoroshi/ts.zip"); - + +use lazy_static::lazy_static; + +lazy_static! { + static ref OTOROSHI_WASM_TEMPLATES_ZIPNAME: HashMap<&'static str, &'static str> = { + let mut zip_names: HashMap<&'static str, &'static str> = HashMap::new(); + zip_names.insert("ACCESS_CONTROL", "otoroshi_wasm_access_control"); + zip_names.insert("BACKEND", "otoroshi_wasm_backend"); + zip_names.insert("PRE_ROUTE", "otoroshi_wasm_pre_route"); + zip_names.insert("REQUEST_TRANSFORMER", "otoroshi_wasm_request_transformer"); + zip_names.insert("RESPONSE_TRANSFORMER", "otoroshi_wasm_response_transformer"); + zip_names.insert("ROUTE_MATCHER", "otoroshi_wasm_route_matcher"); + zip_names.insert("SINK", "otoroshi_wasm_sink"); + + zip_names + }; + static ref OTOROSHI_WASM_TEMPLATES: HashMap<&'static str, HashMap<&'static str, &'static[u8]>> = { + let mut m: HashMap<&'static str, HashMap<&'static str, &'static[u8]>> = HashMap::new(); + + let mut js_plugins: HashMap<&'static str, &'static[u8]> = HashMap::new(); + js_plugins.insert("ACCESS_CONTROL", include_bytes!("../templates/otoroshi/languages/js/otoroshi_wasm_access_control.zip")); + js_plugins.insert("BACKEND", include_bytes!("../templates/otoroshi/languages/js/otoroshi_wasm_backend.zip")); + js_plugins.insert("PRE_ROUTE", include_bytes!("../templates/otoroshi/languages/js/otoroshi_wasm_pre_route.zip")); + js_plugins.insert("REQUEST_TRANSFORMER", include_bytes!("../templates/otoroshi/languages/js/otoroshi_wasm_request_transformer.zip")); + js_plugins.insert("RESPONSE_TRANSFORMER", include_bytes!("../templates/otoroshi/languages/js/otoroshi_wasm_response_transformer.zip")); + js_plugins.insert("ROUTE_MATCHER", include_bytes!("../templates/otoroshi/languages/js/otoroshi_wasm_route_matcher.zip")); + js_plugins.insert("SINK", include_bytes!("../templates/otoroshi/languages/js/otoroshi_wasm_sink.zip")); + js_plugins.insert("EMPTY", include_bytes!("../templates/otoroshi/js.zip")); + + let mut go_plugins: HashMap<&'static str, &'static[u8]> = HashMap::new(); + go_plugins.insert("ACCESS_CONTROL", include_bytes!("../templates/otoroshi/languages/go/otoroshi_wasm_access_control.zip")); + go_plugins.insert("BACKEND", include_bytes!("../templates/otoroshi/languages/go/otoroshi_wasm_backend.zip")); + go_plugins.insert("PRE_ROUTE", include_bytes!("../templates/otoroshi/languages/go/otoroshi_wasm_pre_route.zip")); + go_plugins.insert("REQUEST_TRANSFORMER", include_bytes!("../templates/otoroshi/languages/go/otoroshi_wasm_request_transformer.zip")); + go_plugins.insert("RESPONSE_TRANSFORMER", include_bytes!("../templates/otoroshi/languages/go/otoroshi_wasm_response_transformer.zip")); + go_plugins.insert("ROUTE_MATCHER", include_bytes!("../templates/otoroshi/languages/go/otoroshi_wasm_route_matcher.zip")); + go_plugins.insert("SINK", include_bytes!("../templates/otoroshi/languages/go/otoroshi_wasm_sink.zip")); + go_plugins.insert("EMPTY", include_bytes!("../templates/otoroshi/go.zip")); + + let mut ts_plugins: HashMap<&'static str, &'static[u8]> = HashMap::new(); + ts_plugins.insert("ACCESS_CONTROL", include_bytes!("../templates/otoroshi/languages/ts/otoroshi_wasm_access_control.zip")); + ts_plugins.insert("BACKEND", include_bytes!("../templates/otoroshi/languages/ts/otoroshi_wasm_backend.zip")); + ts_plugins.insert("PRE_ROUTE", include_bytes!("../templates/otoroshi/languages/ts/otoroshi_wasm_pre_route.zip")); + ts_plugins.insert("REQUEST_TRANSFORMER", include_bytes!("../templates/otoroshi/languages/ts/otoroshi_wasm_request_transformer.zip")); + ts_plugins.insert("RESPONSE_TRANSFORMER", include_bytes!("../templates/otoroshi/languages/ts/otoroshi_wasm_response_transformer.zip")); + ts_plugins.insert("ROUTE_MATCHER", include_bytes!("../templates/otoroshi/languages/ts/otoroshi_wasm_route_matcher.zip")); + ts_plugins.insert("SINK", include_bytes!("../templates/otoroshi/languages/ts/otoroshi_wasm_sink.zip")); + ts_plugins.insert("EMPTY", include_bytes!("../templates/otoroshi/ts.zip")); + + let mut rust_plugins: HashMap<&'static str, &'static[u8]> = HashMap::new(); + rust_plugins.insert("ACCESS_CONTROL", include_bytes!("../templates/otoroshi/languages/rust/otoroshi_wasm_access_control.zip")); + rust_plugins.insert("BACKEND", include_bytes!("../templates/otoroshi/languages/rust/otoroshi_wasm_backend.zip")); + rust_plugins.insert("PRE_ROUTE", include_bytes!("../templates/otoroshi/languages/rust/otoroshi_wasm_pre_route.zip")); + rust_plugins.insert("REQUEST_TRANSFORMER", include_bytes!("../templates/otoroshi/languages/rust/otoroshi_wasm_request_transformer.zip")); + rust_plugins.insert("RESPONSE_TRANSFORMER", include_bytes!("../templates/otoroshi/languages/rust/otoroshi_wasm_response_transformer.zip")); + rust_plugins.insert("ROUTE_MATCHER", include_bytes!("../templates/otoroshi/languages/rust/otoroshi_wasm_route_matcher.zip")); + rust_plugins.insert("SINK", include_bytes!("../templates/otoroshi/languages/rust/otoroshi_wasm_sink.zip")); + rust_plugins.insert("EMPTY", include_bytes!("../templates/otoroshi/rust.zip")); + + m.insert("js", js_plugins); + m.insert("go", go_plugins); + m.insert("ts", ts_plugins); + m.insert("rust", rust_plugins); + + m + }; +} #[derive(Debug, PartialEq)] pub enum Host { @@ -125,7 +189,41 @@ enum Commands { ], require_equals = true, )] - template: String, + template: Option, + #[arg( + value_name = "PRODUCT", + // short = 'p', + long = "product", + value_parser = [ + "izanami", + "otoroshi", + "other" + ], + )] + product: Option, + /// The product template + #[arg( + value_name = "PRODUCT_TEMPLATE", + // short = 'p', + long = "product_template", + value_parser = [ + "ACCESS_CONTROL", + "BACKEND", + "PRE_ROUTE", + "REQUEST_TRANSFORMER", + "RESPONSE_TRANSFORMER", + "ROUTE_MATCHER", + "SINK", + ] + )] + product_template: Option, + /// The language + #[arg( + value_name = "LANGUAGE", + // short = 'p', + long = "language" + )] + language: Option, /// The plugin name #[arg( value_name = "NAME", @@ -281,35 +379,83 @@ fn update_metadata_file(path: &PathBuf, name: &String, template: &String) -> Was } } -fn initialize(template: String, name: String, path: Option) -> WasmoResult<()> { - logger::loading("Creating plugin ...".to_string()); +fn initialize_empty_project(language: String) -> &'static [u8] { + match language.as_str() { + "go" => EMPTY_ZIP_GO, + "js" => EMPTY_ZIP_JS, + "opa" => EMPTY_ZIP_OPA, + "rust" => EMPTY_ZIP_RUST, + "ts" => EMPTY_ZIP_TS, + _ => EMPTY_ZIP_TS + } +} - let manifest_dir = std::env::temp_dir(); +fn get_otoroshi_template(language: String, product_template: String) -> &'static [u8] { + OTOROSHI_WASM_TEMPLATES.get(language.to_uppercase().as_str()) + .unwrap() + .get(product_template.to_uppercase().as_str()).unwrap() +} - let zip_bytes = match template.as_str() { - "go" => EMPTY_ZIP_GO, - "js" => EMPTY_ZIP_JS, - "opa" => EMPTY_ZIP_OPA, - "rust" => EMPTY_ZIP_RUST, - "ts" => EMPTY_ZIP_TS, - - "izanami_go" => IZANAMI_ZIP_GO, - "izanami_js" => IZANAMI_ZIP_JS, - "izanami_opa" => IZANAMI_ZIP_OPA, - "izanami_rust" => IZANAMI_ZIP_RUST, - "izanami_ts" => IZANAMI_ZIP_TS, - - "otoroshi_go" => OTOROSHI_ZIP_GO, - "otoroshi_js" => OTOROSHI_ZIP_JS, - "otoroshi_opa" => OTOROSHI_ZIP_OPA, - "otoroshi_rust" => OTOROSHI_ZIP_RUST, - "otoroshi_ts" => OTOROSHI_ZIP_TS, - - _ => EMPTY_ZIP_JS - }; +fn initialize( + language: Option, + product: Option, + template: Option, + product_template: Option, + name: String, + path: Option) -> WasmoResult<()> { + logger::loading("Creating plugin ...".to_string()); - let language_used = template.replace("izanami_", "").replace("otoroshi_", ""); + let zip_bytes = match (language.clone(), product, template.clone(), product_template.clone()) { + (Some(language), None, None, None) => initialize_empty_project(language), + (Some(language), Some(product), None, product_template) => { + match product.as_str() { + "otoroshi" => get_otoroshi_template(language, product_template.unwrap_or("empty".to_string())), + "izanami" => match language.as_str() { + "go" => IZANAMI_ZIP_GO, + "js" => IZANAMI_ZIP_JS, + "opa" => IZANAMI_ZIP_OPA, + "rust" => IZANAMI_ZIP_RUST, + "ts" => IZANAMI_ZIP_TS, + _ => return Err(WasmoError::Raw("Unsupported language".to_string())) + }, + _ => return Err(WasmoError::Raw("Only otoroshi or izanami values are allowed as product value".to_string())) + } + }, + (None, None, Some(template), None) => + match template.as_str() { + "go" => EMPTY_ZIP_GO, + "js" => EMPTY_ZIP_JS, + "opa" => EMPTY_ZIP_OPA, + "rust" => EMPTY_ZIP_RUST, + "ts" => EMPTY_ZIP_TS, + + "izanami_go" => IZANAMI_ZIP_GO, + "izanami_js" => IZANAMI_ZIP_JS, + "izanami_opa" => IZANAMI_ZIP_OPA, + "izanami_rust" => IZANAMI_ZIP_RUST, + "izanami_ts" => IZANAMI_ZIP_TS, + + "otoroshi_go" => OTOROSHI_ZIP_GO, + "otoroshi_js" => OTOROSHI_ZIP_JS, + "otoroshi_opa" => OTOROSHI_ZIP_OPA, + "otoroshi_rust" => OTOROSHI_ZIP_RUST, + "otoroshi_ts" => OTOROSHI_ZIP_TS, + + _ => EMPTY_ZIP_JS + }, + (_, _, _, _) => return Err(WasmoError::Raw("You should provide language, product, and product_template parameters, or use only the deprecated template parameter.".to_string())) + }; + + let language_used = product_template.clone() + .map(|product| OTOROSHI_WASM_TEMPLATES_ZIPNAME.get(product.as_str()).unwrap_or(&"FAILED").to_string()) + .unwrap_or(language + .unwrap_or(template.map(|template| template.replace("izanami_", "").replace("otoroshi_", "")).unwrap_or("FAILED".to_string()))); + if language_used == "FAILED" { + return Err(WasmoError::Raw("Invalid language".to_string())); + } + + let manifest_dir = std::env::temp_dir(); let zip_path = Path::new(&manifest_dir).join(format!("{}.zip", &language_used)); if std::path::Path::new(&zip_path).exists() { @@ -326,10 +472,17 @@ fn initialize(template: String, name: String, path: Option) -> WasmoResu }; logger::indent_println("Unzipping the template ...".to_string()); - let zip_action = zip_extensions::read::zip_extract( - &PathBuf::from(zip_path), - &manifest_dir, - ); + + let zip_action = match zip_extensions::read::zip_extract( + &PathBuf::from(zip_path.clone()), + &PathBuf::from(manifest_dir.clone()) + ) { + Ok(()) => Ok(()), + Err(_) => zip_extensions::read::zip_extract( + &PathBuf::from(zip_path), + &PathBuf::from(manifest_dir.clone()).join(language_used.clone()) + ) + }; match zip_action { Ok(()) => rename_plugin(language_used, name, path), @@ -729,9 +882,12 @@ async fn main() { }, Commands::Init { template, + language, + product, + product_template, name, path, - } => initialize(template, name, path.map(absolute_path)), + } => initialize(language, product, template, product_template, name, path.map(absolute_path)), Commands::Build { server, path, diff --git a/cli/src/error.rs b/cli/src/error.rs index 4774b57..53d059b 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -10,7 +10,8 @@ pub enum WasmoError { FileSystem(String), NoDockerRunning(String), DockerContainer(String), - Configuration(String) + Configuration(String), + Raw(String) } impl fmt::Display for WasmoError { @@ -34,6 +35,9 @@ impl fmt::Display for WasmoError { }, WasmoError::Configuration(err) => { write!(f,"something happened with the configuration, {}", &err) + }, + WasmoError::Raw(err) => { + write!(f, "{}", &err) } } } diff --git a/cli/templates/otoroshi/languages/go/otoroshi_wasm_access_control.zip b/cli/templates/otoroshi/languages/go/otoroshi_wasm_access_control.zip new file mode 100644 index 0000000..9476e62 Binary files /dev/null and b/cli/templates/otoroshi/languages/go/otoroshi_wasm_access_control.zip differ diff --git a/cli/templates/otoroshi/languages/go/otoroshi_wasm_backend.zip b/cli/templates/otoroshi/languages/go/otoroshi_wasm_backend.zip new file mode 100644 index 0000000..373f5f0 Binary files /dev/null and b/cli/templates/otoroshi/languages/go/otoroshi_wasm_backend.zip differ diff --git a/cli/templates/otoroshi/languages/go/otoroshi_wasm_pre_route.zip b/cli/templates/otoroshi/languages/go/otoroshi_wasm_pre_route.zip new file mode 100644 index 0000000..27385a8 Binary files /dev/null and b/cli/templates/otoroshi/languages/go/otoroshi_wasm_pre_route.zip differ diff --git a/cli/templates/otoroshi/languages/go/otoroshi_wasm_request_transformer.zip b/cli/templates/otoroshi/languages/go/otoroshi_wasm_request_transformer.zip new file mode 100644 index 0000000..467f85b Binary files /dev/null and b/cli/templates/otoroshi/languages/go/otoroshi_wasm_request_transformer.zip differ diff --git a/cli/templates/otoroshi/languages/go/otoroshi_wasm_response_transformer.zip b/cli/templates/otoroshi/languages/go/otoroshi_wasm_response_transformer.zip new file mode 100644 index 0000000..252ed67 Binary files /dev/null and b/cli/templates/otoroshi/languages/go/otoroshi_wasm_response_transformer.zip differ diff --git a/cli/templates/otoroshi/languages/go/otoroshi_wasm_route_matcher.zip b/cli/templates/otoroshi/languages/go/otoroshi_wasm_route_matcher.zip new file mode 100644 index 0000000..1fed9f6 Binary files /dev/null and b/cli/templates/otoroshi/languages/go/otoroshi_wasm_route_matcher.zip differ diff --git a/cli/templates/otoroshi/languages/go/otoroshi_wasm_sink.zip b/cli/templates/otoroshi/languages/go/otoroshi_wasm_sink.zip new file mode 100644 index 0000000..8fa40a8 Binary files /dev/null and b/cli/templates/otoroshi/languages/go/otoroshi_wasm_sink.zip differ diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control.zip b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control.zip new file mode 100644 index 0000000..45e3ff1 Binary files /dev/null and b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control.zip differ diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/esbuild.js b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/esbuild.js new file mode 100755 index 0000000..9186020 --- /dev/null +++ b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.js'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/index.js b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/index.js new file mode 100755 index 0000000..8c72957 --- /dev/null +++ b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/index.js @@ -0,0 +1,21 @@ +export function execute() { + let context = JSON.parse(Host.inputString()) + + if (context.request.headers["foo"] === "bar") { + const out = { + result: true + } + Host.outputString(JSON.stringify(out)) + } else { + const error = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + } + Host.outputString(JSON.stringify(error)) + } + + return 0 +} \ No newline at end of file diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/package.json b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/package.json new file mode 100755 index 0000000..b1b8bb7 --- /dev/null +++ b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/package.json @@ -0,0 +1,7 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9" + } +} \ No newline at end of file diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/plugin.d.ts b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_backend.zip b/cli/templates/otoroshi/languages/js/otoroshi_wasm_backend.zip new file mode 100644 index 0000000..3f7976e Binary files /dev/null and b/cli/templates/otoroshi/languages/js/otoroshi_wasm_backend.zip differ diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_pre_route.zip b/cli/templates/otoroshi/languages/js/otoroshi_wasm_pre_route.zip new file mode 100644 index 0000000..5909bfc Binary files /dev/null and b/cli/templates/otoroshi/languages/js/otoroshi_wasm_pre_route.zip differ diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_request_transformer.zip b/cli/templates/otoroshi/languages/js/otoroshi_wasm_request_transformer.zip new file mode 100644 index 0000000..23aca92 Binary files /dev/null and b/cli/templates/otoroshi/languages/js/otoroshi_wasm_request_transformer.zip differ diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_response_transformer.zip b/cli/templates/otoroshi/languages/js/otoroshi_wasm_response_transformer.zip new file mode 100644 index 0000000..a3adda7 Binary files /dev/null and b/cli/templates/otoroshi/languages/js/otoroshi_wasm_response_transformer.zip differ diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_route_matcher.zip b/cli/templates/otoroshi/languages/js/otoroshi_wasm_route_matcher.zip new file mode 100644 index 0000000..a5bfbe8 Binary files /dev/null and b/cli/templates/otoroshi/languages/js/otoroshi_wasm_route_matcher.zip differ diff --git a/cli/templates/otoroshi/languages/js/otoroshi_wasm_sink.zip b/cli/templates/otoroshi/languages/js/otoroshi_wasm_sink.zip new file mode 100644 index 0000000..9125d5d Binary files /dev/null and b/cli/templates/otoroshi/languages/js/otoroshi_wasm_sink.zip differ diff --git a/cli/templates/otoroshi/languages/rust/otoroshi_wasm_access_control.zip b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_access_control.zip new file mode 100644 index 0000000..15a843a Binary files /dev/null and b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_access_control.zip differ diff --git a/cli/templates/otoroshi/languages/rust/otoroshi_wasm_backend.zip b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_backend.zip new file mode 100644 index 0000000..f36775d Binary files /dev/null and b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_backend.zip differ diff --git a/cli/templates/otoroshi/languages/rust/otoroshi_wasm_pre_route.zip b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_pre_route.zip new file mode 100644 index 0000000..3fa89e7 Binary files /dev/null and b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_pre_route.zip differ diff --git a/cli/templates/otoroshi/languages/rust/otoroshi_wasm_request_transformer.zip b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_request_transformer.zip new file mode 100644 index 0000000..b8c1075 Binary files /dev/null and b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_request_transformer.zip differ diff --git a/cli/templates/otoroshi/languages/rust/otoroshi_wasm_response_transformer.zip b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_response_transformer.zip new file mode 100644 index 0000000..9773a64 Binary files /dev/null and b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_response_transformer.zip differ diff --git a/cli/templates/otoroshi/languages/rust/otoroshi_wasm_route_matcher.zip b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_route_matcher.zip new file mode 100644 index 0000000..5e9ed11 Binary files /dev/null and b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_route_matcher.zip differ diff --git a/cli/templates/otoroshi/languages/rust/otoroshi_wasm_sink.zip b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_sink.zip new file mode 100644 index 0000000..6dbddf2 Binary files /dev/null and b/cli/templates/otoroshi/languages/rust/otoroshi_wasm_sink.zip differ diff --git a/cli/templates/otoroshi/languages/ts/otoroshi_wasm_access_control.zip b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_access_control.zip new file mode 100644 index 0000000..d47bdcf Binary files /dev/null and b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_access_control.zip differ diff --git a/cli/templates/otoroshi/languages/ts/otoroshi_wasm_backend.zip b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_backend.zip new file mode 100644 index 0000000..bc49b7c Binary files /dev/null and b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_backend.zip differ diff --git a/cli/templates/otoroshi/languages/ts/otoroshi_wasm_pre_route.zip b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_pre_route.zip new file mode 100644 index 0000000..d47bdcf Binary files /dev/null and b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_pre_route.zip differ diff --git a/cli/templates/otoroshi/languages/ts/otoroshi_wasm_request_transformer.zip b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_request_transformer.zip new file mode 100644 index 0000000..06f6f8b Binary files /dev/null and b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_request_transformer.zip differ diff --git a/cli/templates/otoroshi/languages/ts/otoroshi_wasm_response_transformer.zip b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_response_transformer.zip new file mode 100644 index 0000000..9333ea6 Binary files /dev/null and b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_response_transformer.zip differ diff --git a/cli/templates/otoroshi/languages/ts/otoroshi_wasm_route_matcher.zip b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_route_matcher.zip new file mode 100644 index 0000000..1e45d9c Binary files /dev/null and b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_route_matcher.zip differ diff --git a/cli/templates/otoroshi/languages/ts/otoroshi_wasm_sink.zip b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_sink.zip new file mode 100644 index 0000000..b5667d6 Binary files /dev/null and b/cli/templates/otoroshi/languages/ts/otoroshi_wasm_sink.zip differ diff --git a/docs/documentation/app/cli/getting-started/_page.mdx b/docs/documentation/app/cli/getting-started/_page.mdx index 6851926..20bbc92 100644 --- a/docs/documentation/app/cli/getting-started/_page.mdx +++ b/docs/documentation/app/cli/getting-started/_page.mdx @@ -39,7 +39,38 @@ wasmo build --host=OneShotDocker --path=my-first-plugin Then open the content of your `my-first-plugin` folder. You should find the generated WASM binary named `my-first-plugin-1.0.0.wasm`. -## Selecting a template +## Specifying language and product to create a plugin + +With the newer version, you should create a plugin by specifying the language to be used, the target product, and the template. + +``` +wasmo init --name=my-first-plugin --language=js --product=otoroshi --product_template=ACCESS_CONTROL +``` + +The product template parameter accepts multiple values: + - **REQUEST_TRANSFORMER**: Transform the content of the request with a wasm plugin + - **RESPONSE_TRANSFORMER**: Transform the content of a response with a wasm plugin + - **ACCESS_CONTROL**: Delegate route access to a wasm plugin + - **BACKEND**: This plugin can be used to use a wasm plugin as backend + - **ROUTE_MATCHER**: This plugin can be used to use a wasm plugin as route matcher + - **SINK**: Handle unmatched requests with a wasm plugin + - **PRE_ROUTE**: This plugin can be used to use a wasm plugin as in pre-route phase + +You can also create a Izanami plugin + +``` +wasmo init --name=my-first-plugin --language=js --product=izanami +``` + +For the moment, Izanami doesn't provide any templates. + +If you want to start from scratch, without targeting any products + +``` +wasmo init --name=my-first-plugin --language=js +``` + +## Or selecting a template You can now optionally start a new plugin from a template by appending `--template=[template-name]` to the creation command. diff --git a/docs/documentation/app/integrations/otoroshi/_page.mdx b/docs/documentation/app/integrations/otoroshi/_page.mdx index d9cc935..9decf69 100644 --- a/docs/documentation/app/integrations/otoroshi/_page.mdx +++ b/docs/documentation/app/integrations/otoroshi/_page.mdx @@ -39,3 +39,211 @@ To have more informations about Otoroshi and Wasmo, you can follow the two tutor - [Wasm usage](https://maif.github.io/otoroshi/manual/how-to-s/wasm-usage.html) - [Wasmo and Otoroshi](https://maif.github.io/otoroshi/manual/how-to-s/wasmo-installation.html) + +## Otoroshi plugins + +Wasmo can initialize plugins with predefined Otoroshi templates, which you can find directly on the UI. + +### Wasm Pre-Route + +This plugin can be used to use a wasm plugin as in pre-route phase + +```js +export function execute() { + let context = JSON.parse(Host.inputString()); + + if (context.request.headers["foo"] === "bar") { + const out = { + result: true + }; + Host.outputString(JSON.stringify(out)); + } else { + const error = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + }; + Host.outputString(JSON.stringify(error)); + } + + return 0; + } +``` + +### Wasm Request Transformer + +Transform the content of the request with a wasm plugin + +```js +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + ...context, + method: "POST", + headers: { + ...context.otoroshi_request.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_REQUEST_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + } + })) + + return 0 +} +``` + +### Wasm Response Transformer + +Transform the content of a response with a wasm plugin + +```js +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + ...context, + status: 200, + headers: { + ...context.otoroshi_response.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_RESPONSE_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + }, + // cookies + })) + + return 0 +} +``` + +### Wasm Route matcher + +The "matcher" is a tool that allows filtering a route during the routing phase. +In practice, you can create two routes that are identical from a frontend perspective +but have different "route matchers." +These matchers will select one route or the other based on a specific criterion. + +```js +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + result: context.request.headers.foo === "bar" + })) + + return 0 +} +``` + +### Wasm Sink + +Handle unmatched requests with a wasm plugin + +```js +export function sink_matches() { + // const context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + result: true + })) + + return 0 +} + +export function sink_handle() { + const context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + status: 200, + headers: { + 'Content-Type': 'application/json' + }, + body_json: { + "WASM_SINK_RESPONSE": `Unknown path and domain for ${context.request.path}` + } + })) + + return 0 +} +``` + +### Wasm Access Control + +Delegate route access to a wasm plugin + +```js +export function execute() { + let context = JSON.parse(Host.inputString()) + + if (context.request.headers["foo"] === "bar") { + const out = { + result: true + } + Host.outputString(JSON.stringify(out)) + } else { + const error = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + } + Host.outputString(JSON.stringify(error)) + } + + return 0 +} +``` + +### Wasm Backend + +This plugin can be used to use a wasm plugin as backend + +```js +export function execute() { + const str = Host.inputString() + const context = JSON.parse(str) + + let headers = { ...context.request.headers } + headers["foo"] = "bar" + + const response = { + headers, + 'Content-Type': "text/html", + body: ` + + + + + + + +

This HTML comes from the Wasmo plugin

+ + + + `, + status: 200 + } + + Host.outputString(JSON.stringify(response)) + + return 0 +} +``` \ No newline at end of file diff --git a/server/datastores/postgres.js b/server/datastores/postgres.js index ed0026c..9deb051 100755 --- a/server/datastores/postgres.js +++ b/server/datastores/postgres.js @@ -257,10 +257,11 @@ module.exports = class PgDatastore extends Datastore { filename: metadata.name.replace(/ /g, '-'), type: metadata.type, pluginId: pluginId, - template: metadata.template + template: metadata.template, + productTemplate: metadata.productTemplate } - console.log('generate pluginID', pluginId, newPlugin.pluginId) + console.log('generate pluginID', pluginId, newPlugin) return this.pool.connect() .then(client => { diff --git a/server/datastores/s3.js b/server/datastores/s3.js index 298bb65..b863912 100755 --- a/server/datastores/s3.js +++ b/server/datastores/s3.js @@ -550,7 +550,8 @@ module.exports = class S3Datastore extends Datastore { filename: metadata.name.replace(/ /g, '-'), type: metadata.type, pluginId: pluginId, - template: metadata.template + template: metadata.template, + productTemplate: metadata.productTemplate }; console.log('generate pluginID', pluginId, newPlugin.pluginId) diff --git a/server/index.js b/server/index.js index 5db004b..618e8fe 100755 --- a/server/index.js +++ b/server/index.js @@ -13,6 +13,7 @@ const { ENV, AUTHENTICATION } = require('./configuration'); const pluginsRouter = require('./routers/plugins'); const templatesRouter = require('./routers/templates'); +const productsTemplatesRouter = require('./routers/products_templates'); const publicRouter = require('./routers/public'); const wasmRouter = require('./routers/wasm'); const invitationRouter = require('./routers/invitation'); @@ -125,6 +126,7 @@ function createServer(appVersion) { app.use(`${baseURL}/`, publicRouter); app.use(`${baseURL}/api/plugins`, pluginsRouter); app.use(`${baseURL}/api/templates`, templatesRouter); + app.use(`${baseURL}/api/products_templates`, productsTemplatesRouter); app.use(`${baseURL}/api/wasm`, wasmRouter); app.use(`${baseURL}/api/version`, (_, res) => res.json(appVersion)); app.use(`${baseURL}/api/development`, (_, res) => res.json(ENV.IS_DEV)); diff --git a/server/routers/plugins.js b/server/routers/plugins.js index 9e91b6a..e7ea94f 100755 --- a/server/routers/plugins.js +++ b/server/routers/plugins.js @@ -116,7 +116,8 @@ router.post('/', async (req, res) => { const out = await Datastore.createEmptyPlugin(req.user.email, req.body.metadata || { name: req.body.plugin, type: req.body.type, - template: req.body.template || 'empty' + template: req.body.template || 'empty', + productTemplate: req.body.productTemplate }); if (out.status !== 201 || !req.body.files) { diff --git a/server/routers/products_templates.js b/server/routers/products_templates.js new file mode 100755 index 0000000..cc9a27b --- /dev/null +++ b/server/routers/products_templates.js @@ -0,0 +1,84 @@ +const fetch = require('node-fetch'); +const express = require('express'); +const path = require('path'); +const { FileSystem } = require('../services/file-system'); +const { ENV } = require('../configuration'); + +const LANGUAGES_INDEX = { + rust: 'lib.rs', + js: 'index.js', + ts: 'index.ts', + go: 'main.go' +}; + +const router = express.Router() + +router.get('/', (req, res) => { + if (!req.query) { + res + .status(400) + .json({ + error: 'Missing type of project' + }) + } else { + const { type, productTemplate } = req.query; + // const template = !req.query.template || req.query.template === 'undefined' ? 'empty' : req.query.template; + + if (['rust', 'js', 'go', 'ts'].includes(type)) { + const path = `templates/otoroshi/${productTemplate}/${LANGUAGES_INDEX[type]}` + + getTemplates(path, res); + } else { + res + .status(404) + .json({ + error: 'No template for this type of project' + }) + } + } +}); + +function getTemplatesFromPath(type, template, res) { + console.log(path.join(__dirname, '../templates', template, `${type}.zip`)) + if (template !== 'empty') + return res.sendFile(path.join(__dirname, '../templates', template, `${type}.zip`)) + else + return res.sendFile(path.join(__dirname, '../templates', `${type}.zip`)) +} + +function getTemplates(templatePath, res) { + const source = ENV.MANAGER_TEMPLATES; + + if (!source) { + return res.sendFile(path.join(__dirname, '..', templatePath)) + } else if (source.startsWith('file://')) { + const paths = [templatePath] + + FileSystem.existsFile(...paths) + .then(() => { + res.download(FileSystem.pathsToPath(...paths), 'data') + }) + .catch(err => { + res + .status(400) + .json({ error: err }) + }) + } else if (source.startsWith('http')) { + fetch(`${source}/${templatePath}`, { + redirect: 'follow' + }) + .then(r => r.json()) + .then(r => { + fetch(r.download_url) + .then(raw => raw.body.pipe(res)) + }) + } else { + res + .status(404) + .json({ + error: 'No template for this type of project' + }) + } +} + +module.exports = router \ No newline at end of file diff --git a/server/routers/templates.js b/server/routers/templates.js index 6dfa014..be2c438 100755 --- a/server/routers/templates.js +++ b/server/routers/templates.js @@ -14,11 +14,11 @@ router.get('/', (req, res) => { error: 'Missing type of project' }) } else { - const { type } = req.query; + const { type, productTemplate } = req.query; const template = !req.query.template || req.query.template === 'undefined' ? 'empty' : req.query.template; - + if (['rust', 'js', 'go', 'ts', 'opa'].includes(type)) { - getTemplates(type, template, res); + getTemplates(type, template, productTemplate, res); } else { res .status(404) @@ -36,7 +36,7 @@ function getTemplatesFromPath(type, template, res) { return res.sendFile(path.join(__dirname, '../templates', `${type}.zip`)) } -function getTemplates(type, template, res) { +function getTemplates(type, template, productTemplate, res) { const source = ENV.MANAGER_TEMPLATES; const zipName = `${type}.zip`; diff --git a/server/templates/izanami/js.zip b/server/templates/izanami/js.zip index 8d927e5..bbbd186 100644 Binary files a/server/templates/izanami/js.zip and b/server/templates/izanami/js.zip differ diff --git a/server/templates/izanami/js/esbuild.js b/server/templates/izanami/js/esbuild.js index 50edc7c..9186020 100755 --- a/server/templates/izanami/js/esbuild.js +++ b/server/templates/izanami/js/esbuild.js @@ -1,4 +1,4 @@ -const esbuild = require('esbuild'); +const esbuild = require('esbuild') esbuild .build({ diff --git a/server/templates/izanami/ts.zip b/server/templates/izanami/ts.zip index 9c400c2..01dc2b2 100644 Binary files a/server/templates/izanami/ts.zip and b/server/templates/izanami/ts.zip differ diff --git a/server/templates/izanami/ts/esbuild.js b/server/templates/izanami/ts/esbuild.js index 0afe91f..1e13e53 100755 --- a/server/templates/izanami/ts/esbuild.js +++ b/server/templates/izanami/ts/esbuild.js @@ -1,4 +1,4 @@ -const esbuild = require('esbuild'); +const esbuild = require('esbuild') esbuild .build({ diff --git a/server/templates/js.zip b/server/templates/js.zip index 1d24ccf..fc9c670 100644 Binary files a/server/templates/js.zip and b/server/templates/js.zip differ diff --git a/server/templates/js/esbuild.js b/server/templates/js/esbuild.js index 50edc7c..9186020 100755 --- a/server/templates/js/esbuild.js +++ b/server/templates/js/esbuild.js @@ -1,4 +1,4 @@ -const esbuild = require('esbuild'); +const esbuild = require('esbuild') esbuild .build({ diff --git a/server/templates/languages/go/otoroshi_wasm_access_control/go.mod b/server/templates/languages/go/otoroshi_wasm_access_control/go.mod new file mode 100755 index 0000000..25268c7 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_access_control/go.mod @@ -0,0 +1,6 @@ +module @@PLUGIN_NAME@@/@@PLUGIN_VERSION@@ + +go 1.21 + +require github.com/buger/jsonparser v1.1.1 // indirect +// require github.com/MAIF/otoroshi-go-types v0.0.2 // toggle this line if you want to use Otoroshi Host functions \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_access_control/main.go b/server/templates/languages/go/otoroshi_wasm_access_control/main.go new file mode 100755 index 0000000..6db7fa6 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_access_control/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var foo, err = jsonparser.GetString(input, "request", "headers", "foo") + + if err != nil { + } + + var output = "" + + if foo == "bar" { + output = `{ + "result": true + }` + } else { + output = `{ + "result": false, + "error": { + "message": "you're not authorized", + "status": 401 + } + }` + } + + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/languages/go/otoroshi_wasm_backend/go.mod b/server/templates/languages/go/otoroshi_wasm_backend/go.mod new file mode 100755 index 0000000..25268c7 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_backend/go.mod @@ -0,0 +1,6 @@ +module @@PLUGIN_NAME@@/@@PLUGIN_VERSION@@ + +go 1.21 + +require github.com/buger/jsonparser v1.1.1 // indirect +// require github.com/MAIF/otoroshi-go-types v0.0.2 // toggle this line if you want to use Otoroshi Host functions \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_backend/main.go b/server/templates/languages/go/otoroshi_wasm_backend/main.go new file mode 100755 index 0000000..41e73c3 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_backend/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "github.com/extism/go-pdk" + "github.com/buger/jsonparser" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var headers, dataType, offset, err = jsonparser.Get(input, "request", "headers") + + _ = dataType + _ = offset + _ = headers + + if err != nil {} + + output := `{ "headers": { "Content-Type": "text/html" }, "body": "

This HTML comes from the Wasmo plugin

", "status": 200 }` + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_pre_route/go.mod b/server/templates/languages/go/otoroshi_wasm_pre_route/go.mod new file mode 100755 index 0000000..25268c7 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_pre_route/go.mod @@ -0,0 +1,6 @@ +module @@PLUGIN_NAME@@/@@PLUGIN_VERSION@@ + +go 1.21 + +require github.com/buger/jsonparser v1.1.1 // indirect +// require github.com/MAIF/otoroshi-go-types v0.0.2 // toggle this line if you want to use Otoroshi Host functions \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_pre_route/main.go b/server/templates/languages/go/otoroshi_wasm_pre_route/main.go new file mode 100755 index 0000000..e967039 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_pre_route/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "github.com/extism/go-pdk" + "github.com/buger/jsonparser" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var foo, err = jsonparser.GetString(input, "request", "headers", "foo") + + if err != nil {} + + var output = "" + + if foo == "bar" { + output = `{ + "result": true + }` + } else { + output = `{ + "result": false, + "error": { + "message": "you're not authorized", + "status": 401 + } + }` + } + + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_request_transformer/go.mod b/server/templates/languages/go/otoroshi_wasm_request_transformer/go.mod new file mode 100755 index 0000000..25268c7 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_request_transformer/go.mod @@ -0,0 +1,6 @@ +module @@PLUGIN_NAME@@/@@PLUGIN_VERSION@@ + +go 1.21 + +require github.com/buger/jsonparser v1.1.1 // indirect +// require github.com/MAIF/otoroshi-go-types v0.0.2 // toggle this line if you want to use Otoroshi Host functions \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_request_transformer/main.go b/server/templates/languages/go/otoroshi_wasm_request_transformer/main.go new file mode 100755 index 0000000..5eb4001 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_request_transformer/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "encoding/json" + + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var headers, dataType, offset, err = jsonparser.Get(input, "request", "headers") + + _ = dataType + _ = offset + + var outHeaders map[string]interface{} + + // Unmarshal the JSON data into the map + err = json.Unmarshal(headers, &outHeaders) + if err != nil { + + } + + outHeaders["Content-Type"] = "application/json" + outHeaders["OTOROSHI_WASM_PLUGIN_ID"] = "OTOROSHI_WASM_REQUEST_TRANSFORMER" + + if err != nil { + } + + jsonHeaders, marshallingError := json.Marshal(outHeaders) + if marshallingError != nil { + + } + + output := `{ + "method": "POST", + "headers": ` + string(jsonHeaders) + `, + "body_json": { "foo": "bar" } + }` + + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/languages/go/otoroshi_wasm_response_transformer/go.mod b/server/templates/languages/go/otoroshi_wasm_response_transformer/go.mod new file mode 100755 index 0000000..25268c7 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_response_transformer/go.mod @@ -0,0 +1,6 @@ +module @@PLUGIN_NAME@@/@@PLUGIN_VERSION@@ + +go 1.21 + +require github.com/buger/jsonparser v1.1.1 // indirect +// require github.com/MAIF/otoroshi-go-types v0.0.2 // toggle this line if you want to use Otoroshi Host functions \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_response_transformer/main.go b/server/templates/languages/go/otoroshi_wasm_response_transformer/main.go new file mode 100755 index 0000000..58b131b --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_response_transformer/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "encoding/json" + + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var headers, dataType, offset, err = jsonparser.Get(input, "request", "headers") + + _ = dataType + _ = offset + + var outHeaders map[string]interface{} + + // Unmarshal the JSON data into the map + err = json.Unmarshal(headers, &outHeaders) + if err != nil { + + } + + outHeaders["Content-Type"] = "application/json" + outHeaders["OTOROSHI_WASM_PLUGIN_ID"] = "OTOROSHI_WASM_RESPONSE_TRANSFORMER" + + if err != nil { + } + + jsonHeaders, marshallingError := json.Marshal(outHeaders) + if marshallingError != nil { + + } + + output := `{ + "status": 200, + "headers": ` + string(jsonHeaders) + `, + "body_json": { "foo": "bar" } + }` + + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/languages/go/otoroshi_wasm_route_matcher/go.mod b/server/templates/languages/go/otoroshi_wasm_route_matcher/go.mod new file mode 100755 index 0000000..25268c7 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_route_matcher/go.mod @@ -0,0 +1,6 @@ +module @@PLUGIN_NAME@@/@@PLUGIN_VERSION@@ + +go 1.21 + +require github.com/buger/jsonparser v1.1.1 // indirect +// require github.com/MAIF/otoroshi-go-types v0.0.2 // toggle this line if you want to use Otoroshi Host functions \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_route_matcher/main.go b/server/templates/languages/go/otoroshi_wasm_route_matcher/main.go new file mode 100755 index 0000000..943f38f --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_route_matcher/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" + + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var foo, err = jsonparser.GetString(input, "request", "headers", "foo") + + if err != nil { + } + + output := `{ "result": ` + strconv.FormatBool(foo == "bar") + `}` + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/languages/go/otoroshi_wasm_sink/go.mod b/server/templates/languages/go/otoroshi_wasm_sink/go.mod new file mode 100755 index 0000000..25268c7 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_sink/go.mod @@ -0,0 +1,6 @@ +module @@PLUGIN_NAME@@/@@PLUGIN_VERSION@@ + +go 1.21 + +require github.com/buger/jsonparser v1.1.1 // indirect +// require github.com/MAIF/otoroshi-go-types v0.0.2 // toggle this line if you want to use Otoroshi Host functions \ No newline at end of file diff --git a/server/templates/languages/go/otoroshi_wasm_sink/main.go b/server/templates/languages/go/otoroshi_wasm_sink/main.go new file mode 100755 index 0000000..0dcd089 --- /dev/null +++ b/server/templates/languages/go/otoroshi_wasm_sink/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" + // "github.com/MAIF/otoroshi-go-types" +) + +//export sink_matches +func sink_matches() int32 { + output := `{ "result": true }` + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +//export sink_handle +func sink_handle() int32 { + input := pdk.Input() + + var path, err = jsonparser.GetString(input, "request", "path") + + if err != nil { + } + + output := `{ + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "body_json": { + "WASM_SINK_RESPONSE": "Unknown path and domain for ` + path + `" + } + }` + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/languages/js/otoroshi_wasm_access_control/esbuild.js b/server/templates/languages/js/otoroshi_wasm_access_control/esbuild.js new file mode 100755 index 0000000..9186020 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_access_control/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.js'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/js/otoroshi_wasm_access_control/index.js b/server/templates/languages/js/otoroshi_wasm_access_control/index.js new file mode 100755 index 0000000..8c72957 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_access_control/index.js @@ -0,0 +1,21 @@ +export function execute() { + let context = JSON.parse(Host.inputString()) + + if (context.request.headers["foo"] === "bar") { + const out = { + result: true + } + Host.outputString(JSON.stringify(out)) + } else { + const error = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + } + Host.outputString(JSON.stringify(error)) + } + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_access_control/package.json b/server/templates/languages/js/otoroshi_wasm_access_control/package.json new file mode 100755 index 0000000..b1b8bb7 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_access_control/package.json @@ -0,0 +1,7 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9" + } +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_access_control/plugin.d.ts b/server/templates/languages/js/otoroshi_wasm_access_control/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_access_control/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_backend/esbuild.js b/server/templates/languages/js/otoroshi_wasm_backend/esbuild.js new file mode 100755 index 0000000..9186020 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_backend/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.js'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/js/otoroshi_wasm_backend/index.js b/server/templates/languages/js/otoroshi_wasm_backend/index.js new file mode 100755 index 0000000..90409d3 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_backend/index.js @@ -0,0 +1,39 @@ +export function execute() { + const str = Host.inputString() + const context = JSON.parse(str) + + let headers = { ...context.request.headers } + headers["foo"] = "bar" + + const response = { + headers, + 'Content-Type': "text/html", + body: ` + + + + + + + +

This HTML comes from the Wasmo plugin

+ + + + `, + status: 200 + } + + Host.outputString(JSON.stringify(response)) + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_backend/package.json b/server/templates/languages/js/otoroshi_wasm_backend/package.json new file mode 100755 index 0000000..b1b8bb7 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_backend/package.json @@ -0,0 +1,7 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9" + } +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_backend/plugin.d.ts b/server/templates/languages/js/otoroshi_wasm_backend/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_backend/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_pre_route/esbuild.js b/server/templates/languages/js/otoroshi_wasm_pre_route/esbuild.js new file mode 100755 index 0000000..9186020 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_pre_route/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.js'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/js/otoroshi_wasm_pre_route/index.js b/server/templates/languages/js/otoroshi_wasm_pre_route/index.js new file mode 100755 index 0000000..c54cb54 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_pre_route/index.js @@ -0,0 +1,21 @@ +export function execute() { + let context = JSON.parse(Host.inputString()); + + if (context.request.headers["foo"] === "bar") { + const out = { + result: true + }; + Host.outputString(JSON.stringify(out)); + } else { + const error = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + }; + Host.outputString(JSON.stringify(error)); + } + + return 0; + } \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_pre_route/package.json b/server/templates/languages/js/otoroshi_wasm_pre_route/package.json new file mode 100755 index 0000000..b1b8bb7 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_pre_route/package.json @@ -0,0 +1,7 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9" + } +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_pre_route/plugin.d.ts b/server/templates/languages/js/otoroshi_wasm_pre_route/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_pre_route/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_request_transformer/esbuild.js b/server/templates/languages/js/otoroshi_wasm_request_transformer/esbuild.js new file mode 100755 index 0000000..9186020 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_request_transformer/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.js'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/js/otoroshi_wasm_request_transformer/index.js b/server/templates/languages/js/otoroshi_wasm_request_transformer/index.js new file mode 100755 index 0000000..03485bd --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_request_transformer/index.js @@ -0,0 +1,18 @@ +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + ...context, + method: "POST", + headers: { + ...context.otoroshi_request.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_REQUEST_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + } + })) + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_request_transformer/package.json b/server/templates/languages/js/otoroshi_wasm_request_transformer/package.json new file mode 100755 index 0000000..b1b8bb7 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_request_transformer/package.json @@ -0,0 +1,7 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9" + } +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_request_transformer/plugin.d.ts b/server/templates/languages/js/otoroshi_wasm_request_transformer/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_request_transformer/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_response_transformer/esbuild.js b/server/templates/languages/js/otoroshi_wasm_response_transformer/esbuild.js new file mode 100755 index 0000000..9186020 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_response_transformer/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.js'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/js/otoroshi_wasm_response_transformer/index.js b/server/templates/languages/js/otoroshi_wasm_response_transformer/index.js new file mode 100755 index 0000000..91fe07b --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_response_transformer/index.js @@ -0,0 +1,19 @@ +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + ...context, + status: 200, + headers: { + ...context.otoroshi_response.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_RESPONSE_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + }, + // cookies + })) + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_response_transformer/package.json b/server/templates/languages/js/otoroshi_wasm_response_transformer/package.json new file mode 100755 index 0000000..b1b8bb7 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_response_transformer/package.json @@ -0,0 +1,7 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9" + } +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_response_transformer/plugin.d.ts b/server/templates/languages/js/otoroshi_wasm_response_transformer/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_response_transformer/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_route_matcher/esbuild.js b/server/templates/languages/js/otoroshi_wasm_route_matcher/esbuild.js new file mode 100755 index 0000000..9186020 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_route_matcher/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.js'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/js/otoroshi_wasm_route_matcher/index.js b/server/templates/languages/js/otoroshi_wasm_route_matcher/index.js new file mode 100755 index 0000000..52902e3 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_route_matcher/index.js @@ -0,0 +1,15 @@ +/* + The "matcher" is a tool that allows filtering a route during the routing phase. + In practice, you can create two routes that are identical from a frontend perspective + but have different "route matchers." + These matchers will select one route or the other based on a specific criterion. +*/ +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + result: context.request.headers.foo === "bar" + })) + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_route_matcher/package.json b/server/templates/languages/js/otoroshi_wasm_route_matcher/package.json new file mode 100755 index 0000000..b1b8bb7 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_route_matcher/package.json @@ -0,0 +1,7 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9" + } +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_route_matcher/plugin.d.ts b/server/templates/languages/js/otoroshi_wasm_route_matcher/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_route_matcher/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_sink/esbuild.js b/server/templates/languages/js/otoroshi_wasm_sink/esbuild.js new file mode 100755 index 0000000..9186020 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_sink/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.js'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/js/otoroshi_wasm_sink/index.js b/server/templates/languages/js/otoroshi_wasm_sink/index.js new file mode 100755 index 0000000..7e63900 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_sink/index.js @@ -0,0 +1,25 @@ +export function sink_matches() { + // const context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + result: true + })) + + return 0 +} + +export function sink_handle() { + const context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + status: 200, + headers: { + 'Content-Type': 'application/json' + }, + body_json: { + "WASM_SINK_RESPONSE": `Unknown path and domain for ${context.request.path}` + } + })) + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_sink/package.json b/server/templates/languages/js/otoroshi_wasm_sink/package.json new file mode 100755 index 0000000..b1b8bb7 --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_sink/package.json @@ -0,0 +1,7 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9" + } +} \ No newline at end of file diff --git a/server/templates/languages/js/otoroshi_wasm_sink/plugin.d.ts b/server/templates/languages/js/otoroshi_wasm_sink/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/js/otoroshi_wasm_sink/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/rust/otoroshi_wasm_access_control/Cargo.toml b/server/templates/languages/rust/otoroshi_wasm_access_control/Cargo.toml new file mode 100755 index 0000000..6d0f75d --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_access_control/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "@@PLUGIN_NAME@@" +version = "@@PLUGIN_VERSION@@" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata] +wasi = false + +[dependencies] +extism-pdk = "1.0.1" +serde = "1.0.152" +serde_json = "1.0.91" +otoroshi_rust_types = "1.0.0" + +[lib] +crate_type = ["cdylib"] +path = "src/lib.rs" diff --git a/server/templates/languages/rust/otoroshi_wasm_access_control/lib.rs b/server/templates/languages/rust/otoroshi_wasm_access_control/lib.rs new file mode 100755 index 0000000..77574af --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_access_control/lib.rs @@ -0,0 +1,105 @@ +use extism_pdk::*; +use otoroshi_rust_types::types::*; + +#[plugin_fn] +pub fn execute( + Json(_context): Json, +) -> FnResult> { + let out = WasmAccessValidatorResponse { + result: false, + error: Some(WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + Ok(Json(out)) +} + +/* + +// WasmRouteMatcher + +#[plugin_fn] +pub fn matches_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmPreRoute + +#[plugin_fn] +pub fn pre_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmAccessValidator + +#[plugin_fn] +pub fn can_access(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestTransformer + + +#[plugin_fn] +pub fn transform_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmBackend + +#[plugin_fn] +pub fn call_backend(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmResponseTransformer + +#[plugin_fn] +pub fn transform_response(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmSink + +#[plugin_fn] +pub fn sink_matches(Json(_context): Json) -> FnResult> { + /// +} + +#[plugin_fn] +pub fn sink_handle(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestHandler + +#[plugin_fn] +pub fn handle_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmJob + +#[plugin_fn] +pub fn job_run(Json(_context): Json) -> FnResult> { + /// +} + +*/ diff --git a/server/templates/languages/rust/otoroshi_wasm_access_control/src b/server/templates/languages/rust/otoroshi_wasm_access_control/src new file mode 100755 index 0000000..1b6afd8 --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_access_control/src @@ -0,0 +1,35 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute( + Json(context): Json, +) -> FnResult> { + let out = types::WasmAccessValidatorResponse { + result: false, + error: Some(types::WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + + match context.request.headers.get("foo") { + Some(foo) => { + if foo == "bar" { + Ok(Json(types::WasmAccessValidatorResponse { + result: true, + error: None, + })) + } else { + Ok(Json(types::WasmAccessValidatorResponse { + result: false, + error: Some(types::WasmAccessValidatorError { + message: format!("{} is not authorized", foo).to_owned(), + status: 401, + }), + })) + } + } + None => Ok(Json(out)), + } +} diff --git a/server/templates/languages/rust/otoroshi_wasm_backend/Cargo.toml b/server/templates/languages/rust/otoroshi_wasm_backend/Cargo.toml new file mode 100755 index 0000000..6d0f75d --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_backend/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "@@PLUGIN_NAME@@" +version = "@@PLUGIN_VERSION@@" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata] +wasi = false + +[dependencies] +extism-pdk = "1.0.1" +serde = "1.0.152" +serde_json = "1.0.91" +otoroshi_rust_types = "1.0.0" + +[lib] +crate_type = ["cdylib"] +path = "src/lib.rs" diff --git a/server/templates/languages/rust/otoroshi_wasm_backend/lib.rs b/server/templates/languages/rust/otoroshi_wasm_backend/lib.rs new file mode 100755 index 0000000..77574af --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_backend/lib.rs @@ -0,0 +1,105 @@ +use extism_pdk::*; +use otoroshi_rust_types::types::*; + +#[plugin_fn] +pub fn execute( + Json(_context): Json, +) -> FnResult> { + let out = WasmAccessValidatorResponse { + result: false, + error: Some(WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + Ok(Json(out)) +} + +/* + +// WasmRouteMatcher + +#[plugin_fn] +pub fn matches_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmPreRoute + +#[plugin_fn] +pub fn pre_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmAccessValidator + +#[plugin_fn] +pub fn can_access(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestTransformer + + +#[plugin_fn] +pub fn transform_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmBackend + +#[plugin_fn] +pub fn call_backend(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmResponseTransformer + +#[plugin_fn] +pub fn transform_response(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmSink + +#[plugin_fn] +pub fn sink_matches(Json(_context): Json) -> FnResult> { + /// +} + +#[plugin_fn] +pub fn sink_handle(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestHandler + +#[plugin_fn] +pub fn handle_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmJob + +#[plugin_fn] +pub fn job_run(Json(_context): Json) -> FnResult> { + /// +} + +*/ diff --git a/server/templates/languages/rust/otoroshi_wasm_backend/src b/server/templates/languages/rust/otoroshi_wasm_backend/src new file mode 100755 index 0000000..a407e43 --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_backend/src @@ -0,0 +1,41 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; +use std::collections::HashMap; + +#[plugin_fn] +pub fn execute(Json(context): Json) -> FnResult> { + let mut headers = HashMap::new(); + headers.insert("foo".to_string(), "bar".to_string()); + + let response = types::WasmBackendResponse { + headers: Some(headers.into_iter().chain(context.raw_request.headers).collect()), + body_str: Some(r#" + + + + + + + +

This HTML comes from the Wasmo plugin

+ + + + "#.to_owned()), + body_base64: None, + body_bytes: None, + body_json: None, + status: 200 + }; + + Ok(Json(response)) +} \ No newline at end of file diff --git a/server/templates/languages/rust/otoroshi_wasm_pre_route/Cargo.toml b/server/templates/languages/rust/otoroshi_wasm_pre_route/Cargo.toml new file mode 100755 index 0000000..6d0f75d --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_pre_route/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "@@PLUGIN_NAME@@" +version = "@@PLUGIN_VERSION@@" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata] +wasi = false + +[dependencies] +extism-pdk = "1.0.1" +serde = "1.0.152" +serde_json = "1.0.91" +otoroshi_rust_types = "1.0.0" + +[lib] +crate_type = ["cdylib"] +path = "src/lib.rs" diff --git a/server/templates/languages/rust/otoroshi_wasm_pre_route/lib.rs b/server/templates/languages/rust/otoroshi_wasm_pre_route/lib.rs new file mode 100755 index 0000000..77574af --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_pre_route/lib.rs @@ -0,0 +1,105 @@ +use extism_pdk::*; +use otoroshi_rust_types::types::*; + +#[plugin_fn] +pub fn execute( + Json(_context): Json, +) -> FnResult> { + let out = WasmAccessValidatorResponse { + result: false, + error: Some(WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + Ok(Json(out)) +} + +/* + +// WasmRouteMatcher + +#[plugin_fn] +pub fn matches_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmPreRoute + +#[plugin_fn] +pub fn pre_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmAccessValidator + +#[plugin_fn] +pub fn can_access(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestTransformer + + +#[plugin_fn] +pub fn transform_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmBackend + +#[plugin_fn] +pub fn call_backend(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmResponseTransformer + +#[plugin_fn] +pub fn transform_response(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmSink + +#[plugin_fn] +pub fn sink_matches(Json(_context): Json) -> FnResult> { + /// +} + +#[plugin_fn] +pub fn sink_handle(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestHandler + +#[plugin_fn] +pub fn handle_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmJob + +#[plugin_fn] +pub fn job_run(Json(_context): Json) -> FnResult> { + /// +} + +*/ diff --git a/server/templates/languages/rust/otoroshi_wasm_request_transformer/Cargo.toml b/server/templates/languages/rust/otoroshi_wasm_request_transformer/Cargo.toml new file mode 100755 index 0000000..6d0f75d --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_request_transformer/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "@@PLUGIN_NAME@@" +version = "@@PLUGIN_VERSION@@" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata] +wasi = false + +[dependencies] +extism-pdk = "1.0.1" +serde = "1.0.152" +serde_json = "1.0.91" +otoroshi_rust_types = "1.0.0" + +[lib] +crate_type = ["cdylib"] +path = "src/lib.rs" diff --git a/server/templates/languages/rust/otoroshi_wasm_request_transformer/lib.rs b/server/templates/languages/rust/otoroshi_wasm_request_transformer/lib.rs new file mode 100755 index 0000000..77574af --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_request_transformer/lib.rs @@ -0,0 +1,105 @@ +use extism_pdk::*; +use otoroshi_rust_types::types::*; + +#[plugin_fn] +pub fn execute( + Json(_context): Json, +) -> FnResult> { + let out = WasmAccessValidatorResponse { + result: false, + error: Some(WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + Ok(Json(out)) +} + +/* + +// WasmRouteMatcher + +#[plugin_fn] +pub fn matches_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmPreRoute + +#[plugin_fn] +pub fn pre_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmAccessValidator + +#[plugin_fn] +pub fn can_access(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestTransformer + + +#[plugin_fn] +pub fn transform_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmBackend + +#[plugin_fn] +pub fn call_backend(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmResponseTransformer + +#[plugin_fn] +pub fn transform_response(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmSink + +#[plugin_fn] +pub fn sink_matches(Json(_context): Json) -> FnResult> { + /// +} + +#[plugin_fn] +pub fn sink_handle(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestHandler + +#[plugin_fn] +pub fn handle_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmJob + +#[plugin_fn] +pub fn job_run(Json(_context): Json) -> FnResult> { + /// +} + +*/ diff --git a/server/templates/languages/rust/otoroshi_wasm_request_transformer/src b/server/templates/languages/rust/otoroshi_wasm_request_transformer/src new file mode 100755 index 0000000..1b4e967 --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_request_transformer/src @@ -0,0 +1,27 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute( + Json(context): Json, +) -> FnResult> { + let mut out_headers = context.request.headers; + out_headers.insert( + "OTOROSHI_WASM_PLUGIN_ID".to_string(), + "OTOROSHI_WASM_REQUEST_TRANSFORMER".to_string(), + ); + out_headers.insert("Content-Type".to_string(), "text/plain".to_string()); + + let out = types::WasmTransformerResponse { + url: None, + method: Some("POST".to_string()), + body_str: Some("Text plain content".to_string()), + headers: out_headers, + cookies: serde_json::Value::Null, + body_base64: None, + body_bytes: None, + body_json: None, + }; + + Ok(Json(out)) +} diff --git a/server/templates/languages/rust/otoroshi_wasm_response_transformer/Cargo.toml b/server/templates/languages/rust/otoroshi_wasm_response_transformer/Cargo.toml new file mode 100755 index 0000000..6d0f75d --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_response_transformer/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "@@PLUGIN_NAME@@" +version = "@@PLUGIN_VERSION@@" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata] +wasi = false + +[dependencies] +extism-pdk = "1.0.1" +serde = "1.0.152" +serde_json = "1.0.91" +otoroshi_rust_types = "1.0.0" + +[lib] +crate_type = ["cdylib"] +path = "src/lib.rs" diff --git a/server/templates/languages/rust/otoroshi_wasm_response_transformer/lib.rs b/server/templates/languages/rust/otoroshi_wasm_response_transformer/lib.rs new file mode 100755 index 0000000..77574af --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_response_transformer/lib.rs @@ -0,0 +1,105 @@ +use extism_pdk::*; +use otoroshi_rust_types::types::*; + +#[plugin_fn] +pub fn execute( + Json(_context): Json, +) -> FnResult> { + let out = WasmAccessValidatorResponse { + result: false, + error: Some(WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + Ok(Json(out)) +} + +/* + +// WasmRouteMatcher + +#[plugin_fn] +pub fn matches_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmPreRoute + +#[plugin_fn] +pub fn pre_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmAccessValidator + +#[plugin_fn] +pub fn can_access(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestTransformer + + +#[plugin_fn] +pub fn transform_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmBackend + +#[plugin_fn] +pub fn call_backend(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmResponseTransformer + +#[plugin_fn] +pub fn transform_response(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmSink + +#[plugin_fn] +pub fn sink_matches(Json(_context): Json) -> FnResult> { + /// +} + +#[plugin_fn] +pub fn sink_handle(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestHandler + +#[plugin_fn] +pub fn handle_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmJob + +#[plugin_fn] +pub fn job_run(Json(_context): Json) -> FnResult> { + /// +} + +*/ diff --git a/server/templates/languages/rust/otoroshi_wasm_response_transformer/src b/server/templates/languages/rust/otoroshi_wasm_response_transformer/src new file mode 100755 index 0000000..94e94a3 --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_response_transformer/src @@ -0,0 +1,27 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute( + Json(context): Json, +) -> FnResult> { + let mut out_headers = context.request.headers; + out_headers.insert( + "OTOROSHI_WASM_PLUGIN_ID".to_string(), + "OTOROSHI_WASM_RESPONSE_TRANSFORMER".to_string(), + ); + out_headers.insert("Content-Type".to_string(), "text/plain".to_string()); + + let out = types::WasmResponse { + status: Some(200), + error: None, + body_str: Some("{ \"foo\": \"bar\" }".to_string()), + headers: out_headers, + cookies: serde_json::Value::Null, + body_base64: None, + body_bytes: None, + body_json: None, + }; + + Ok(Json(out)) +} diff --git a/server/templates/languages/rust/otoroshi_wasm_route_matcher/Cargo.toml b/server/templates/languages/rust/otoroshi_wasm_route_matcher/Cargo.toml new file mode 100755 index 0000000..6d0f75d --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_route_matcher/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "@@PLUGIN_NAME@@" +version = "@@PLUGIN_VERSION@@" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata] +wasi = false + +[dependencies] +extism-pdk = "1.0.1" +serde = "1.0.152" +serde_json = "1.0.91" +otoroshi_rust_types = "1.0.0" + +[lib] +crate_type = ["cdylib"] +path = "src/lib.rs" diff --git a/server/templates/languages/rust/otoroshi_wasm_route_matcher/lib.rs b/server/templates/languages/rust/otoroshi_wasm_route_matcher/lib.rs new file mode 100755 index 0000000..77574af --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_route_matcher/lib.rs @@ -0,0 +1,105 @@ +use extism_pdk::*; +use otoroshi_rust_types::types::*; + +#[plugin_fn] +pub fn execute( + Json(_context): Json, +) -> FnResult> { + let out = WasmAccessValidatorResponse { + result: false, + error: Some(WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + Ok(Json(out)) +} + +/* + +// WasmRouteMatcher + +#[plugin_fn] +pub fn matches_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmPreRoute + +#[plugin_fn] +pub fn pre_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmAccessValidator + +#[plugin_fn] +pub fn can_access(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestTransformer + + +#[plugin_fn] +pub fn transform_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmBackend + +#[plugin_fn] +pub fn call_backend(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmResponseTransformer + +#[plugin_fn] +pub fn transform_response(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmSink + +#[plugin_fn] +pub fn sink_matches(Json(_context): Json) -> FnResult> { + /// +} + +#[plugin_fn] +pub fn sink_handle(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestHandler + +#[plugin_fn] +pub fn handle_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmJob + +#[plugin_fn] +pub fn job_run(Json(_context): Json) -> FnResult> { + /// +} + +*/ diff --git a/server/templates/languages/rust/otoroshi_wasm_route_matcher/src b/server/templates/languages/rust/otoroshi_wasm_route_matcher/src new file mode 100755 index 0000000..c6b8c55 --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_route_matcher/src @@ -0,0 +1,10 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute(Json(context): Json) -> +FnResult> { + Ok(Json(WasmMatchRouteResponse { + result: context.request.headers.foo === "bar" + })) +} \ No newline at end of file diff --git a/server/templates/languages/rust/otoroshi_wasm_sink/Cargo.toml b/server/templates/languages/rust/otoroshi_wasm_sink/Cargo.toml new file mode 100755 index 0000000..6d0f75d --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_sink/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "@@PLUGIN_NAME@@" +version = "@@PLUGIN_VERSION@@" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata] +wasi = false + +[dependencies] +extism-pdk = "1.0.1" +serde = "1.0.152" +serde_json = "1.0.91" +otoroshi_rust_types = "1.0.0" + +[lib] +crate_type = ["cdylib"] +path = "src/lib.rs" diff --git a/server/templates/languages/rust/otoroshi_wasm_sink/lib.rs b/server/templates/languages/rust/otoroshi_wasm_sink/lib.rs new file mode 100755 index 0000000..77574af --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_sink/lib.rs @@ -0,0 +1,105 @@ +use extism_pdk::*; +use otoroshi_rust_types::types::*; + +#[plugin_fn] +pub fn execute( + Json(_context): Json, +) -> FnResult> { + let out = WasmAccessValidatorResponse { + result: false, + error: Some(WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + Ok(Json(out)) +} + +/* + +// WasmRouteMatcher + +#[plugin_fn] +pub fn matches_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmPreRoute + +#[plugin_fn] +pub fn pre_route(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmAccessValidator + +#[plugin_fn] +pub fn can_access(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestTransformer + + +#[plugin_fn] +pub fn transform_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmBackend + +#[plugin_fn] +pub fn call_backend(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmResponseTransformer + +#[plugin_fn] +pub fn transform_response(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmSink + +#[plugin_fn] +pub fn sink_matches(Json(_context): Json) -> FnResult> { + /// +} + +#[plugin_fn] +pub fn sink_handle(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmRequestHandler + +#[plugin_fn] +pub fn handle_request(Json(_context): Json) -> FnResult> { + /// +} + +// ------------------------- + +// WasmJob + +#[plugin_fn] +pub fn job_run(Json(_context): Json) -> FnResult> { + /// +} + +*/ diff --git a/server/templates/languages/rust/otoroshi_wasm_sink/src b/server/templates/languages/rust/otoroshi_wasm_sink/src new file mode 100755 index 0000000..6e9b358 --- /dev/null +++ b/server/templates/languages/rust/otoroshi_wasm_sink/src @@ -0,0 +1,28 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn sink_matches( + Json(context): Json, +) -> FnResult> { + Ok(Json(types::WasmSinkMatchesResponse { result: true })) +} + +#[plugin_fn] +pub fn sink_handle( + Json(context): Json, +) -> FnResult> { + let path: String = context.request.path; + + Ok(Json(types::WasmSinkHandleResponse { + status: 404, + body_str: Some(format!( + r#"{{ "WASM_SINK_RESPONSE": "Unknown path and domain for {}" }}"#, + path + )), + headers: context.request.headers, + body_base64: None, + body_bytes: None, + body_json: None, + })) +} diff --git a/server/templates/languages/ts/otoroshi_wasm_access_control/esbuild.js b/server/templates/languages/ts/otoroshi_wasm_access_control/esbuild.js new file mode 100755 index 0000000..1e13e53 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_access_control/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.ts'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/ts/otoroshi_wasm_access_control/index.ts b/server/templates/languages/ts/otoroshi_wasm_access_control/index.ts new file mode 100755 index 0000000..887e1cf --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_access_control/index.ts @@ -0,0 +1,25 @@ +import { WasmAccessValidatorContext, WasmAccessValidatorResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + let context = JSON.parse(Host.inputString()) as WasmAccessValidatorContext; + + if (context.request.headers["foo"] === "bar") { + const out: WasmAccessValidatorResponse = { + result: true + }; + Host.outputString(JSON.stringify(out)); + } else { + const error: WasmAccessValidatorResponse = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + }; + Host.outputString(JSON.stringify(error)); + } + + return 0; +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_access_control/package.json b/server/templates/languages/ts/otoroshi_wasm_access_control/package.json new file mode 100755 index 0000000..9fd1c92 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_access_control/package.json @@ -0,0 +1,8 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9", + "otoroshi-ts-types": "1.0.2" + } +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_access_control/plugin.d.ts b/server/templates/languages/ts/otoroshi_wasm_access_control/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_access_control/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_backend/esbuild.js b/server/templates/languages/ts/otoroshi_wasm_backend/esbuild.js new file mode 100755 index 0000000..1e13e53 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_backend/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.ts'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/ts/otoroshi_wasm_backend/index.ts b/server/templates/languages/ts/otoroshi_wasm_backend/index.ts new file mode 100755 index 0000000..71bcdd7 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_backend/index.ts @@ -0,0 +1,43 @@ +import { WasmQueryContext, WasmQueryResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + const context = JSON.parse(Host.inputString()) as WasmQueryContext; + + const headers = { + "foo": "bar", + ...(context.request.headers || {}) + } + + const response: WasmQueryResponse = { + headers, + status: 200, + body: ` + + + + + + + +

This HTML comes from the Wasmo plugin

+ + + + `, + }; + Host.outputString(JSON.stringify(response)); + + return 0; +} + diff --git a/server/templates/languages/ts/otoroshi_wasm_backend/package.json b/server/templates/languages/ts/otoroshi_wasm_backend/package.json new file mode 100755 index 0000000..9fd1c92 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_backend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9", + "otoroshi-ts-types": "1.0.2" + } +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_backend/plugin.d.ts b/server/templates/languages/ts/otoroshi_wasm_backend/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_backend/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_pre_route/esbuild.js b/server/templates/languages/ts/otoroshi_wasm_pre_route/esbuild.js new file mode 100755 index 0000000..1e13e53 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_pre_route/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.ts'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/ts/otoroshi_wasm_pre_route/index.ts b/server/templates/languages/ts/otoroshi_wasm_pre_route/index.ts new file mode 100755 index 0000000..887e1cf --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_pre_route/index.ts @@ -0,0 +1,25 @@ +import { WasmAccessValidatorContext, WasmAccessValidatorResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + let context = JSON.parse(Host.inputString()) as WasmAccessValidatorContext; + + if (context.request.headers["foo"] === "bar") { + const out: WasmAccessValidatorResponse = { + result: true + }; + Host.outputString(JSON.stringify(out)); + } else { + const error: WasmAccessValidatorResponse = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + }; + Host.outputString(JSON.stringify(error)); + } + + return 0; +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_pre_route/package.json b/server/templates/languages/ts/otoroshi_wasm_pre_route/package.json new file mode 100755 index 0000000..9fd1c92 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_pre_route/package.json @@ -0,0 +1,8 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9", + "otoroshi-ts-types": "1.0.2" + } +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_pre_route/plugin.d.ts b/server/templates/languages/ts/otoroshi_wasm_pre_route/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_pre_route/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_request_transformer/esbuild.js b/server/templates/languages/ts/otoroshi_wasm_request_transformer/esbuild.js new file mode 100755 index 0000000..1e13e53 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_request_transformer/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.ts'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/ts/otoroshi_wasm_request_transformer/index.ts b/server/templates/languages/ts/otoroshi_wasm_request_transformer/index.ts new file mode 100755 index 0000000..579afd7 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_request_transformer/index.ts @@ -0,0 +1,23 @@ +import { WasmRequestTransformerContext, WasmTransformerResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + let context = JSON.parse(Host.inputString()) as WasmRequestTransformerContext; + + const error: WasmTransformerResponse = { + ...context, + method: "POST", + headers: { + ...context.otoroshi_request.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_REQUEST_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + } + } + Host.outputString(JSON.stringify(error)); + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_request_transformer/package.json b/server/templates/languages/ts/otoroshi_wasm_request_transformer/package.json new file mode 100755 index 0000000..9fd1c92 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_request_transformer/package.json @@ -0,0 +1,8 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9", + "otoroshi-ts-types": "1.0.2" + } +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_request_transformer/plugin.d.ts b/server/templates/languages/ts/otoroshi_wasm_request_transformer/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_request_transformer/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_response_transformer/esbuild.js b/server/templates/languages/ts/otoroshi_wasm_response_transformer/esbuild.js new file mode 100755 index 0000000..1e13e53 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_response_transformer/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.ts'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/ts/otoroshi_wasm_response_transformer/index.ts b/server/templates/languages/ts/otoroshi_wasm_response_transformer/index.ts new file mode 100755 index 0000000..e924d80 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_response_transformer/index.ts @@ -0,0 +1,23 @@ +import { WasmResponseTransformerContext, WasmTransformerResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + let context = JSON.parse(Host.inputString()) as WasmResponseTransformerContext; + + const error: WasmTransformerResponse = { + ...context, + status: 200, + headers: { + ...context.otoroshi_request.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_RESPONSE_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + } + } + Host.outputString(JSON.stringify(error)); + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_response_transformer/package.json b/server/templates/languages/ts/otoroshi_wasm_response_transformer/package.json new file mode 100755 index 0000000..9fd1c92 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_response_transformer/package.json @@ -0,0 +1,8 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9", + "otoroshi-ts-types": "1.0.2" + } +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_response_transformer/plugin.d.ts b/server/templates/languages/ts/otoroshi_wasm_response_transformer/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_response_transformer/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_route_matcher/esbuild.js b/server/templates/languages/ts/otoroshi_wasm_route_matcher/esbuild.js new file mode 100755 index 0000000..1e13e53 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_route_matcher/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.ts'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/ts/otoroshi_wasm_route_matcher/index.ts b/server/templates/languages/ts/otoroshi_wasm_route_matcher/index.ts new file mode 100755 index 0000000..dcf6d22 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_route_matcher/index.ts @@ -0,0 +1,16 @@ +import { WasmMatchRouteContext, WasmMatchRouteResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + const context = JSON.parse(Host.inputString()) as WasmMatchRouteContext; + + const out: WasmMatchRouteResponse = { + result: context.request.headers.foo === "bar" + } + + Host.outputString(JSON.stringify(out)); + + return 0; +} + diff --git a/server/templates/languages/ts/otoroshi_wasm_route_matcher/package.json b/server/templates/languages/ts/otoroshi_wasm_route_matcher/package.json new file mode 100755 index 0000000..9fd1c92 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_route_matcher/package.json @@ -0,0 +1,8 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9", + "otoroshi-ts-types": "1.0.2" + } +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_route_matcher/plugin.d.ts b/server/templates/languages/ts/otoroshi_wasm_route_matcher/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_route_matcher/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_sink/esbuild.js b/server/templates/languages/ts/otoroshi_wasm_sink/esbuild.js new file mode 100755 index 0000000..1e13e53 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_sink/esbuild.js @@ -0,0 +1,12 @@ +const esbuild = require('esbuild') + +esbuild + .build({ + entryPoints: ['index.ts'], + outdir: 'dist', + bundle: true, + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'] // don't go over es2020 because quickjs doesn't support it + }) diff --git a/server/templates/languages/ts/otoroshi_wasm_sink/index.ts b/server/templates/languages/ts/otoroshi_wasm_sink/index.ts new file mode 100755 index 0000000..252f510 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_sink/index.ts @@ -0,0 +1,33 @@ +import { WasmSinkContext, WasmSinkMatchesResponse, WasmSinkHandleResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function sink_matches() { + // const context = JSON.parse(Host.inputString()) as WasmSinkContext; + + const out: WasmSinkMatchesResponse = { + result: true + } + + Host.outputString(JSON.stringify(out)); + + return 0; +} + +export function sink_handle() { + const context = JSON.parse(Host.inputString()) as WasmSinkContext; + + const out: WasmSinkHandleResponse = { + status: 200, + headers: { + 'Content-Type': 'application/json' + }, + body_json: { + "WASM_SINK_RESPONSE": `Unknown path and domain for ${context.request.path}` + } + } + + Host.outputString(JSON.stringify(out)) + + return 0 +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_sink/package.json b/server/templates/languages/ts/otoroshi_wasm_sink/package.json new file mode 100755 index 0000000..9fd1c92 --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_sink/package.json @@ -0,0 +1,8 @@ +{ + "name": "@@PLUGIN_NAME@@", + "version": "@@PLUGIN_VERSION@@", + "devDependencies": { + "esbuild": "^0.17.9", + "otoroshi-ts-types": "1.0.2" + } +} \ No newline at end of file diff --git a/server/templates/languages/ts/otoroshi_wasm_sink/plugin.d.ts b/server/templates/languages/ts/otoroshi_wasm_sink/plugin.d.ts new file mode 100755 index 0000000..45524cc --- /dev/null +++ b/server/templates/languages/ts/otoroshi_wasm_sink/plugin.d.ts @@ -0,0 +1,9 @@ +/* + We must also describe the Wasm interface for our plug-in. + We do this with a typescript module DTS file + + DO NOT DELETE THIS FILE +*/ +declare module 'main' { + export function execute(): I32; +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/index.js b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/index.js new file mode 100755 index 0000000..8c72957 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/index.js @@ -0,0 +1,21 @@ +export function execute() { + let context = JSON.parse(Host.inputString()) + + if (context.request.headers["foo"] === "bar") { + const out = { + result: true + } + Host.outputString(JSON.stringify(out)) + } else { + const error = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + } + Host.outputString(JSON.stringify(error)) + } + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/index.ts b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/index.ts new file mode 100755 index 0000000..887e1cf --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/index.ts @@ -0,0 +1,25 @@ +import { WasmAccessValidatorContext, WasmAccessValidatorResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + let context = JSON.parse(Host.inputString()) as WasmAccessValidatorContext; + + if (context.request.headers["foo"] === "bar") { + const out: WasmAccessValidatorResponse = { + result: true + }; + Host.outputString(JSON.stringify(out)); + } else { + const error: WasmAccessValidatorResponse = { + result: false, + error: { + message: "you're not authorized", + status: 401 + } + }; + Host.outputString(JSON.stringify(error)); + } + + return 0; +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/lib.rs b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/lib.rs new file mode 100755 index 0000000..1b6afd8 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/lib.rs @@ -0,0 +1,35 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute( + Json(context): Json, +) -> FnResult> { + let out = types::WasmAccessValidatorResponse { + result: false, + error: Some(types::WasmAccessValidatorError { + message: "you're not authorized".to_owned(), + status: 401, + }), + }; + + match context.request.headers.get("foo") { + Some(foo) => { + if foo == "bar" { + Ok(Json(types::WasmAccessValidatorResponse { + result: true, + error: None, + })) + } else { + Ok(Json(types::WasmAccessValidatorResponse { + result: false, + error: Some(types::WasmAccessValidatorError { + message: format!("{} is not authorized", foo).to_owned(), + status: 401, + }), + })) + } + } + None => Ok(Json(out)), + } +} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/main.go b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/main.go new file mode 100755 index 0000000..6db7fa6 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var foo, err = jsonparser.GetString(input, "request", "headers", "foo") + + if err != nil { + } + + var output = "" + + if foo == "bar" { + output = `{ + "result": true + }` + } else { + output = `{ + "result": false, + "error": { + "message": "you're not authorized", + "status": 401 + } + }` + } + + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/policies.rego b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/policies.rego new file mode 100755 index 0000000..7907d94 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ACCESS_CONTROL/policies.rego @@ -0,0 +1,7 @@ +package example + +default can_access = false + +can_access { + input.request.headers.foo == "bar" +} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/index.js b/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/index.js new file mode 100755 index 0000000..90409d3 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/index.js @@ -0,0 +1,39 @@ +export function execute() { + const str = Host.inputString() + const context = JSON.parse(str) + + let headers = { ...context.request.headers } + headers["foo"] = "bar" + + const response = { + headers, + 'Content-Type': "text/html", + body: ` + + + + + + + +

This HTML comes from the Wasmo plugin

+ + + + `, + status: 200 + } + + Host.outputString(JSON.stringify(response)) + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/index.ts b/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/index.ts new file mode 100755 index 0000000..71bcdd7 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/index.ts @@ -0,0 +1,43 @@ +import { WasmQueryContext, WasmQueryResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + const context = JSON.parse(Host.inputString()) as WasmQueryContext; + + const headers = { + "foo": "bar", + ...(context.request.headers || {}) + } + + const response: WasmQueryResponse = { + headers, + status: 200, + body: ` + + + + + + + +

This HTML comes from the Wasmo plugin

+ + + + `, + }; + Host.outputString(JSON.stringify(response)); + + return 0; +} + diff --git a/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/lib.rs b/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/lib.rs new file mode 100755 index 0000000..a407e43 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/lib.rs @@ -0,0 +1,41 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; +use std::collections::HashMap; + +#[plugin_fn] +pub fn execute(Json(context): Json) -> FnResult> { + let mut headers = HashMap::new(); + headers.insert("foo".to_string(), "bar".to_string()); + + let response = types::WasmBackendResponse { + headers: Some(headers.into_iter().chain(context.raw_request.headers).collect()), + body_str: Some(r#" + + + + + + + +

This HTML comes from the Wasmo plugin

+ + + + "#.to_owned()), + body_base64: None, + body_bytes: None, + body_json: None, + status: 200 + }; + + Ok(Json(response)) +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/main.go b/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/main.go new file mode 100755 index 0000000..41e73c3 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_BACKEND/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "github.com/extism/go-pdk" + "github.com/buger/jsonparser" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var headers, dataType, offset, err = jsonparser.Get(input, "request", "headers") + + _ = dataType + _ = offset + _ = headers + + if err != nil {} + + output := `{ "headers": { "Content-Type": "text/html" }, "body": "

This HTML comes from the Wasmo plugin

", "status": 200 }` + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/index.js b/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/index.js new file mode 100755 index 0000000..429f8d2 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/index.js @@ -0,0 +1,20 @@ +export function execute() { + let context = JSON.parse(Host.inputString()) + + if (context.request.headers["bar"] === "foo") { + Host.outputString(JSON.stringify({ + error: false + })) + } else { + Host.outputString(JSON.stringify({ + error: true, + headers: { + 'Content-Type': 'text/plain' + }, + status: 401, + body: "you're not authorized" + })) + } + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/index.ts b/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/index.ts new file mode 100755 index 0000000..655c625 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/index.ts @@ -0,0 +1,26 @@ +import { WasmPreRouteContext, WasmPreRouteResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + let context = JSON.parse(Host.inputString()) as WasmPreRouteContext; + + if (context.request.headers["bar"] === "foo") { + const out: WasmPreRouteResponse = { + error: false + } + Host.outputString(JSON.stringify(out)); + } else { + const error: WasmPreRouteResponse = { + error: true, + status: 401, + headers: { + 'Content-Type': 'text/plain' + }, + body: "you're not authorized" + } + Host.outputString(JSON.stringify(error)); + } + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/lib.rs b/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/lib.rs new file mode 100755 index 0000000..f63fe46 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/lib.rs @@ -0,0 +1,28 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute(Json(context): Json) -> FnResult> { + let out = types::WasmPreRouteResponse { + error: Some(true), + body: "you're not authorized", + status: 401 + }; + + match context.request.headers.get("bar") { + Some(bar) => { + if bar == "foo" { + Ok(Json(types::WasmPreRouteResponse { + error: Some(false) + })) + } else { + Ok(Json(types::WasmPreRouteResponse { + error: Some(true), + body: format!("{} is not authorized", bar).to_owned(), + status: 401 + })) + } + } + None => Ok(Json(out)), + } +} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/main.go b/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/main.go new file mode 100755 index 0000000..4621dde --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_PRE_ROUTE/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var bar, err = jsonparser.GetString(input, "request", "headers", "bar") + + if err != nil { + } + + var output = "" + + if bar == "foo" { + output = `{ + "error": false + }` + } else { + output = `{ + "error": true, + "headers": { + "Content-Type": "text/plain" + }, + "status": 401, + "body": "you're not authorized" + }` + } + + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/index.js b/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/index.js new file mode 100755 index 0000000..03485bd --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/index.js @@ -0,0 +1,18 @@ +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + ...context, + method: "POST", + headers: { + ...context.otoroshi_request.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_REQUEST_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + } + })) + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/index.ts b/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/index.ts new file mode 100755 index 0000000..579afd7 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/index.ts @@ -0,0 +1,23 @@ +import { WasmRequestTransformerContext, WasmTransformerResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + let context = JSON.parse(Host.inputString()) as WasmRequestTransformerContext; + + const error: WasmTransformerResponse = { + ...context, + method: "POST", + headers: { + ...context.otoroshi_request.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_REQUEST_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + } + } + Host.outputString(JSON.stringify(error)); + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/lib.rs b/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/lib.rs new file mode 100755 index 0000000..1b4e967 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/lib.rs @@ -0,0 +1,27 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute( + Json(context): Json, +) -> FnResult> { + let mut out_headers = context.request.headers; + out_headers.insert( + "OTOROSHI_WASM_PLUGIN_ID".to_string(), + "OTOROSHI_WASM_REQUEST_TRANSFORMER".to_string(), + ); + out_headers.insert("Content-Type".to_string(), "text/plain".to_string()); + + let out = types::WasmTransformerResponse { + url: None, + method: Some("POST".to_string()), + body_str: Some("Text plain content".to_string()), + headers: out_headers, + cookies: serde_json::Value::Null, + body_base64: None, + body_bytes: None, + body_json: None, + }; + + Ok(Json(out)) +} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/main.go b/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/main.go new file mode 100755 index 0000000..5eb4001 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_REQUEST_TRANSFORMER/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "encoding/json" + + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var headers, dataType, offset, err = jsonparser.Get(input, "request", "headers") + + _ = dataType + _ = offset + + var outHeaders map[string]interface{} + + // Unmarshal the JSON data into the map + err = json.Unmarshal(headers, &outHeaders) + if err != nil { + + } + + outHeaders["Content-Type"] = "application/json" + outHeaders["OTOROSHI_WASM_PLUGIN_ID"] = "OTOROSHI_WASM_REQUEST_TRANSFORMER" + + if err != nil { + } + + jsonHeaders, marshallingError := json.Marshal(outHeaders) + if marshallingError != nil { + + } + + output := `{ + "method": "POST", + "headers": ` + string(jsonHeaders) + `, + "body_json": { "foo": "bar" } + }` + + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/index.js b/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/index.js new file mode 100755 index 0000000..91fe07b --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/index.js @@ -0,0 +1,19 @@ +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + ...context, + status: 200, + headers: { + ...context.otoroshi_response.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_RESPONSE_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + }, + // cookies + })) + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/index.ts b/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/index.ts new file mode 100755 index 0000000..e924d80 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/index.ts @@ -0,0 +1,23 @@ +import { WasmResponseTransformerContext, WasmTransformerResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + let context = JSON.parse(Host.inputString()) as WasmResponseTransformerContext; + + const error: WasmTransformerResponse = { + ...context, + status: 200, + headers: { + ...context.otoroshi_request.headers, + OTOROSHI_WASM_PLUGIN_ID: "OTOROSHI_WASM_RESPONSE_TRANSFORMER", + "Content-Type": "application/json" + }, + body_json: { + foo: "bar" + } + } + Host.outputString(JSON.stringify(error)); + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/lib.rs b/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/lib.rs new file mode 100755 index 0000000..94e94a3 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/lib.rs @@ -0,0 +1,27 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute( + Json(context): Json, +) -> FnResult> { + let mut out_headers = context.request.headers; + out_headers.insert( + "OTOROSHI_WASM_PLUGIN_ID".to_string(), + "OTOROSHI_WASM_RESPONSE_TRANSFORMER".to_string(), + ); + out_headers.insert("Content-Type".to_string(), "text/plain".to_string()); + + let out = types::WasmResponse { + status: Some(200), + error: None, + body_str: Some("{ \"foo\": \"bar\" }".to_string()), + headers: out_headers, + cookies: serde_json::Value::Null, + body_base64: None, + body_bytes: None, + body_json: None, + }; + + Ok(Json(out)) +} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/main.go b/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/main.go new file mode 100755 index 0000000..58b131b --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_RESPONSE_TRANSFORMER/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "encoding/json" + + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var headers, dataType, offset, err = jsonparser.Get(input, "request", "headers") + + _ = dataType + _ = offset + + var outHeaders map[string]interface{} + + // Unmarshal the JSON data into the map + err = json.Unmarshal(headers, &outHeaders) + if err != nil { + + } + + outHeaders["Content-Type"] = "application/json" + outHeaders["OTOROSHI_WASM_PLUGIN_ID"] = "OTOROSHI_WASM_RESPONSE_TRANSFORMER" + + if err != nil { + } + + jsonHeaders, marshallingError := json.Marshal(outHeaders) + if marshallingError != nil { + + } + + output := `{ + "status": 200, + "headers": ` + string(jsonHeaders) + `, + "body_json": { "foo": "bar" } + }` + + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/index.js b/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/index.js new file mode 100755 index 0000000..52902e3 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/index.js @@ -0,0 +1,15 @@ +/* + The "matcher" is a tool that allows filtering a route during the routing phase. + In practice, you can create two routes that are identical from a frontend perspective + but have different "route matchers." + These matchers will select one route or the other based on a specific criterion. +*/ +export function execute() { + let context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + result: context.request.headers.foo === "bar" + })) + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/index.ts b/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/index.ts new file mode 100755 index 0000000..dcf6d22 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/index.ts @@ -0,0 +1,16 @@ +import { WasmMatchRouteContext, WasmMatchRouteResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function execute() { + const context = JSON.parse(Host.inputString()) as WasmMatchRouteContext; + + const out: WasmMatchRouteResponse = { + result: context.request.headers.foo === "bar" + } + + Host.outputString(JSON.stringify(out)); + + return 0; +} + diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/lib.rs b/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/lib.rs new file mode 100755 index 0000000..c6b8c55 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/lib.rs @@ -0,0 +1,10 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn execute(Json(context): Json) -> +FnResult> { + Ok(Json(WasmMatchRouteResponse { + result: context.request.headers.foo === "bar" + })) +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/main.go b/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/main.go new file mode 100755 index 0000000..943f38f --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_ROUTE_MATCHER/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" + + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" + // "github.com/MAIF/otoroshi-go-types" +) + +//export execute +func execute() int32 { + input := pdk.Input() + + var foo, err = jsonparser.GetString(input, "request", "headers", "foo") + + if err != nil { + } + + output := `{ "result": ` + strconv.FormatBool(foo == "bar") + `}` + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_SINK/index.js b/server/templates/otoroshi/OTOROSHI_WASM_SINK/index.js new file mode 100755 index 0000000..7e63900 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_SINK/index.js @@ -0,0 +1,25 @@ +export function sink_matches() { + // const context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + result: true + })) + + return 0 +} + +export function sink_handle() { + const context = JSON.parse(Host.inputString()) + + Host.outputString(JSON.stringify({ + status: 200, + headers: { + 'Content-Type': 'application/json' + }, + body_json: { + "WASM_SINK_RESPONSE": `Unknown path and domain for ${context.request.path}` + } + })) + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_SINK/index.ts b/server/templates/otoroshi/OTOROSHI_WASM_SINK/index.ts new file mode 100755 index 0000000..252f510 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_SINK/index.ts @@ -0,0 +1,33 @@ +import { WasmSinkContext, WasmSinkMatchesResponse, WasmSinkHandleResponse } from 'otoroshi-ts-types'; + +export declare var Host: any; + +export function sink_matches() { + // const context = JSON.parse(Host.inputString()) as WasmSinkContext; + + const out: WasmSinkMatchesResponse = { + result: true + } + + Host.outputString(JSON.stringify(out)); + + return 0; +} + +export function sink_handle() { + const context = JSON.parse(Host.inputString()) as WasmSinkContext; + + const out: WasmSinkHandleResponse = { + status: 200, + headers: { + 'Content-Type': 'application/json' + }, + body_json: { + "WASM_SINK_RESPONSE": `Unknown path and domain for ${context.request.path}` + } + } + + Host.outputString(JSON.stringify(out)) + + return 0 +} \ No newline at end of file diff --git a/server/templates/otoroshi/OTOROSHI_WASM_SINK/lib.rs b/server/templates/otoroshi/OTOROSHI_WASM_SINK/lib.rs new file mode 100755 index 0000000..6e9b358 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_SINK/lib.rs @@ -0,0 +1,28 @@ +use extism_pdk::*; +use otoroshi_rust_types::types; + +#[plugin_fn] +pub fn sink_matches( + Json(context): Json, +) -> FnResult> { + Ok(Json(types::WasmSinkMatchesResponse { result: true })) +} + +#[plugin_fn] +pub fn sink_handle( + Json(context): Json, +) -> FnResult> { + let path: String = context.request.path; + + Ok(Json(types::WasmSinkHandleResponse { + status: 404, + body_str: Some(format!( + r#"{{ "WASM_SINK_RESPONSE": "Unknown path and domain for {}" }}"#, + path + )), + headers: context.request.headers, + body_base64: None, + body_bytes: None, + body_json: None, + })) +} diff --git a/server/templates/otoroshi/OTOROSHI_WASM_SINK/main.go b/server/templates/otoroshi/OTOROSHI_WASM_SINK/main.go new file mode 100755 index 0000000..0dcd089 --- /dev/null +++ b/server/templates/otoroshi/OTOROSHI_WASM_SINK/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "github.com/buger/jsonparser" + "github.com/extism/go-pdk" + // "github.com/MAIF/otoroshi-go-types" +) + +//export sink_matches +func sink_matches() int32 { + output := `{ "result": true }` + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +//export sink_handle +func sink_handle() int32 { + input := pdk.Input() + + var path, err = jsonparser.GetString(input, "request", "path") + + if err != nil { + } + + output := `{ + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "body_json": { + "WASM_SINK_RESPONSE": "Unknown path and domain for ` + path + `" + } + }` + mem := pdk.AllocateString(output) + pdk.OutputMemory(mem) + + return 0 +} + +func main() {} diff --git a/server/templates/otoroshi/js.zip b/server/templates/otoroshi/js.zip index d7fb560..e4f0970 100644 Binary files a/server/templates/otoroshi/js.zip and b/server/templates/otoroshi/js.zip differ diff --git a/server/templates/otoroshi/js/esbuild.js b/server/templates/otoroshi/js/esbuild.js index 50edc7c..9186020 100755 --- a/server/templates/otoroshi/js/esbuild.js +++ b/server/templates/otoroshi/js/esbuild.js @@ -1,4 +1,4 @@ -const esbuild = require('esbuild'); +const esbuild = require('esbuild') esbuild .build({ diff --git a/server/templates/otoroshi/opa.zip b/server/templates/otoroshi/opa.zip index 85a3cdb..b392b4a 100644 Binary files a/server/templates/otoroshi/opa.zip and b/server/templates/otoroshi/opa.zip differ diff --git a/server/templates/otoroshi/rust.zip b/server/templates/otoroshi/rust.zip index bb515a3..48bddd1 100644 Binary files a/server/templates/otoroshi/rust.zip and b/server/templates/otoroshi/rust.zip differ diff --git a/server/templates/otoroshi/rust/Cargo.toml b/server/templates/otoroshi/rust/Cargo.toml index bb98343..6d0f75d 100755 --- a/server/templates/otoroshi/rust/Cargo.toml +++ b/server/templates/otoroshi/rust/Cargo.toml @@ -11,7 +11,7 @@ wasi = false extism-pdk = "1.0.1" serde = "1.0.152" serde_json = "1.0.91" -otoroshi_rust_types = "0.0.1" +otoroshi_rust_types = "1.0.0" [lib] crate_type = ["cdylib"] diff --git a/server/templates/otoroshi/ts.zip b/server/templates/otoroshi/ts.zip index 6828de6..f64ad44 100644 Binary files a/server/templates/otoroshi/ts.zip and b/server/templates/otoroshi/ts.zip differ diff --git a/server/templates/otoroshi/ts/esbuild.js b/server/templates/otoroshi/ts/esbuild.js index 0afe91f..1e13e53 100755 --- a/server/templates/otoroshi/ts/esbuild.js +++ b/server/templates/otoroshi/ts/esbuild.js @@ -1,4 +1,4 @@ -const esbuild = require('esbuild'); +const esbuild = require('esbuild') esbuild .build({ diff --git a/server/templates/otoroshi/ts/package.json b/server/templates/otoroshi/ts/package.json index d8e78f8..9fd1c92 100755 --- a/server/templates/otoroshi/ts/package.json +++ b/server/templates/otoroshi/ts/package.json @@ -3,6 +3,6 @@ "version": "@@PLUGIN_VERSION@@", "devDependencies": { "esbuild": "^0.17.9", - "otoroshi-ts-types": "0.0.2" + "otoroshi-ts-types": "1.0.2" } } \ No newline at end of file diff --git a/server/templates/rust.zip b/server/templates/rust.zip index 00f7566..4d4dba3 100644 Binary files a/server/templates/rust.zip and b/server/templates/rust.zip differ diff --git a/server/templates/rust/Cargo.toml b/server/templates/rust/Cargo.toml index c2881c3..6d0f75d 100755 --- a/server/templates/rust/Cargo.toml +++ b/server/templates/rust/Cargo.toml @@ -11,6 +11,7 @@ wasi = false extism-pdk = "1.0.1" serde = "1.0.152" serde_json = "1.0.91" +otoroshi_rust_types = "1.0.0" [lib] crate_type = ["cdylib"] diff --git a/server/templates/ts.zip b/server/templates/ts.zip index 1a14a33..e7c4f30 100644 Binary files a/server/templates/ts.zip and b/server/templates/ts.zip differ diff --git a/server/templates/ts/esbuild.js b/server/templates/ts/esbuild.js index 0afe91f..1e13e53 100755 --- a/server/templates/ts/esbuild.js +++ b/server/templates/ts/esbuild.js @@ -1,4 +1,4 @@ -const esbuild = require('esbuild'); +const esbuild = require('esbuild') esbuild .build({ diff --git a/server/templates/ts/package.json b/server/templates/ts/package.json index d8e78f8..9fd1c92 100755 --- a/server/templates/ts/package.json +++ b/server/templates/ts/package.json @@ -3,6 +3,6 @@ "version": "@@PLUGIN_VERSION@@", "devDependencies": { "esbuild": "^0.17.9", - "otoroshi-ts-types": "0.0.2" + "otoroshi-ts-types": "1.0.2" } } \ No newline at end of file diff --git a/server/templates/update.sh b/server/templates/update.sh index 1cf3807..18bca85 100755 --- a/server/templates/update.sh +++ b/server/templates/update.sh @@ -21,4 +21,136 @@ zip -r go.zip go && \ zip -r ts.zip ts && \ zip -r js.zip js && \ zip -r rust.zip rust && \ -zip -r opa.zip opa \ No newline at end of file +zip -r opa.zip opa + +cd .. +rm -rf languages +mkdir -p languages/js/otoroshi_wasm_access_control +mkdir -p languages/js/otoroshi_wasm_backend +mkdir -p languages/js/otoroshi_wasm_pre_route +mkdir -p languages/js/otoroshi_wasm_request_transformer +mkdir -p languages/js/otoroshi_wasm_response_transformer +mkdir -p languages/js/otoroshi_wasm_route_matcher +mkdir -p languages/js/otoroshi_wasm_sink + +mkdir -p languages/go/otoroshi_wasm_access_control +mkdir -p languages/go/otoroshi_wasm_backend +mkdir -p languages/go/otoroshi_wasm_pre_route +mkdir -p languages/go/otoroshi_wasm_request_transformer +mkdir -p languages/go/otoroshi_wasm_response_transformer +mkdir -p languages/go/otoroshi_wasm_route_matcher +mkdir -p languages/go/otoroshi_wasm_sink + +mkdir -p languages/ts/otoroshi_wasm_access_control +mkdir -p languages/ts/otoroshi_wasm_backend +mkdir -p languages/ts/otoroshi_wasm_pre_route +mkdir -p languages/ts/otoroshi_wasm_request_transformer +mkdir -p languages/ts/otoroshi_wasm_response_transformer +mkdir -p languages/ts/otoroshi_wasm_route_matcher +mkdir -p languages/ts/otoroshi_wasm_sink + +mkdir -p languages/rust/otoroshi_wasm_access_control +mkdir -p languages/rust/otoroshi_wasm_backend +mkdir -p languages/rust/otoroshi_wasm_pre_route +mkdir -p languages/rust/otoroshi_wasm_request_transformer +mkdir -p languages/rust/otoroshi_wasm_response_transformer +mkdir -p languages/rust/otoroshi_wasm_route_matcher +mkdir -p languages/rust/otoroshi_wasm_sink + +cp otoroshi/js/* languages/js/otoroshi_wasm_access_control +cp otoroshi/js/* languages/js/otoroshi_wasm_backend +cp otoroshi/js/* languages/js/otoroshi_wasm_pre_route +cp otoroshi/js/* languages/js/otoroshi_wasm_request_transformer +cp otoroshi/js/* languages/js/otoroshi_wasm_response_transformer +cp otoroshi/js/* languages/js/otoroshi_wasm_route_matcher +cp otoroshi/js/* languages/js/otoroshi_wasm_sink + +cp otoroshi/go/* languages/go/otoroshi_wasm_access_control +cp otoroshi/go/* languages/go/otoroshi_wasm_backend +cp otoroshi/go/* languages/go/otoroshi_wasm_pre_route +cp otoroshi/go/* languages/go/otoroshi_wasm_request_transformer +cp otoroshi/go/* languages/go/otoroshi_wasm_response_transformer +cp otoroshi/go/* languages/go/otoroshi_wasm_route_matcher +cp otoroshi/go/* languages/go/otoroshi_wasm_sink + +cp otoroshi/ts/* languages/ts/otoroshi_wasm_access_control +cp otoroshi/ts/* languages/ts/otoroshi_wasm_backend +cp otoroshi/ts/* languages/ts/otoroshi_wasm_pre_route +cp otoroshi/ts/* languages/ts/otoroshi_wasm_request_transformer +cp otoroshi/ts/* languages/ts/otoroshi_wasm_response_transformer +cp otoroshi/ts/* languages/ts/otoroshi_wasm_route_matcher +cp otoroshi/ts/* languages/ts/otoroshi_wasm_sink + +cp otoroshi/rust/* languages/rust/otoroshi_wasm_access_control +cp otoroshi/rust/* languages/rust/otoroshi_wasm_backend +cp otoroshi/rust/* languages/rust/otoroshi_wasm_pre_route +cp otoroshi/rust/* languages/rust/otoroshi_wasm_request_transformer +cp otoroshi/rust/* languages/rust/otoroshi_wasm_response_transformer +cp otoroshi/rust/* languages/rust/otoroshi_wasm_route_matcher +cp otoroshi/rust/* languages/rust/otoroshi_wasm_sink + +cp otoroshi/otoroshi_wasm_access_control/index.js languages/js/otoroshi_wasm_access_control +cp otoroshi/otoroshi_wasm_backend/index.js languages/js/otoroshi_wasm_backend +cp otoroshi/otoroshi_wasm_pre_route /index.js languages/js/otoroshi_wasm_pre_route +cp otoroshi/otoroshi_wasm_request_transformer/index.js languages/js/otoroshi_wasm_request_transformer +cp otoroshi/otoroshi_wasm_response_transformer/index.js languages/js/otoroshi_wasm_response_transformer +cp otoroshi/otoroshi_wasm_route_matcher/index.js languages/js/otoroshi_wasm_route_matcher +cp otoroshi/otoroshi_wasm_sink/index.js languages/js/otoroshi_wasm_sink + +cp otoroshi/otoroshi_wasm_access_control/index.ts languages/ts/otoroshi_wasm_access_control +cp otoroshi/otoroshi_wasm_backend/index.ts languages/ts/otoroshi_wasm_backend +cp otoroshi/otoroshi_wasm_pre_route /index.ts languages/ts/otoroshi_wasm_pre_route +cp otoroshi/otoroshi_wasm_request_transformer/index.ts languages/ts/otoroshi_wasm_request_transformer +cp otoroshi/otoroshi_wasm_response_transformer/index.ts languages/ts/otoroshi_wasm_response_transformer +cp otoroshi/otoroshi_wasm_route_matcher/index.ts languages/ts/otoroshi_wasm_route_matcher +cp otoroshi/otoroshi_wasm_sink/index.ts languages/ts/otoroshi_wasm_sink + +cp otoroshi/otoroshi_wasm_access_control/lib.rs languages/rust/otoroshi_wasm_access_control/src +cp otoroshi/otoroshi_wasm_backend/lib.rs languages/rust/otoroshi_wasm_backend/src +cp otoroshi/otoroshi_wasm_pre_route /lib.rs languages/rust/otoroshi_wasm_pre_route /src +cp otoroshi/otoroshi_wasm_request_transformer/lib.rs languages/rust/otoroshi_wasm_request_transformer/src +cp otoroshi/otoroshi_wasm_response_transformer/lib.rs languages/rust/otoroshi_wasm_response_transformer/src +cp otoroshi/otoroshi_wasm_route_matcher/lib.rs languages/rust/otoroshi_wasm_route_matcher/src +cp otoroshi/otoroshi_wasm_sink/lib.rs languages/rust/otoroshi_wasm_sink/src + +cp otoroshi/otoroshi_wasm_access_control/main.go languages/go/otoroshi_wasm_access_control +cp otoroshi/otoroshi_wasm_backend/main.go languages/go/otoroshi_wasm_backend +cp otoroshi/otoroshi_wasm_pre_route /main.go languages/go/otoroshi_wasm_pre_route +cp otoroshi/otoroshi_wasm_request_transformer/main.go languages/go/otoroshi_wasm_request_transformer +cp otoroshi/otoroshi_wasm_response_transformer/main.go languages/go/otoroshi_wasm_response_transformer +cp otoroshi/otoroshi_wasm_route_matcher/main.go languages/go/otoroshi_wasm_route_matcher +cp otoroshi/otoroshi_wasm_sink/main.go languages/go/otoroshi_wasm_sink + +# zip -r go.zip go + +zip -rj ../../cli/templates/otoroshi/languages/js/otoroshi_wasm_access_control.zip languages/js/otoroshi_wasm_access_control +zip -rj ../../cli/templates/otoroshi/languages/js/otoroshi_wasm_backend.zip languages/js/otoroshi_wasm_backend +zip -rj ../../cli/templates/otoroshi/languages/js/otoroshi_wasm_pre_route .zip languages/js/otoroshi_wasm_pre_route +zip -rj ../../cli/templates/otoroshi/languages/js/otoroshi_wasm_request_transformer.zip languages/js/otoroshi_wasm_request_transformer +zip -rj ../../cli/templates/otoroshi/languages/js/otoroshi_wasm_response_transformer.zip languages/js/otoroshi_wasm_response_transformer +zip -rj ../../cli/templates/otoroshi/languages/js/otoroshi_wasm_route_matcher.zip languages/js/otoroshi_wasm_route_matcher +zip -rj ../../cli/templates/otoroshi/languages/js/otoroshi_wasm_sink.zip languages/js/otoroshi_wasm_sink + +zip -rj ../../cli/templates/otoroshi/languages/ts/otoroshi_wasm_access_control.zip languages/ts/otoroshi_wasm_access_control +zip -rj ../../cli/templates/otoroshi/languages/ts/otoroshi_wasm_backend.zip languages/ts/otoroshi_wasm_backend +zip -rj ../../cli/templates/otoroshi/languages/ts/otoroshi_wasm_pre_route .zip languages/ts/otoroshi_wasm_pre_route +zip -rj ../../cli/templates/otoroshi/languages/ts/otoroshi_wasm_request_transformer.zip languages/ts/otoroshi_wasm_request_transformer +zip -rj ../../cli/templates/otoroshi/languages/ts/otoroshi_wasm_response_transformer.zip languages/ts/otoroshi_wasm_response_transformer +zip -rj ../../cli/templates/otoroshi/languages/ts/otoroshi_wasm_route_matcher.zip languages/ts/otoroshi_wasm_route_matcher +zip -rj ../../cli/templates/otoroshi/languages/ts/otoroshi_wasm_sink.zip languages/ts/otoroshi_wasm_sink + +zip -rj ../../cli/templates/otoroshi/languages/rust/otoroshi_wasm_access_control.zip languages/rust/otoroshi_wasm_access_control/src +zip -rj ../../cli/templates/otoroshi/languages/rust/otoroshi_wasm_backend.zip languages/rust/otoroshi_wasm_backend/src +zip -rj ../../cli/templates/otoroshi/languages/rust/otoroshi_wasm_pre_route .zip languages/rust/otoroshi_wasm_pre_route /src +zip -rj ../../cli/templates/otoroshi/languages/rust/otoroshi_wasm_request_transformer.zip languages/rust/otoroshi_wasm_request_transformer/src +zip -rj ../../cli/templates/otoroshi/languages/rust/otoroshi_wasm_response_transformer.zip languages/rust/otoroshi_wasm_response_transformer/src +zip -rj ../../cli/templates/otoroshi/languages/rust/otoroshi_wasm_route_matcher.zip languages/rust/otoroshi_wasm_route_matcher/src +zip -rj ../../cli/templates/otoroshi/languages/rust/otoroshi_wasm_sink.zip languages/rust/otoroshi_wasm_sink/src + +zip -r ../../cli/templates/otoroshi/languages/go/otoroshi_wasm_access_control.zip languages/go/otoroshi_wasm_access_control +zip -r ../../cli/templates/otoroshi/languages/go/otoroshi_wasm_backend.zip languages/go/otoroshi_wasm_backend +zip -r ../../cli/templates/otoroshi/languages/go/otoroshi_wasm_pre_route .zip languages/go/otoroshi_wasm_pre_route +zip -r ../../cli/templates/otoroshi/languages/go/otoroshi_wasm_request_transformer.zip languages/go/otoroshi_wasm_request_transformer +zip -r ../../cli/templates/otoroshi/languages/go/otoroshi_wasm_response_transformer.zip languages/go/otoroshi_wasm_response_transformer +zip -r ../../cli/templates/otoroshi/languages/go/otoroshi_wasm_route_matcher.zip languages/go/otoroshi_wasm_route_matcher +zip -r ../../cli/templates/otoroshi/languages/go/otoroshi_wasm_sink.zip languages/go/otoroshi_wasm_sink \ No newline at end of file diff --git a/ui/src/App.js b/ui/src/App.js index 7a6b67f..e518ddf 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -86,8 +86,8 @@ class App extends React.Component { } else if (editorState === 'onNewPlugin') { const newPlugin = plugins.find(plugin => plugin.new && plugin.newFilename && plugin.newFilename.length > 0) if (newPlugin) { - const { newFilename, type, template } = newPlugin; - Service.createPlugin(newFilename, type, template) + const { newFilename, type, template, productTemplate } = newPlugin; + Service.createPlugin(newFilename, type, template, productTemplate) .then(res => { if (!res.error) { this.setState({ @@ -185,7 +185,7 @@ class App extends React.Component { }) } - onNewPlugin = (type, template) => { + onNewPlugin = (type, template, productTemplate) => { this.setState({ plugins: this.state.plugins.filter(p => !p.new) }, () => { @@ -198,7 +198,8 @@ class App extends React.Component { new: true, filename: '', type, - template + template, + productTemplate } ] }) @@ -289,7 +290,7 @@ class App extends React.Component { }) } - initializeEmptyPlugin = () => { + initializeEmptyPlugin = async () => { const { selectedPlugin } = this.state; const INFORMATIONS_FILENAME = { @@ -301,6 +302,20 @@ class App extends React.Component { opa: "package.json" }; + const LANGUAGES_INDEX = { + rust: 'lib.rs', + js: 'index.js', + ts: 'index.ts', + go: 'main.go' + }; + + let indexFileContent = undefined + + if (selectedPlugin.type !== "opa" && selectedPlugin.productTemplate) { + indexFileContent = await Service.getPluginProductTemplate(selectedPlugin.type, selectedPlugin.template || 'empty', selectedPlugin.productTemplate) + .then(res => res.text()) + } + this.updateSelectedPlugin({ selectedPlugin: { ...selectedPlugin, @@ -312,6 +327,11 @@ class App extends React.Component { .replace('@@PLUGIN_NAME@@', selectedPlugin.filename) .replace('@@PLUGIN_VERSION@@', '1.0.0') } + } else if (indexFileContent && file.filename === LANGUAGES_INDEX[selectedPlugin.type]) { + return { + ...file, + content: indexFileContent + } } return file; }) @@ -357,7 +377,7 @@ class App extends React.Component { .then(res => { // first case match the creation of a new plugin if (res.error && res.status === 404) { - Service.getPluginTemplate(plugin.type, plugin.template || 'empty') + Service.getPluginTemplate(plugin.type, plugin.template || 'empty', plugin.productTemplate) .then(template => { if (template.status !== 200) { template.json().then(res => window.alert(JSON.stringify(res))) diff --git a/ui/src/PluginManager.js b/ui/src/PluginManager.js index b641aa4..9c6431e 100644 --- a/ui/src/PluginManager.js +++ b/ui/src/PluginManager.js @@ -9,6 +9,7 @@ import Otoroshi from './assets/otoroshi.png'; import Izanami from './assets/izanami.png'; import { createGithubRepo } from './services'; import { LOGOS } from './FilesLogo'; +import { OTOROSHI_TEMPLATES } from './templates/otoroshi'; class PluginManager extends React.Component { render() { @@ -44,8 +45,11 @@ class PluginManager extends React.Component { } function NewPluginModal({ onNewPlugin, setProjectSelector, reloadPlugins, active }) { + const [showGithubModal, setGithubModal] = useState(false); - const [showTemplates, setShowTemplates] = useState(false); + const [language, setLanguage] = useState(false); + const [product, setProduct] = useState(); + const [otoroshiTemplates, setOtoroshiTemplates] = useState(false); const [repo, setRepo] = useState(""); const [owner, setOwner] = useState(""); @@ -156,7 +160,7 @@ function NewPluginModal({ onNewPlugin, setProjectSelector, reloadPlugins, active }} onClick={e => e.stopPropagation()}> {active &&

Languages

+ className='d-flex align-items-center justify-content-center'>Language
{[ { @@ -197,9 +201,9 @@ function NewPluginModal({ onNewPlugin, setProjectSelector, reloadPlugins, active type="button" key={`action-${i}`} className='btn btn-sm btn-light d-flex align-items-center mb-2' - onClick={onClick ? onClick : () => setShowTemplates(value)} + onClick={onClick ? onClick : () => setLanguage(value)} style={{ - border: value === showTemplates ? '1px solid #2ecc71' : 'none', + border: value === language ? '1px solid #2ecc71' : 'none', gap: '.5rem', padding: '.5rem 1rem', borderRadius: 0, @@ -214,7 +218,7 @@ function NewPluginModal({ onNewPlugin, setProjectSelector, reloadPlugins, active width: 30, height: 30, background: 'rgb(46 204 113 / 27%)', - display: value === showTemplates ? 'block' : 'none' + display: value === language ? 'block' : 'none' }}> @@ -227,19 +231,35 @@ function NewPluginModal({ onNewPlugin, setProjectSelector, reloadPlugins, active style={{ border: 'none', borderRadius: 6, padding: '.5rem 1rem', background: '#000', flex: 1 }} onClick={e => { e.stopPropagation(); - setShowTemplates(false) + setLanguage(false) setProjectSelector(false) }}>Cancel
} - {active && showTemplates && } + {active && language && + { + setProduct(product) + if (product === "otoroshi" && language !== "opa") { + setOtoroshiTemplates(true) + } else { + setOtoroshiTemplates(false) + onNewPlugin(language, product) + setProjectSelector(false) + } + }} />} + {active && otoroshiTemplates && + } } -function TemplatesSelector({ language, onNewPlugin }) { - +function ProductsSelector({ onClick, product }) { return

Templates

+ className='d-flex align-items-center justify-content-center'>Target
{[ { icon: , title: 'Empty', - onClick: () => onNewPlugin(language, 'empty') + value: 'empty', + onClick: () => onClick('empty') }, { icon: , title: 'Otoroshi', - onClick: () => onNewPlugin(language, 'otoroshi') + value: 'otoroshi', + onClick: () => onClick('otoroshi') }, { icon: , title: 'Izanami', - onClick: () => onNewPlugin(language, 'izanami') + value: 'izanami', + onClick: () => onClick('izanami') } - ].map(({ icon, onClick, title }, i) => { + ].map(({ icon, onClick, title, value }, i) => { + const selected = value === product + return + })} +
+
+
+} + +function OtoroshiTemplatesSelector({ language, onNewPlugin }) { + + const [otoroshiTemplate, setOtoroshiTemplate] = useState("") + + return
+
+

Templates

+
+ {Object.entries(OTOROSHI_TEMPLATES).map(([title, { key, description }]) => ({ + icon: , + title, + description, + onClick: () => onNewPlugin(language, 'empty', key) + })).map(({ icon, onClick, title, description }, i) => { return })}
diff --git a/ui/src/Terminal.js b/ui/src/Terminal.js index 6e796dc..4d9f109 100644 --- a/ui/src/Terminal.js +++ b/ui/src/Terminal.js @@ -20,7 +20,6 @@ function Terminal({ sizeTerminal, toggleResizingTerminal, changeTerminalSize, se }, [loadConfigurationFile]); const connect = (isDevelopment, isWSS) => { - // console.log("connect ws") let socket; let protocol = 'ws'; @@ -58,7 +57,7 @@ function Terminal({ sizeTerminal, toggleResizingTerminal, changeTerminalSize, se } socket.onclose = function (e) { - // console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason); + console.log('Socket is closed. Reconnect will be attempted in 5 second.', e.reason); setTimeout(function () { connect(isDevelopment, isWSS); diff --git a/ui/src/services/index.js b/ui/src/services/index.js index 2701dfa..e3aacfd 100644 --- a/ui/src/services/index.js +++ b/ui/src/services/index.js @@ -23,13 +23,14 @@ const rawFetch = (url, init = {}) => fetch(`/api${url}`, { const jsonFetch = (url, init) => f(url, init).then(r => r.json()) -export const createPlugin = (plugin, type, template) => { +export const createPlugin = (plugin, type, template, productTemplate) => { return jsonFetch('/plugins', { method: 'POST', body: JSON.stringify({ plugin, type, - template + template, + productTemplate }) }) } @@ -53,7 +54,9 @@ export const getPlugin = plugin => rawFetch(`/plugins/${plugin}`) export const getPluginConfig = plugin => jsonFetch(`/plugins/${plugin}/configurations`) -export const getPluginTemplate = (type, template) => f(`/templates?type=${type}&template=${template}`); +export const getPluginTemplate = (type, template, productTemplate) => f(`/templates?type=${type}&template=${template}&productTemplate=${productTemplate}`); + +export const getPluginProductTemplate = (type, template, productTemplate) => f(`/products_templates?type=${type}&template=${template}&productTemplate=${productTemplate}`); const buildZip = plugin => { const jsZip = new JSZip() diff --git a/ui/src/templates/otoroshi.js b/ui/src/templates/otoroshi.js new file mode 100644 index 0000000..39b898a --- /dev/null +++ b/ui/src/templates/otoroshi.js @@ -0,0 +1,34 @@ +export const OTOROSHI_TEMPLATES = { + "Request transformer": { + key: "OTOROSHI_WASM_REQUEST_TRANSFORMER", + description: "Transform the content of the request with a wasm plugin" + }, + "Response transformer": { + key: "OTOROSHI_WASM_RESPONSE_TRANSFORMER", + description: "Transform the content of a response with a wasm plugin" + }, + "Access control": { + key: "OTOROSHI_WASM_ACCESS_CONTROL", + description: "Delegate route access to a wasm plugin" + }, + "Backend": { + key: "OTOROSHI_WASM_BACKEND", + description: "This plugin can be used to use a wasm plugin as backend" + }, + "Route matcher": { + key: "OTOROSHI_WASM_ROUTE_MATCHER", + description: "This plugin can be used to use a wasm plugin as route matcher" + }, + "Sink": { + key: "OTOROSHI_WASM_SINK", + description: "Handle unmatched requests with a wasm plugin" + }, + // "Router": { + // key: "OTOROSHI_WASM_ROUTER", + // description: "Can decide for routing with a wasm plugin" + // }, + "Pre route": { + key: "OTOROSHI_WASM_PRE_ROUTE", + description: "This plugin can be used to use a wasm plugin as in pre-route phase" + }, +} \ No newline at end of file