Extending Envoy Proxy with Golang WebAssembly

$ brew update
$ brew install envoy
$ brew tap tinygo-org/tools
$ brew install tinygo
package main

import (
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
)

type helloHttpContext struct {
proxywasm.DefaultHttpContext
}

func main() {

proxywasm.SetNewHttpContext(newHttpContext)
}

func newHttpContext(uint32, uint32) proxywasm.HttpContext {

return &helloHttpContext{}
}

func (ctx *helloHttpContext) OnHttpRequestHeaders(numHeaders int, _ bool) types.Action {

if numHeaders > 0 {
headers, err := proxywasm.GetHttpRequestHeaders()
if err != nil {
proxywasm.LogErrorf("failed to get request headers with '%v'", err)
return types.ActionContinue
}
proxywasm.LogInfof("request headers: '%+v'", headers)
}

return types.ActionContinue
}
$ tinygo build -o ./hello.wasm -scheduler=none -target=wasi ./main.go
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 127.0.0.1, port_value: 8085 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: svc_hello }
http_filters:
- name: envoy.filters.http.wasm
typed_config:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
value:
config:
name: "my_plugin"
root_id: "my_root_id"
vm_config:
vm_id: "my_vm_id"
runtime: "envoy.wasm.runtime.v8"
code:
local:
filename: "hello.wasm"
allow_precompiled: true
- name: envoy.filters.http.router
typed_config: {}

clusters:
- name: svc_hello
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: svc_hello
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8080

admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 8001
package main

import (
"net/http"

log "github.com/sirupsen/logrus"
)

func main() {

m := http.NewServeMux()
m.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
if _, err := w.Write([]byte("hola mundo :)")); err != nil {
log.Errorf("failed to stream response with '%v'", err)
}
})
const addr = ":8080"
server := &http.Server{
Addr: addr,
Handler: m,
}
log.Infof("listening on '%s'", addr)
log.Fatal(server.ListenAndServe())
}
$ envoy -c envoy.yaml -l debug
$ curl localhost:8085/hello
wasm log: response headers: [[:status 200] [date Sun, 24 Jan 2021 00:42:00 GMT] [content-length 13] [content-type text/plain; charset=utf-8] [x-envoy-upstream-service-time 0]]

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store