From 2041438866a21d52ce7d1c14da7a36ebb48827bc Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Wed, 27 Oct 2021 14:01:06 +0900 Subject: [PATCH] Fix panic in dispatched callback on getting empty http trailers. (#218) Signed-off-by: Takeshi Yoneda --- e2e/e2e_test.go | 1 + examples/dispatch_call_on_tick/envoy.yaml | 7 +++++- examples/dispatch_call_on_tick/main.go | 30 ++++++++++++++++++++--- proxywasm/hostcall.go | 2 ++ proxywasm/proxytest/http.go | 8 ++++++ 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 8b22ffa7..226c7925 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -34,6 +34,7 @@ func Test_dispatch_call_on_tick(t *testing.T) { if checkMessage(stdErr.String(), []string{ fmt.Sprintf("called %d for contextID=1", count), fmt.Sprintf("called %d for contextID=2", count), + ":status: 200", ":status: 503", }, nil) { count++ } diff --git a/examples/dispatch_call_on_tick/envoy.yaml b/examples/dispatch_call_on_tick/envoy.yaml index eb1505da..f10bf8e7 100644 --- a/examples/dispatch_call_on_tick/envoy.yaml +++ b/examples/dispatch_call_on_tick/envoy.yaml @@ -74,11 +74,16 @@ static_resources: - "*" routes: - match: - prefix: "/" + prefix: "/ok" direct_response: status: 200 body: inline_string: "example body\n" + - match: + prefix: "/fail" + direct_response: + status: 503 + http_filters: - name: envoy.filters.http.router typed_config: {} diff --git a/examples/dispatch_call_on_tick/main.go b/examples/dispatch_call_on_tick/main.go index 483ea36b..685a2609 100644 --- a/examples/dispatch_call_on_tick/main.go +++ b/examples/dispatch_call_on_tick/main.go @@ -15,6 +15,8 @@ package main import ( + "crypto/rand" + "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm" "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types" ) @@ -55,16 +57,38 @@ func (ctx *pluginContext) OnPluginStart(pluginConfigurationSize int) types.OnPlu ctx.callBack = func(numHeaders, bodySize, numTrailers int) { ctx.cnt++ proxywasm.LogInfof("called %d for contextID=%d", ctx.cnt, ctx.contextID) + headers, err := proxywasm.GetHttpCallResponseHeaders() + if err != nil && err != types.ErrorStatusNotFound { + panic(err) + } + for _, h := range headers { + proxywasm.LogInfof("response header for the dispatched call: %s: %s", h[0], h[1]) + } + headers, err = proxywasm.GetHttpCallResponseTrailers() + if err != nil && err != types.ErrorStatusNotFound { + panic(err) + } + for _, h := range headers { + proxywasm.LogInfof("response trailer for the dispatched call: %s: %s", h[0], h[1]) + } } return types.OnPluginStartStatusOK } // Override types.DefaultPluginContext. func (ctx *pluginContext) OnTick() { - hs := [][2]string{ - {":method", "GET"}, {":authority", "some_authority"}, {":path", "/path/to/service"}, {"accept", "*/*"}, + headers := [][2]string{ + {":method", "GET"}, {":authority", "some_authority"}, {"accept", "*/*"}, + } + // Pick random value to select the request path. + buf := make([]byte, 1) + _, _ = rand.Read(buf) + if buf[0]%2 == 0 { + headers = append(headers, [2]string{":path", "/ok"}) + } else { + headers = append(headers, [2]string{":path", "/fail"}) } - if _, err := proxywasm.DispatchHttpCall("web_service", hs, nil, nil, 5000, ctx.callBack); err != nil { + if _, err := proxywasm.DispatchHttpCall("web_service", headers, nil, nil, 5000, ctx.callBack); err != nil { proxywasm.LogCriticalf("dispatch httpcall failed: %v", err) } } diff --git a/proxywasm/hostcall.go b/proxywasm/hostcall.go index 2504ffb3..df6df606 100644 --- a/proxywasm/hostcall.go +++ b/proxywasm/hostcall.go @@ -781,6 +781,8 @@ func getMap(mapType internal.MapType) ([][2]string, error) { st := internal.ProxyGetHeaderMapPairs(mapType, &raw, &rvs) if st != internal.StatusOK { return nil, internal.StatusToError(st) + } else if raw == nil { + return nil, types.ErrorStatusNotFound } bs := internal.RawBytePtrToByteSlice(raw, rvs) diff --git a/proxywasm/proxytest/http.go b/proxywasm/proxytest/http.go index f1d7c434..6acb844a 100644 --- a/proxywasm/proxytest/http.go +++ b/proxywasm/proxytest/http.go @@ -272,6 +272,14 @@ func (h *httpHostEmulator) httpHostEmulatorProxyGetHeaderMapPairs(mapType intern panic("unreachable: maybe a bug in this host emulation or SDK") } + if len(m) == 0 { + // The host might reutrn OK without setting the data pointer, + // if there's nothing to pass to Wasm VM. + *returnValueData = nil + *returnValueSize = 0 + return internal.StatusOK + } + *returnValueData = &m[0] *returnValueSize = len(m) return internal.StatusOK