Skip to content

Commit 6d6d765

Browse files
authored
feat: support headers in proxy_send_http_response (#29)
1 parent 004174e commit 6d6d765

File tree

8 files changed

+151
-1
lines changed

8 files changed

+151
-1
lines changed

config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ngx_module_srcs=" \
44
$ngx_addon_dir/src/http/ngx_http_wasm_module.c \
55
$ngx_addon_dir/src/http/ngx_http_wasm_api.c \
66
$ngx_addon_dir/src/http/ngx_http_wasm_state.c \
7+
$ngx_addon_dir/src/http/ngx_http_wasm_map.c \
78
$ngx_addon_dir/src/vm/wasmtime.c \
89
$ngx_addon_dir/src/vm/vm.c \
910
"

src/http/ngx_http_wasm_api.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1+
#define _GNU_SOURCE /* for RTLD_DEFAULT */
2+
#include <dlfcn.h>
13
#include "vm/vm.h"
24
#include "ngx_http_wasm_api.h"
35
#include "ngx_http_wasm_module.h"
46
#include "ngx_http_wasm_state.h"
7+
#include "ngx_http_wasm_map.h"
8+
9+
10+
static int (*set_resp_header) (ngx_http_request_t *r,
11+
const char *key_data, size_t key_len, int is_nil,
12+
const char *sval, size_t sval_len, ngx_str_t *mvals,
13+
size_t mvals_len, int override, char **errmsg);
514

615

716
wasm_functype_t *
@@ -33,6 +42,25 @@ ngx_http_wasm_host_api_func(const ngx_wasm_host_api_t *api)
3342
}
3443

3544

45+
ngx_int_t
46+
ngx_http_wasm_resolve_symbol(void)
47+
{
48+
char *err;
49+
50+
dlerror(); /* Clear any existing error */
51+
52+
set_resp_header = dlsym(RTLD_DEFAULT, "ngx_http_lua_ffi_set_resp_header");
53+
err = dlerror();
54+
if (err != NULL) {
55+
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
56+
"failed to resolve symbol: %s", err);
57+
return NGX_ERROR;
58+
}
59+
60+
return NGX_OK;
61+
}
62+
63+
3664
int32_t
3765
proxy_set_effective_context(int32_t id)
3866
{
@@ -217,10 +245,37 @@ proxy_send_http_response(int32_t res_code,
217245
log = r->connection->log;
218246

219247
wmcf = ngx_http_get_module_main_conf(r, ngx_http_wasm_module);
220-
/* TODO handle other args */
221248
wmcf->code = res_code;
222249
wmcf->body.len = body_size;
223250

251+
if (headers_size > 0) {
252+
char *errmsg = NULL;
253+
char *key, *val;
254+
int32_t key_len, val_len;
255+
ngx_int_t rc;
256+
proxy_wasm_map_iter it;
257+
258+
p = ngx_wasm_vm.get_memory(log, headers, headers_size);
259+
if (p == NULL) {
260+
return PROXY_RESULT_INVALID_MEMORY_ACCESS;
261+
}
262+
263+
ngx_http_wasm_map_init_iter(&it, p);
264+
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+
274+
return PROXY_RESULT_BAD_ARGUMENT;
275+
}
276+
}
277+
}
278+
224279
if (body_size > 0) {
225280
p = ngx_wasm_vm.get_memory(log, body, body_size);
226281
if (p == NULL) {

src/http/ngx_http_wasm_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ static ngx_wasm_host_api_t host_apis[] = {
336336

337337

338338
wasm_functype_t *ngx_http_wasm_host_api_func(const ngx_wasm_host_api_t *api);
339+
ngx_int_t ngx_http_wasm_resolve_symbol(void);
339340

340341

341342
#endif // NGX_HTTP_WASM_API_H

src/http/ngx_http_wasm_map.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "ngx_http_wasm_map.h"
2+
3+
4+
/**
5+
* the format of proxy_map_t is:
6+
* number of items (4 bytes) +
7+
* len of key1 + len of val1 + len of key2 + ... (4 bytes for each len)
8+
* data of key1 + \0 + data of val1 + data of key2 + ...
9+
*/
10+
11+
12+
void
13+
ngx_http_wasm_map_init_iter(proxy_wasm_map_iter *it, const u_char *map_data)
14+
{
15+
it->idx = 0;
16+
it->len = *(int32_t *) map_data;
17+
it->size_ptr = (int32_t *) (map_data) + 1;
18+
it->data_ptr = (char *) (it->size_ptr + 2 * it->len);
19+
}
20+
21+
22+
bool
23+
ngx_http_wasm_map_next(proxy_wasm_map_iter *it, char **key, int32_t *key_len,
24+
char **val, int32_t *val_len)
25+
{
26+
if (it->idx == it->len) {
27+
return false;
28+
}
29+
30+
*key_len = *it->size_ptr;
31+
it->size_ptr++;
32+
*val_len = *it->size_ptr;
33+
it->size_ptr++;
34+
35+
*key = it->data_ptr;
36+
it->data_ptr += *key_len + 1;
37+
*val = it->data_ptr;
38+
it->data_ptr += *val_len + 1;
39+
40+
it->idx++;
41+
return true;
42+
}

src/http/ngx_http_wasm_map.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef NGX_HTTP_WASM_MAP_H
2+
#define NGX_HTTP_WASM_MAP_H
3+
#include <stdbool.h>
4+
#include <ngx_core.h>
5+
6+
7+
typedef struct {
8+
int32_t idx;
9+
int32_t len;
10+
int32_t *size_ptr;
11+
char *data_ptr;
12+
} proxy_wasm_map_iter;
13+
14+
15+
void ngx_http_wasm_map_init_iter(proxy_wasm_map_iter *it, const u_char *map_data);
16+
bool ngx_http_wasm_map_next(proxy_wasm_map_iter *it, char **key, int32_t *key_len,
17+
char **val, int32_t *val_len);
18+
19+
20+
#endif // NGX_HTTP_WASM_MAP_H

src/http/ngx_http_wasm_module.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <ngx_config.h>
22
#include <ngx_core.h>
33
#include <ngx_http.h>
4+
#include "ngx_http_wasm_api.h"
45
#include "ngx_http_wasm_module.h"
56
#include "ngx_http_wasm_state.h"
67
#include "ngx_http_wasm_ctx.h"
@@ -141,6 +142,11 @@ ngx_http_wasm_init(ngx_conf_t *cf)
141142
return NGX_OK;
142143
}
143144

145+
rc = ngx_http_wasm_resolve_symbol();
146+
if (rc != NGX_OK) {
147+
return rc;
148+
}
149+
144150
wmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_wasm_module);
145151
if (wmcf->vm.len == 0) {
146152
return NGX_OK;

t/http_send_response.t

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ location /t {
1717
--- error_code: 403
1818
--- response_body chomp
1919
should not pass
20+
--- response_headers
21+
powered-by: proxy-wasm-go-sdk!!
2022

2123

2224

@@ -36,3 +38,20 @@ location /t {
3638
--- error_code: 502
3739
--- response_body_like eval
3840
qr/<title>502 Bad Gateway<\/title>/
41+
42+
43+
44+
=== TEST 3: multi headers
45+
--- config
46+
location /t {
47+
content_by_lua_block {
48+
local wasm = require("resty.proxy-wasm")
49+
local plugin = assert(wasm.load("plugin", "t/testdata/http_send_response/main.go.wasm"))
50+
local ctx = assert(wasm.on_configure(plugin, 'multi_hdrs'))
51+
assert(wasm.on_http_request_headers(ctx))
52+
}
53+
}
54+
--- error_code: 401
55+
--- response_headers
56+
hi: spacewander
57+
hello: spacewander, world

t/testdata/http_send_response/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ func (ctx *httpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) t
5555
}, []byte(body), -1)
5656
} else if action == "502" {
5757
err = proxywasm.SendHttpResponse(502, nil, nil, -1)
58+
} else if action == "multi_hdrs" {
59+
err = proxywasm.SendHttpResponse(401, [][2]string{
60+
{"hello", "spacewander"},
61+
{"hi", "spacewander"},
62+
{"hello", "world"},
63+
}, nil, -1)
5864
}
5965

6066
if err != nil {

0 commit comments

Comments
 (0)