Skip to content

Commit 9cf8926

Browse files
bzp2010spacewander
andauthored
feat: support set property (#78)
Co-authored-by: 罗泽轩 <spacewanderlzx@gmail.com>
1 parent b871ac4 commit 9cf8926

File tree

9 files changed

+194
-6
lines changed

9 files changed

+194
-6
lines changed

.github/workflows/test.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ jobs:
2121
with:
2222
node-version: 10.0.0
2323

24+
- name: Set up Golang
25+
uses: actions/setup-go@v2
26+
with:
27+
go-version: "1.17.5"
28+
2429
- name: Install rust
2530
uses: actions-rs/toolchain@v1
2631
with:
@@ -50,7 +55,8 @@ jobs:
5055
5156
- name: Script
5257
run: |
53-
sudo make build.go.testdata
58+
sudo chown -R runner:root ~/.cache
59+
make build.go.testdata
5460
5561
pushd ./t/testdata/assemblyscript && npm install && npm run asbuild && popd
5662
pushd ./t/testdata/rust && cargo build --target=wasm32-wasi && popd

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ install:
88

99
.PHONY: build.go.testdata
1010
build.go.testdata:
11-
@find ./t/testdata -type f -name "main.go" | xargs -Ip tinygo build -o p.wasm -scheduler=none -target=wasi p
11+
@find ./t/testdata -type f -name "*.go" | xargs -Ip tinygo build -o p.wasm -scheduler=none -target=wasi p
1212

1313
.PHONY: build.testdata
1414
build.testdata:

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
module github.com/api7/wasm-nginx-module
22

3-
go 1.15
3+
go 1.17
44

55
require (
6-
github.com/tetratelabs/proxy-wasm-go-sdk v0.14.1-0.20210819090022-1e4e69881a31
6+
github.com/tetratelabs/proxy-wasm-go-sdk v0.16.0
77
github.com/valyala/fastjson v1.6.3 // indirect
88
)
99

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
66
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
77
github.com/tetratelabs/proxy-wasm-go-sdk v0.14.1-0.20210819090022-1e4e69881a31 h1:V3GXN5nayOdIU3NypbxVegGFCVGm78qOA8Q7wkeudy8=
88
github.com/tetratelabs/proxy-wasm-go-sdk v0.14.1-0.20210819090022-1e4e69881a31/go.mod h1:qZ+4i6e2wHlhnhgpH0VG4QFzqd2BEvQbQFU0npt2e2k=
9+
github.com/tetratelabs/proxy-wasm-go-sdk v0.15.0 h1:9ckJdaKHhWi1km9J5s7jMF/3GXnSbFkBeR9k9z5cPkY=
10+
github.com/tetratelabs/proxy-wasm-go-sdk v0.15.0/go.mod h1:8CxNZJ+9yDEvNnAog384fC8j1tKNF0tTZevGjOuY9ds=
11+
github.com/tetratelabs/proxy-wasm-go-sdk v0.16.0 h1:6xhDLV4DD2+q3Rs4CDh7cqo69rQ50XgCusv/58D44o4=
12+
github.com/tetratelabs/proxy-wasm-go-sdk v0.16.0/go.mod h1:8CxNZJ+9yDEvNnAog384fC8j1tKNF0tTZevGjOuY9ds=
913
github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc=
1014
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
1115
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

proxy_wasm_abi.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,17 @@ Remove key (`key_data`, `key_size`) from a given map (`map_type`).
268268

269269
Get data such as Nginx variables and plugin ID, Use path_data as key and write the value of the obtained variable to res_data.
270270

271+
272+
### `proxy_set_property`
273+
274+
* params:
275+
- `i32 (const char*) path_data`
276+
- `i32 (size_t) path_size`
277+
- `i32 (const char*) data`
278+
- `i32 (size_t) size`
279+
280+
Set the Nginx variable value, using path_data as the key and data as the value.
281+
271282
## HTTP (L7) extensions
272283

273284
### `proxy_send_http_response`

src/http/ngx_http_wasm_api.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ static int (*set_req_header) (ngx_http_request_t *r,
6767
const char *key, size_t key_len, const char *value,
6868
size_t value_len, ngx_str_t *mvals, size_t mvals_len,
6969
int override, char **errmsg);
70+
static int (*set_variable)(ngx_http_request_t *r, u_char *name_data,
71+
size_t name_len, u_char *lowcase_buf, u_char *value, size_t value_len,
72+
u_char *errbuf, size_t *errlen);
7073

7174
static char *err_bad_ctx = "API disabled in the current context";
7275
static char *err_no_req_ctx = "no request ctx found";
@@ -125,6 +128,7 @@ ngx_http_wasm_resolve_symbol(void)
125128
must_resolve_symbol(get_req_headers_count, ngx_http_lua_ffi_req_get_headers_count);
126129
must_resolve_symbol(get_req_headers, ngx_http_lua_ffi_req_get_headers);
127130
must_resolve_symbol(set_req_header, ngx_http_lua_ffi_req_set_header);
131+
must_resolve_symbol(set_variable, ngx_http_lua_ffi_var_set);
128132

129133
return NGX_OK;
130134
}
@@ -359,6 +363,51 @@ int32_t
359363
proxy_set_property(int32_t path_data, int32_t path_size,
360364
int32_t data, int32_t size)
361365
{
366+
int result;
367+
u_char *key_lowcase;
368+
u_char *errmsg;
369+
size_t errlen = 256;
370+
ngx_log_t *log;
371+
const u_char *key;
372+
const u_char *value;
373+
ngx_http_request_t *r;
374+
375+
log = ngx_http_wasm_get_log();
376+
must_get_req(r);
377+
378+
/* fetch property key and value */
379+
key = ngx_wasm_vm.get_memory(log, path_data, path_size);
380+
if (key == NULL) {
381+
return PROXY_RESULT_INVALID_MEMORY_ACCESS;
382+
}
383+
384+
value = ngx_wasm_vm.get_memory(log, data, size);
385+
if (key == NULL) {
386+
return PROXY_RESULT_INVALID_MEMORY_ACCESS;
387+
}
388+
389+
/*
390+
* Request a piece of temporary memory to store the
391+
* lowercase characters of the property key and errmsg
392+
* of variable setting.
393+
*/
394+
key_lowcase = ngx_http_wasm_get_string_buf(r->pool, path_size + errlen);
395+
errmsg = key_lowcase + path_size;
396+
397+
/* Call the functions in lua-resty-core to set the variables. */
398+
result = set_variable(r, (u_char *) key, path_size, key_lowcase,
399+
(u_char *) value, size, errmsg, &errlen);
400+
401+
if (result != NGX_OK) {
402+
ngx_log_error(NGX_LOG_ERR, log, 0, (const char *)errmsg);
403+
404+
if (ngx_strstrn(errmsg, "not found for writing", 20) != NULL) {
405+
return PROXY_RESULT_NOT_FOUND;
406+
}
407+
408+
return PROXY_RESULT_INTERNAL_FAILURE;
409+
}
410+
362411
return PROXY_RESULT_OK;
363412
}
364413

t/property.t

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ location /t {
1313
}
1414
1515
local wasm = require("resty.proxy-wasm")
16-
local plugin = wasm.load("plugin", "t/testdata/property/main.go.wasm")
16+
local plugin = wasm.load("plugin", "t/testdata/property/get.go.wasm")
1717
for _, case in ipairs(test_cases) do
1818
local plugin_ctx, err = wasm.on_configure(plugin, case)
1919
assert(wasm.on_http_request_headers(plugin_ctx))
@@ -37,7 +37,7 @@ get property: request_uri = /t?test=yeah
3737
location /t {
3838
content_by_lua_block {
3939
local wasm = require("resty.proxy-wasm")
40-
local plugin = wasm.load("plugin", "t/testdata/property/main.go.wasm")
40+
local plugin = wasm.load("plugin", "t/testdata/property/get.go.wasm")
4141
local plugin_ctx, err = wasm.on_configure(plugin, "none")
4242
assert(wasm.on_http_request_headers(plugin_ctx))
4343
}
@@ -46,3 +46,59 @@ location /t {
4646
GET /t?test=yeah
4747
--- error_log
4848
error get property: error status returned by host: not found
49+
50+
51+
52+
=== TEST 3: set_property (custom variable: success)
53+
--- config
54+
location /t {
55+
set $for_test origin_value;
56+
content_by_lua_block {
57+
local wasm = require("resty.proxy-wasm")
58+
local plugin = wasm.load("plugin", "t/testdata/property/set.go.wasm")
59+
local plugin_ctx, err = wasm.on_configure(plugin, 'for_test|new_value')
60+
ngx.say(ngx.var.for_test)
61+
ngx.say(#ngx.var.for_test)
62+
assert(wasm.on_http_request_headers(plugin_ctx))
63+
ngx.say(ngx.var.for_test)
64+
ngx.say(#ngx.var.for_test)
65+
}
66+
}
67+
--- response_body
68+
origin_value
69+
12
70+
new_value
71+
9
72+
--- error_log
73+
set property success: for_test = new_value
74+
75+
76+
77+
=== TEST 4: set_property (host: unchangeable)
78+
--- config
79+
location /t {
80+
content_by_lua_block {
81+
local wasm = require("resty.proxy-wasm")
82+
local plugin = wasm.load("plugin", "t/testdata/property/set.go.wasm")
83+
local plugin_ctx, err = wasm.on_configure(plugin, 'host|test.com')
84+
assert(wasm.on_http_request_headers(plugin_ctx))
85+
}
86+
}
87+
--- error_log
88+
variable "host" not changeable
89+
90+
91+
92+
=== TEST 5: set_property (non-existent variable)
93+
--- config
94+
location /t {
95+
content_by_lua_block {
96+
local wasm = require("resty.proxy-wasm")
97+
local plugin = wasm.load("plugin", "t/testdata/property/set.go.wasm")
98+
local plugin_ctx, err = wasm.on_configure(plugin, 'other|new_value')
99+
assert(wasm.on_http_request_headers(plugin_ctx))
100+
}
101+
}
102+
--- error_log
103+
variable "other" not found for writing
104+
error set property: error status returned by host: not found

t/testdata/property/set.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package main
2+
3+
import (
4+
"strings"
5+
6+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
7+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
8+
)
9+
10+
func main() {
11+
proxywasm.SetVMContext(&vmContext{})
12+
}
13+
14+
type vmContext struct {
15+
// Embed the default VM context here,
16+
// so that we don't need to reimplement all the methods.
17+
types.DefaultVMContext
18+
}
19+
20+
// Override types.DefaultVMContext.
21+
func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
22+
return &pluginContext{}
23+
}
24+
25+
type pluginContext struct {
26+
// Embed the default plugin context here,
27+
// so that we don't need to reimplement all the methods.
28+
types.DefaultPluginContext
29+
}
30+
31+
// Override types.DefaultPluginContext.
32+
func (*pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
33+
return &httpLifecycle{contextID: contextID}
34+
}
35+
36+
func (*pluginContext) OnPluginStart(pluginConfigurationSize int) types.OnPluginStartStatus {
37+
return true
38+
}
39+
40+
type httpLifecycle struct {
41+
// Embed the default http context here,
42+
// so that we don't need to reimplement all the methods.
43+
types.DefaultHttpContext
44+
contextID uint32
45+
}
46+
47+
func (ctx *httpLifecycle) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
48+
data, err := proxywasm.GetPluginConfiguration()
49+
if err != nil {
50+
proxywasm.LogErrorf("error reading plugin configuration: %v", err)
51+
return types.ActionContinue
52+
}
53+
54+
configure := strings.Split(string(data), "|")
55+
err = proxywasm.SetProperty([]string{configure[0]}, []byte(configure[1]))
56+
if err != nil {
57+
proxywasm.LogErrorf("error set property: %v", err)
58+
return types.ActionContinue
59+
}
60+
proxywasm.LogWarnf("set property success: %v = %v", configure[0], configure[1])
61+
return types.ActionContinue
62+
}

0 commit comments

Comments
 (0)