Skip to content
This repository was archived by the owner on Apr 24, 2025. It is now read-only.

Commit d01c7e7

Browse files
author
Wim Spaargaren
committed
chore: add http body example & implement proxytest set buffer bytes method
1 parent 37249c9 commit d01c7e7

File tree

6 files changed

+220
-2
lines changed

6 files changed

+220
-2
lines changed

examples/http_body/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## http_headers
2+
3+
this example replaces the request body
4+
5+
```
6+
2020/10/12 13:41:31 proxy_info_log: body size: 29
7+
2020/10/12 13:41:31 proxy_info_log: initial request body: { "initial": "request body" }
8+
2020/10/12 13:41:31 proxy_info_log: on http request body finished
9+
```

examples/http_body/envoy.yaml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
static_resources:
2+
listeners:
3+
- name: main
4+
address:
5+
socket_address:
6+
address: 0.0.0.0
7+
port_value: 18000
8+
filter_chains:
9+
- filters:
10+
- name: envoy.http_connection_manager
11+
config:
12+
stat_prefix: ingress_http
13+
codec_type: auto
14+
route_config:
15+
name: local_route
16+
virtual_hosts:
17+
- name: local_service
18+
domains:
19+
- "*"
20+
routes:
21+
- match:
22+
prefix: "/"
23+
route:
24+
cluster: web_service
25+
http_filters:
26+
- name: envoy.filters.http.wasm
27+
config:
28+
config:
29+
name: "my_plugin"
30+
root_id: "my_root_id"
31+
vm_config:
32+
vm_id: "my_vm_id"
33+
runtime: "envoy.wasm.runtime.v8"
34+
code:
35+
local:
36+
filename: "./examples/http_headers/main.go.wasm"
37+
allow_precompiled: true
38+
- name: envoy.router
39+
config: {}
40+
- name: staticreply
41+
address:
42+
socket_address:
43+
address: 127.0.0.1
44+
port_value: 8099
45+
filter_chains:
46+
- filters:
47+
- name: envoy.http_connection_manager
48+
config:
49+
stat_prefix: ingress_http
50+
codec_type: auto
51+
route_config:
52+
name: local_route
53+
virtual_hosts:
54+
- name: local_service
55+
domains:
56+
- "*"
57+
routes:
58+
- match:
59+
prefix: "/"
60+
direct_response:
61+
status: 200
62+
body:
63+
inline_string: "example body\n"
64+
http_filters:
65+
- name: envoy.router
66+
config: {}
67+
68+
clusters:
69+
- name: web_service
70+
connect_timeout: 0.25s
71+
type: static
72+
lb_policy: round_robin
73+
hosts:
74+
- socket_address:
75+
address: 127.0.0.1
76+
port_value: 8099
77+
admin:
78+
access_log_path: "/dev/null"
79+
address:
80+
socket_address:
81+
address: 0.0.0.0
82+
port_value: 8001

examples/http_body/main.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2020 Tetrate
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
19+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
20+
)
21+
22+
func main() {
23+
proxywasm.SetNewHttpContext(newContext)
24+
}
25+
26+
type httpBody struct {
27+
// you must embed the default context so that you need not to reimplement all the methods by yourself
28+
proxywasm.DefaultHttpContext
29+
contextID uint32
30+
}
31+
32+
func newContext(rootContextID, contextID uint32) proxywasm.HttpContext {
33+
return &httpBody{contextID: contextID}
34+
}
35+
36+
// override
37+
func (ctx *httpBody) OnHttpRequestBody(bodySize int, endOfStream bool) types.Action {
38+
proxywasm.LogInfof("body size: %d", bodySize)
39+
40+
b, err := proxywasm.GetHttpRequestBody(0, bodySize)
41+
if err != nil {
42+
proxywasm.LogErrorf("failed to get request body: %v", err)
43+
return types.ActionContinue
44+
}
45+
46+
proxywasm.LogInfof("initial request body: %s", string(b))
47+
48+
err = proxywasm.SetHttpRequestBody([]byte(`{"test":"data"}`))
49+
if err != nil {
50+
proxywasm.LogErrorf("failed to get request body: %v", err)
51+
return types.ActionContinue
52+
}
53+
54+
proxywasm.LogInfof("on http request body finished")
55+
56+
return types.ActionContinue
57+
}

examples/http_body/main_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package main
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
8+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxytest"
9+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
10+
)
11+
12+
func TestHttpHeaders_OnHttpRequestHeaders(t *testing.T) {
13+
opt := proxytest.NewEmulatorOption().
14+
WithNewHttpContext(newContext)
15+
host := proxytest.NewHostEmulator(opt)
16+
defer host.Done()
17+
18+
id := host.HttpFilterInitContext()
19+
host.HttpFilterPutRequestBody(id, []byte(`{ "initial": "request body" }`))
20+
21+
res := host.HttpFilterGetRequestBody(id)
22+
assert.Equal(t, `{"test":"data"}`, string(res))
23+
24+
logs := host.GetLogs(types.LogLevelInfo)
25+
require.Greater(t, len(logs), 1)
26+
27+
assert.Equal(t, "on http request body finished", logs[len(logs)-1])
28+
assert.Equal(t, `initial request body: { "initial": "request body" }`, logs[len(logs)-2])
29+
assert.Equal(t, "body size: 29", logs[len(logs)-3])
30+
}

proxytest/http.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ func (h *httpHostEmulator) httpHostEmulatorProxyGetBufferBytes(bt types.BufferTy
7676
return types.StatusOK
7777
}
7878

79+
func (h *httpHostEmulator) httpHostEmulatorProxySetBufferBytes(bt types.BufferType, start int, maxSize int,
80+
bufferData *byte, bufferSize int) types.Status {
81+
body := proxywasm.RawBytePtrToByteSlice(bufferData, bufferSize)
82+
active := proxywasm.VMStateGetActiveContextID()
83+
stream := h.httpStreams[active]
84+
switch bt {
85+
case types.BufferTypeHttpRequestBody:
86+
stream.requestBody = body
87+
case types.BufferTypeHttpResponseBody:
88+
stream.responseBody = body
89+
default:
90+
panic("unreachable: maybe a bug in this host emulation or SDK")
91+
}
92+
return types.StatusOK
93+
}
94+
7995
// impl rawhostcall.ProxyWASMHost: delegated from hostEmulator
8096
func (h *httpHostEmulator) httpHostEmulatorProxyGetHeaderMapValue(mapType types.MapType, keyData *byte,
8197
keySize int, returnValueData **byte, returnValueSize *int) types.Status {
@@ -351,6 +367,15 @@ func (h *httpHostEmulator) HttpFilterPutRequestBody(contextID uint32, body []byt
351367
len(body), false) // TODO: allow for specifying end_of_stream
352368
}
353369

370+
func (h *httpHostEmulator) HttpFilterGetRequestBody(contextID uint32) []byte {
371+
cs, ok := h.httpStreams[contextID]
372+
if !ok {
373+
log.Fatalf("invalid context id: %d", contextID)
374+
}
375+
376+
return cs.requestBody
377+
}
378+
354379
// impl HostEmulator
355380
func (h *httpHostEmulator) HttpFilterPutResponseBody(contextID uint32, body []byte) {
356381
cs, ok := h.httpStreams[contextID]
@@ -363,6 +388,15 @@ func (h *httpHostEmulator) HttpFilterPutResponseBody(contextID uint32, body []by
363388
len(body), false) // TODO: allow for specifying end_of_stream
364389
}
365390

391+
func (h *httpHostEmulator) HttpFilterGetResponseBody(contextID uint32) []byte {
392+
cs, ok := h.httpStreams[contextID]
393+
if !ok {
394+
log.Fatalf("invalid context id: %d", contextID)
395+
}
396+
397+
return cs.responseBody
398+
}
399+
366400
// impl HostEmulator
367401
func (h *httpHostEmulator) HttpFilterCompleteHttpStream(contextID uint32) {
368402
proxywasm.ProxyOnDone(contextID)

proxytest/proxytest.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ type HostEmulator interface {
4141
HttpFilterPutRequestTrailers(contextID uint32, headers [][2]string)
4242
HttpFilterPutResponseTrailers(contextID uint32, headers [][2]string)
4343
HttpFilterPutRequestBody(contextID uint32, body []byte)
44+
HttpFilterGetRequestBody(contextID uint32) []byte
4445
HttpFilterPutResponseBody(contextID uint32, body []byte)
46+
HttpFilterGetResponseBody(contextID uint32) []byte
4547
HttpFilterCompleteHttpStream(contextID uint32)
4648
HttpFilterGetCurrentStreamAction(contextID uint32) types.Action
4749
HttpFilterGetSentLocalResponse(contextID uint32) *LocalHttpResponse
@@ -117,8 +119,12 @@ func (h *hostEmulator) ProxyGetBufferBytes(bt types.BufferType, start int, maxSi
117119
}
118120

119121
func (h *hostEmulator) ProxySetBufferBytes(bt types.BufferType, start int, maxSize int, bufferData *byte, bufferSize int) types.Status {
120-
// TODO: implement host emulator set buffer bytes
121-
return types.StatusOK
122+
switch bt {
123+
case types.BufferTypeHttpRequestBody, types.BufferTypeHttpResponseBody:
124+
return h.httpHostEmulatorProxySetBufferBytes(bt, start, maxSize, bufferData, bufferSize)
125+
default:
126+
panic("unreachable: maybe a bug in this host emulation or SDK")
127+
}
122128
}
123129

124130
// impl rawhostcall.ProxyWASMHost

0 commit comments

Comments
 (0)