Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
flrgh committed Nov 14, 2024
1 parent bd95ac2 commit b67d3a2
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*/wasm
51 changes: 51 additions & 0 deletions examples/property/config/demo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
_format_version: "3.0"

services:
- name: demo
url: http://httpbin.konghq.com
routes:
- name: my-route
paths:
- /anything
strip_path: false
methods:
- GET
- POST
filter_chains:
- filters:
- name: datakit
config:
debug: true
nodes:
- name: FIRST
type: call
url: https://api.zippopotam.us/br/93000-000

- name: SERVICE_ID
type: property
property: kong.service_id

- name: MY_HEADERS
type: jq
inputs:
- first: FIRST.body
- service: SERVICE_ID
jq: |
{
"X-Hello": "World",
"X-Foo": "Bar",
"X-Name": $first.country,
"X-Kong-Service-Id": $service,
}
- name: MY_BODY
type: jq
inputs:
first: FIRST.body
jq: $first

- name: exit
type: exit
inputs:
body: MY_BODY
headers: MY_HEADERS
95 changes: 95 additions & 0 deletions examples/property/demo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env bash
set -x

DEMO_KONG_CONTAINER="${DEMO_KONG_CONTAINER:-kong-wasm}"
DEMO_KONG_IMAGE="${DEMO_KONG_IMAGE:-kong/kong:nightly}"

function message() {
set +x
echo "----------------------------------------------------------------------"
echo $1
echo "----------------------------------------------------------------------"
set -x
}

function cleanup() {
docker kill -s 9 "$DEMO_KONG_CONTAINER" &>/dev/null || true
}

################################################################################

if [[ "$1" == "stop" ]]
then
docker stop $DEMO_KONG_CONTAINER
docker rm $DEMO_KONG_CONTAINER
exit 0
fi

### Build filter ###############################################################

message "Building the filter using cargo..."

(
cd ../..
cargo build --target=wasm32-wasip1 --release || exit 1
) || exit 1

### Copy filter to wasm/ #######################################################

mkdir -p wasm

cp -a ../../target/wasm32-wasip1/release/*.wasm wasm/
cp ../../*.meta.json wasm/

script_dir=$(dirname $(realpath $0))

### Start container ############################################################

message "Setting up the Kong Gateway container..."

cleanup

docker run --rm -d --name "$DEMO_KONG_CONTAINER" \
-v "$script_dir/config:/kong/config/" \
-v "$script_dir/wasm:/wasm" \
-e "KONG_LOG_LEVEL=debug" \
-e "KONG_DATABASE=off" \
-e "KONG_DECLARATIVE_CONFIG=/kong/config/demo.yml" \
-e "KONG_NGINX_WASM_SHM_KV_DATAKIT=12m" \
-e "KONG_NGINX_HTTP_PROXY_WASM_ISOLATION=none" \
-e "KONG_NGINX_WORKER_PROCESSES=2" \
-e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
-e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
-e "KONG_WASM=on" \
-e "KONG_WASM_FILTERS_PATH=/wasm" \
-e "KONG_PLUGINS=off" \
-p 8000:8000 \
-p 8443:8443 \
-p 8001:8001 \
-p 8444:8444 \
"$DEMO_KONG_IMAGE"

trap cleanup ERR EXIT

### Show configuration #########################################################

message "This is the configuration loaded into Kong:"

cat config/demo.yml

sleep 5

### Issue requests #############################################################

message "Now let's send a request to see the filter in effect:"

http POST :8000/anything foo=bar

message "Logs"
docker logs "$DEMO_KONG_CONTAINER" || true

message "Finishing up!"

#docker stop $DEMO_KONG_CONTAINER
#docker rm $DEMO_KONG_CONTAINER

4 changes: 4 additions & 0 deletions examples/property/reconfigure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash

http :8001/config config=@config/demo.yml

3 changes: 3 additions & 0 deletions examples/property/reset.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

rm -rf wasm
1 change: 1 addition & 0 deletions src/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ proxy_wasm::main! {{
nodes::register_node("call", Box::new(nodes::call::CallFactory {}));
nodes::register_node("exit", Box::new(nodes::exit::ExitFactory {}));
nodes::register_node("jq", Box::new(nodes::jq::JqFactory {}));
nodes::register_node("property", Box::new(nodes::property::PropertyFactory {}));

proxy_wasm::set_log_level(LogLevel::Debug);
proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> {
Expand Down
1 change: 1 addition & 0 deletions src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod call;
pub mod exit;
pub mod handlebars;
pub mod jq;
pub mod property;

pub type NodeVec = Vec<Box<dyn Node>>;

Expand Down
91 changes: 91 additions & 0 deletions src/nodes/property.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use log;
use proxy_wasm::traits::*;
use serde_json::Value;
use std::any::Any;
use std::collections::BTreeMap;

use crate::config::get_config_value;
use crate::data::{Input, State, State::*};
use crate::nodes::{Node, NodeConfig, NodeFactory, PortConfig};
use crate::payload::Payload;

#[derive(Clone, Debug)]
pub struct PropertyConfig {
path: Vec<String>,
}

impl PropertyConfig {
fn new(name: String) -> Self {
Self {
path: name.split('.').map(|s| s.to_string()).collect(),
}
}

fn to_path(&self) -> Vec<&str> {
self.path.iter().map(String::as_str).collect()
}
}

impl NodeConfig for PropertyConfig {
fn as_any(&self) -> &dyn Any {
self
}
}

pub struct Property {
config: PropertyConfig,
}

impl Node for Property {
fn run(&self, ctx: &dyn HttpContext, _input: &Input) -> State {
log::debug!("property: run");

Done(match ctx.get_property(self.config.to_path()) {
Some(bytes) => {
log::info!("{:?} => {:?}", &self.config.path, bytes);
vec![Some(Payload::Raw(bytes))]
}
None => {
log::info!("{:?} => None", &self.config.path);
vec![]
}
})
}
}

pub struct PropertyFactory {}

impl NodeFactory for PropertyFactory {
fn default_input_ports(&self) -> PortConfig {
PortConfig {
defaults: PortConfig::names(&["value"]),
user_defined_ports: false,
}
}
fn default_output_ports(&self) -> PortConfig {
PortConfig {
defaults: PortConfig::names(&["value"]),
user_defined_ports: false,
}
}

fn new_config(
&self,
_name: &str,
_inputs: &[String],
_outputs: &[String],
bt: &BTreeMap<String, Value>,
) -> Result<Box<dyn NodeConfig>, String> {
let name = get_config_value::<String>(bt, "property")
.ok_or_else(|| "Missing `property` attribute".to_owned())?;

Ok(Box::new(PropertyConfig::new(name)))
}

fn new_node(&self, config: &dyn NodeConfig) -> Box<dyn Node> {
match config.as_any().downcast_ref::<PropertyConfig>() {
Some(cc) => Box::new(Property { config: cc.clone() }),
None => panic!("incompatible NodeConfig"),
}
}
}

0 comments on commit b67d3a2

Please sign in to comment.