I'm trying to run my WASM Go filter to make an external HTTP call using the net/http module. Envoy fails to load the WASM code. Why is the import failing?
Envoy/Istio version: istio/proxyv2:1.11.4
SDK version: v0.16.1-0.20220127085108-af57b89bc067
TinyGo version: tinygo version 0.22.0 darwin/amd64 (using go version go1.17.6 and LLVM version 13.0.0)
Error Logs
2022-01-31T20:34:18.513749Z error envoy wasm Failed to load Wasm module due to a missing import: env.time.resetTimer
2022-01-31T20:34:18.513794Z error envoy wasm Failed to load Wasm module due to a missing import: env.time.stopTimer
2022-01-31T20:34:18.513807Z error envoy wasm Failed to load Wasm module due to a missing import: env.time.startTimer
2022-01-31T20:34:18.513817Z error envoy wasm Failed to load Wasm module due to a missing import: env.sync/atomic.AddInt32
2022-01-31T20:34:18.513826Z error envoy wasm Failed to load Wasm module due to a missing import: wasi_snapshot_preview1.fd_filestat_get
2022-01-31T20:34:18.513833Z error envoy wasm Failed to load Wasm module due to a missing import: wasi_snapshot_preview1.fd_pread
2022-01-31T20:34:18.513840Z error envoy wasm Failed to load Wasm module due to a missing import: wasi_snapshot_preview1.fd_prestat_get
2022-01-31T20:34:18.513846Z error envoy wasm Failed to load Wasm module due to a missing import: wasi_snapshot_preview1.fd_prestat_dir_name
2022-01-31T20:34:18.513854Z error envoy wasm Failed to load Wasm module due to a missing import: wasi_snapshot_preview1.path_open
2022-01-31T20:34:18.513864Z error envoy wasm Wasm VM failed Failed to initialize Wasm code
2022-01-31T20:34:18.517062Z critical envoy wasm Plugin configured to fail closed failed to load
2022-01-31T20:34:18.517191Z warning envoy config gRPC config for type.googleapis.com/envoy.config.core.v3.TypedExtensionConfig rejected: Unable to create Wasm HTTP filter
tinygo build -o main.wasm -scheduler=asyncify -target=wasi main.go
Actual Code
package main
import (
"errors"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
"io/ioutil"
"time"
"net/http"
)
const (
sharedDataKey = "hello_world_shared_data_key"
)
func main() {
proxywasm.SetVMContext(&vmContext{})
}
type (
vmContext struct{}
pluginContext struct {
// Embed the default plugin context here,
// so that we don't need to reimplement all the methods.
types.DefaultPluginContext
}
httpContext struct {
// Embed the default http context here,
// so that we don't need to reimplement all the methods.
types.DefaultHttpContext
}
)
// Override types.VMContext.
func (*vmContext) OnVMStart(vmConfigurationSize int) types.OnVMStartStatus {
proxywasm.LogInfo("Inside OnVMStart")
http := http.Client{Timeout: time.Duration(10) * time.Second}
resp, err := http.Get("http://SOME_URL:8001/echo?message=hello_world")
if err != nil {
proxywasm.LogWarnf("Error calling hello_world/echo on OnVMStart: %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
proxywasm.LogWarnf("Error parsing hello_world/echo response on OnVMStart: %v", err)
}
proxywasm.LogInfof("Response Body : %s", body)
initialValueBuf := []byte("body")
if err := proxywasm.SetSharedData(sharedDataKey, initialValueBuf, 0); err != nil {
proxywasm.LogWarnf("Error setting shared hello_world data on OnVMStart: %v", err)
}
return types.OnVMStartStatusOK
}
// Override types.DefaultVMContext.
func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
return &pluginContext{}
}
// Override types.DefaultPluginContext.
func (*pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
return &httpContext{}
}
// Override types.DefaultHttpContext.
func (ctx *httpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
for {
value, err := ctx.getSharedData()
if err == nil {
proxywasm.LogInfof("shared data value: %s", value)
} else if errors.Is(err, types.ErrorStatusCasMismatch) {
continue
}
break
}
return types.ActionContinue
}
func (ctx *httpContext) getSharedData() (string, error) {
value, cas, err := proxywasm.GetSharedData(sharedDataKey)
if err != nil {
proxywasm.LogWarnf("error getting shared data on OnHttpRequestHeaders with cas %d: %v ", cas, err)
return "error", err
}
shared_value := string(value)
return shared_value, err
}