Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions filters/builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/zalando/skipper/filters/tee"
"github.com/zalando/skipper/filters/tls"
"github.com/zalando/skipper/filters/tracing"
"github.com/zalando/skipper/filters/wasm"
"github.com/zalando/skipper/filters/xforward"
"github.com/zalando/skipper/script"
)
Expand Down Expand Up @@ -230,6 +231,7 @@ func Filters() []filters.Spec {
consistenthash.NewConsistentHashKey(),
consistenthash.NewConsistentHashBalanceFactor(),
tls.New(),
wasm.NewWASM(),
}
}

Expand Down
1 change: 1 addition & 0 deletions filters/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ const (
OpaServeResponseName = "opaServeResponse"
OpaServeResponseWithReqBodyName = "opaServeResponseWithReqBody"
TLSName = "tlsPassClientCertificates"
WASMName = "wasm"

// Undocumented filters
HealthCheckName = "healthcheck"
Expand Down
15 changes: 15 additions & 0 deletions filters/wasm/testdata/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

//export request
func request(x, y uint32) uint32 {
return x + y
}

//export response
func response(x, y uint32) uint32 {
return x - y
}

// main is required for the `wasi` target, even if it isn't used.
// See https://wazero.io/languages/tinygo/#why-do-i-have-to-define-main
func main() {}
Binary file added filters/wasm/testdata/add.wasm
Binary file not shown.
104 changes: 104 additions & 0 deletions filters/wasm/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package wasm

import (
"context"
"net/url"
"os"

"github.com/sirupsen/logrus"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/zalando/skipper/filters"
)

type wasmSpec struct{}

type wasm struct {
code []byte
mod api.Module
request api.Function
response api.Function
}

func NewWASM() filters.Spec {
return &wasmSpec{}
}

// Name implements filters.Spec.
func (*wasmSpec) Name() string {
return filters.WASMName
}

// CreateFilter implements filters.Spec.
func (*wasmSpec) CreateFilter(args []interface{}) (filters.Filter, error) {
if len(args) != 1 {
return nil, filters.ErrInvalidFilterParameters
}
src, ok := args[0].(string)
if !ok {
return nil, filters.ErrInvalidFilterParameters
}
u, err := url.Parse(src)
if err != nil {
return nil, filters.ErrInvalidFilterParameters
}

var code []byte

switch u.Scheme {
case "file":
code, err = os.ReadFile(u.Path)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should make this lazy and cacheable and cleanup on filter close

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, as I wrote in the PR title super basic. I used https://github.com/tetratelabs/wazero/tree/main/examples/basic to test the super basic example.

if err != nil {
logrus.Errorf("Failed to load file %q: %v", u.Path, err)
return nil, filters.ErrInvalidFilterParameters
}
case "https":
panic("not implemented")
default:
return nil, filters.ErrInvalidFilterParameters
}

ctx := context.Background()
r := wazero.NewRuntime(ctx) // TODO: needs r.Close()
// Instantiate WASI, which implements host functions needed for TinyGo to
// implement `panic`.
wasi_snapshot_preview1.MustInstantiate(ctx, r)

// Instantiate the guest Wasm into the same runtime. It exports the `add`
// function, implemented in WebAssembly.
mod, err := r.Instantiate(ctx, code)
if err != nil {
logrus.Fatalf("failed to instantiate module: %v", err)
}
request := mod.ExportedFunction("request")
response := mod.ExportedFunction("response")

return &wasm{
code: code,
mod: mod,
request: request,
response: response,
}, nil
}

// Request implements filters.Filter.
func (w *wasm) Request(filters.FilterContext) {

result, err := w.request.Call(context.Background(), 2, 3)
if err != nil {
logrus.Errorf("failed to call add: %v", err)
}
logrus.Infof("request result: %v", result)

}

// Response implements filters.Filter.
func (w *wasm) Response(filters.FilterContext) {
result, err := w.response.Call(context.Background(), 3, 2)
if err != nil {
logrus.Errorf("failed to call add: %v", err)
}
logrus.Infof("response result: %v", result)

}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ require (
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/tetratelabs/wazero v1.6.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,8 @@ github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BG
github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/testcontainers/testcontainers-go v0.27.0 h1:IeIrJN4twonTDuMuBNQdKZ+K97yd7VrmNGu+lDpYcDk=
github.com/testcontainers/testcontainers-go v0.27.0/go.mod h1:+HgYZcd17GshBUZv9b+jKFJ198heWPQq3KQIp2+N+7U=
github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g=
github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
Expand Down