Skip to content

Commit 4bec622

Browse files
authored
feat: set response header (#31)
1 parent b3005e4 commit 4bec622

File tree

5 files changed

+160
-10
lines changed

5 files changed

+160
-10
lines changed

proxy_wasm_abi.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,21 @@ configuration separately because proxy-wasm-rust-sdk still uses it.
174174
- `i32 (proxy_result_t) call_result`
175175

176176

177+
### `proxy_add_map_value`
178+
179+
* params:
180+
- `i32 (proxy_map_type_t) map_type`
181+
- `i32 (const char*) key_data`
182+
- `i32 (size_t) key_size`
183+
- `i32 (const char*) value_data`
184+
- `i32 (size_t) value_size`
185+
* returns:
186+
- `i32 (proxy_result_t) call_result`
187+
188+
Add key (`key_data`, `key_size`) with the value (`value_data`, `value_size`) to a given map
189+
(`map_type`).
190+
191+
177192
## HTTP (L7) extensions
178193

179194
### `proxy_send_http_response`

src/http/ngx_http_wasm_api.c

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@
77
#include "ngx_http_wasm_map.h"
88

99

10+
#define FFI_NO_REQ_CTX -100
11+
#define FFI_BAD_CONTEXT -101
12+
13+
1014
static int (*set_resp_header) (ngx_http_request_t *r,
1115
const char *key_data, size_t key_len, int is_nil,
1216
const char *sval, size_t sval_len, ngx_str_t *mvals,
1317
size_t mvals_len, int override, char **errmsg);
1418

19+
static char *err_bad_ctx = "API disabled in the current context";
20+
static char *err_no_req_ctx = "no request ctx found";
21+
1522

1623
wasm_functype_t *
1724
ngx_http_wasm_host_api_func(const ngx_wasm_host_api_t *api)
@@ -107,6 +114,37 @@ ngx_http_wasm_copy_to_wasm(ngx_log_t *log, const u_char *data, int32_t len,
107114
}
108115

109116

117+
static ngx_int_t
118+
ngx_http_wasm_set_resp_header(ngx_http_request_t *r,
119+
const char *key, size_t key_len, int is_nil,
120+
const char *val, size_t val_len,
121+
int override)
122+
{
123+
char *errmsg = NULL;
124+
ngx_int_t rc;
125+
126+
rc = set_resp_header(r, key, key_len, is_nil, val, val_len, NULL, 0,
127+
override, &errmsg);
128+
if (rc != NGX_OK && rc != NGX_DECLINED) {
129+
if (rc == FFI_BAD_CONTEXT) {
130+
errmsg = err_bad_ctx;
131+
} else if (rc == FFI_NO_REQ_CTX) {
132+
errmsg = err_no_req_ctx;
133+
}
134+
135+
if (errmsg != NULL) {
136+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
137+
"faied to set header %*s to %*s: %s",
138+
key_len, key, val_len, val, errmsg);
139+
}
140+
141+
return NGX_ERROR;
142+
}
143+
144+
return NGX_OK;
145+
}
146+
147+
110148
int32_t
111149
proxy_get_property(int32_t path_data, int32_t path_size,
112150
int32_t res_data, int32_t res_size)
@@ -249,7 +287,6 @@ proxy_send_http_response(int32_t res_code,
249287
wmcf->body.len = body_size;
250288

251289
if (headers_size > 0) {
252-
char *errmsg = NULL;
253290
char *key, *val;
254291
int32_t key_len, val_len;
255292
ngx_int_t rc;
@@ -262,15 +299,8 @@ proxy_send_http_response(int32_t res_code,
262299

263300
ngx_http_wasm_map_init_iter(&it, p);
264301
while (ngx_http_wasm_map_next(&it, &key, &key_len, &val, &val_len)) {
265-
rc = set_resp_header(r, key, key_len, 0, val, val_len, NULL, 0,
266-
0, &errmsg);
267-
if (rc != NGX_OK && rc != NGX_DECLINED) {
268-
if (errmsg != NULL) {
269-
ngx_log_error(NGX_LOG_ERR, log, 0,
270-
"faied to set header %*s to %*s: %s",
271-
key_len, key, val_len, val, errmsg);
272-
}
273-
302+
rc = ngx_http_wasm_set_resp_header(r, key, key_len, 0, val, val_len, 0);
303+
if (rc != NGX_OK) {
274304
return PROXY_RESULT_BAD_ARGUMENT;
275305
}
276306
}
@@ -366,6 +396,34 @@ int32_t
366396
proxy_add_header_map_value(int32_t type, int32_t key_data, int32_t key_size,
367397
int32_t data, int32_t size)
368398
{
399+
ngx_int_t rc;
400+
ngx_log_t *log;
401+
ngx_http_request_t *r;
402+
char *key, *val;
403+
404+
log = ngx_http_wasm_get_log();
405+
r = ngx_http_wasm_get_req();
406+
if (r == NULL) {
407+
return PROXY_RESULT_BAD_ARGUMENT;
408+
}
409+
410+
key = (char *) ngx_wasm_vm.get_memory(log, key_data, key_size);
411+
if (key == NULL) {
412+
return PROXY_RESULT_INVALID_MEMORY_ACCESS;
413+
}
414+
415+
val = (char *) ngx_wasm_vm.get_memory(log, data, size);
416+
if (val == NULL) {
417+
return PROXY_RESULT_INVALID_MEMORY_ACCESS;
418+
}
419+
420+
if (type == PROXY_MAP_TYPE_HTTP_RESPONSE_HEADERS) {
421+
rc = ngx_http_wasm_set_resp_header(r, key, key_size, 0, val, size, 0);
422+
if (rc != NGX_OK) {
423+
return PROXY_RESULT_BAD_ARGUMENT;
424+
}
425+
}
426+
369427
return PROXY_RESULT_OK;
370428
}
371429

src/http/ngx_http_wasm_map.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@
44
#include <ngx_core.h>
55

66

7+
typedef enum {
8+
PROXY_MAP_TYPE_HTTP_REQUEST_HEADERS = 0,
9+
PROXY_MAP_TYPE_HTTP_REQUEST_TRAILERS = 1,
10+
PROXY_MAP_TYPE_HTTP_RESPONSE_HEADERS = 2,
11+
PROXY_MAP_TYPE_HTTP_RESPONSE_TRAILERS = 3,
12+
PROXY_MAP_TYPE_HTTP_CALL_RESPONSE_HEADERS = 6,
13+
PROXY_MAP_TYPE_HTTP_CALL_RESPONSE_TRAILERS = 7,
14+
} proxy_map_type_t;
15+
16+
717
typedef struct {
818
int32_t idx;
919
int32_t len;

t/http_header.t

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use t::WASM 'no_plan';
2+
3+
run_tests();
4+
5+
__DATA__
6+
7+
=== TEST 1: response header add
8+
--- config
9+
location /t {
10+
return 200;
11+
header_filter_by_lua_block {
12+
local wasm = require("resty.proxy-wasm")
13+
local plugin = assert(wasm.load("plugin", "t/testdata/http_header/main.go.wasm"))
14+
local ctx = assert(wasm.on_configure(plugin, 'resp_hdr_add'))
15+
assert(wasm.on_http_response_headers(ctx))
16+
}
17+
}
18+
--- response_headers
19+
add: foo, bar

t/testdata/http_header/main.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package main
2+
3+
import (
4+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
5+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
6+
)
7+
8+
func main() {
9+
proxywasm.SetVMContext(&vmContext{})
10+
}
11+
12+
type vmContext struct {
13+
types.DefaultVMContext
14+
}
15+
16+
func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
17+
return &pluginContext{}
18+
}
19+
20+
type pluginContext struct {
21+
types.DefaultPluginContext
22+
}
23+
24+
func (*pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
25+
return &httpContext{contextID: contextID}
26+
}
27+
28+
type httpContext struct {
29+
types.DefaultHttpContext
30+
contextID uint32
31+
}
32+
33+
func (ctx *httpContext) OnHttpResponseHeaders(numHeaders int, endOfStream bool) types.Action {
34+
data, err := proxywasm.GetPluginConfiguration()
35+
if err != nil {
36+
proxywasm.LogCriticalf("error reading plugin configuration: %v", err)
37+
return types.ActionContinue
38+
}
39+
40+
action := string(data)
41+
proxywasm.AddHttpResponseHeader("add", "foo")
42+
43+
if action == "resp_hdr_add" {
44+
proxywasm.AddHttpResponseHeader("add", "bar")
45+
}
46+
47+
return types.ActionContinue
48+
}

0 commit comments

Comments
 (0)