Skip to content

Commit 5c72ab1

Browse files
authored
feat: support getting request body (#90)
1 parent 8bdfff3 commit 5c72ab1

File tree

9 files changed

+387
-22
lines changed

9 files changed

+387
-22
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,30 @@ end
9999
assert(wasm.on_http_request_headers(ctx))
100100
```
101101

102+
### on_http_request_body
103+
104+
`syntax: ok, err = proxy_wasm.on_http_request_body(plugin_ctx, body, end_of_body)`
105+
106+
Run the HTTP request body filter in the plugin of the given plugin ctx.
107+
108+
```lua
109+
local plugin, err = proxy_wasm.load("plugin","t/testdata/plugin_lifecycle/main.go.wasm")
110+
if not plugin then
111+
ngx.log(ngx.ERR, "failed to load wasm ", err)
112+
return
113+
end
114+
local ctx, err = wasm.on_configure(plugin, '{"body":512}')
115+
if not ctx then
116+
ngx.log(ngx.ERR, "failed to create plugin ctx ", err)
117+
return
118+
end
119+
-- get_body is a utility method to get the whole request body
120+
local body = request.get_body()
121+
-- if the body is not the whole request body, for example, it comes from
122+
-- lua-resty-upload, remember to set end_of_body to false
123+
assert(wasm.on_http_request_body(ctx, body, true))
124+
```
125+
102126
### on_http_response_headers
103127

104128
`syntax: ok, err = proxy_wasm.on_http_response_headers(plugin_ctx)`

lib/resty/proxy-wasm.lua

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ void ngx_http_wasm_unload_plugin(void *plugin);
4747
void *ngx_http_wasm_on_configure(void *plugin, const char *conf, size_t size);
4848
void ngx_http_wasm_delete_plugin_ctx(void *hwp_ctx);
4949

50-
ngx_int_t ngx_http_wasm_on_http(void *hwp_ctx, void *r, int type);
50+
ngx_int_t ngx_http_wasm_on_http(void *hwp_ctx, void *r, int type,
51+
const u_char *body, size_t size, int end_of_body);
5152
ngx_str_t *ngx_http_wasm_fetch_local_body(void *r);
5253

5354
ngx_int_t ngx_http_wasm_call_max_headers_count(void *r);
@@ -65,7 +66,7 @@ local ngx_table_size = ffi.sizeof("proxy_wasm_table_elt_t")
6566

6667
local _M = {}
6768
local HTTP_REQUEST_HEADERS = 1
68-
--local HTTP_REQUEST_BODY = 2
69+
local HTTP_REQUEST_BODY = 2
6970
local HTTP_RESPONSE_HEADERS = 4
7071
--local HTTP_RESPONSE_BODY = 8
7172

@@ -258,7 +259,7 @@ local function handle_http_callback(plugin_ctx, r, res)
258259
end
259260

260261

261-
function _M.on_http_request_headers(plugin_ctx)
262+
local function on_http_request(plugin_ctx, ty, body, end_of_body)
262263
if type(plugin_ctx) ~= "cdata" then
263264
return nil, "bad plugin ctx"
264265
end
@@ -268,9 +269,23 @@ function _M.on_http_request_headers(plugin_ctx)
268269
return nil, "bad request"
269270
end
270271

271-
local rc = C.ngx_http_wasm_on_http(plugin_ctx, r, HTTP_REQUEST_HEADERS)
272+
local err
273+
if ty == HTTP_REQUEST_HEADERS then
274+
err = "failed to run proxy_on_http_request_headers"
275+
else
276+
err = "failed to run proxy_on_http_request_body"
277+
end
278+
279+
local body_size
280+
if not body then
281+
body_size = 0
282+
else
283+
body_size = #body
284+
end
285+
286+
local rc = C.ngx_http_wasm_on_http(plugin_ctx, r, ty, body, body_size, end_of_body)
272287
if rc < 0 then
273-
return nil, "failed to run proxy_on_http_request_headers"
288+
return nil, err
274289
end
275290

276291
while true do
@@ -304,6 +319,16 @@ function _M.on_http_request_headers(plugin_ctx)
304319
end
305320

306321

322+
function _M.on_http_request_headers(plugin_ctx)
323+
return on_http_request(plugin_ctx, HTTP_REQUEST_HEADERS, nil, 1)
324+
end
325+
326+
327+
function _M.on_http_request_body(plugin_ctx, body, end_of_body)
328+
return on_http_request(plugin_ctx, HTTP_REQUEST_BODY, body, end_of_body and 1 or 0)
329+
end
330+
331+
307332
function _M.on_http_response_headers(plugin_ctx)
308333
if type(plugin_ctx) ~= "cdata" then
309334
return nil, "bad plugin ctx"
@@ -314,7 +339,7 @@ function _M.on_http_response_headers(plugin_ctx)
314339
return nil, "bad request"
315340
end
316341

317-
local rc = C.ngx_http_wasm_on_http(plugin_ctx, r, HTTP_RESPONSE_HEADERS)
342+
local rc = C.ngx_http_wasm_on_http(plugin_ctx, r, HTTP_RESPONSE_HEADERS, nil, 0, 1)
318343
if rc < 0 then
319344
return nil, "failed to run proxy_on_http_response_headers"
320345
end

proxy_wasm_abi.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,22 @@ might be retrieved using `proxy_get_buffer`.
115115
* returns:
116116
- `i32 (proxy_action_t) next_action`
117117

118-
Called when HTTP request headers are received from the client. TODO: Headers can be retrieved using
119-
`proxy_get_map` and/or `proxy_get_map_value`.
118+
Called when HTTP request headers are received from the client.
120119

121120
TODO: pass a correct `num_headers` but not 0.
122121

122+
### `proxy_on_request_body`
123+
124+
* params:
125+
- `i32 (uint32_t) context_id`
126+
- `i32 (size_t) body_size`
127+
- `i32 (bool) end_of_stream`
128+
* returns:
129+
- `i32 (proxy_action_t) next_action`
130+
131+
Called for HTTP request body received from the client. Request body can be retrieved
132+
using `proxy_get_buffer_bytes`.
133+
123134
### `proxy_on_response_headers`
124135

125136
* params:
@@ -129,8 +140,7 @@ TODO: pass a correct `num_headers` but not 0.
129140
* returns:
130141
- `i32 (proxy_action_t) next_action`
131142

132-
Called when HTTP response headers are received from the upstream. TODO: Headers can be retrieved using
133-
`proxy_get_map` and/or `proxy_get_map_value`.
143+
Called when HTTP response headers are received from the upstream.
134144

135145
TODO: pass a correct `num_headers` but not 0.
136146

src/http/ngx_http_wasm_api.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,9 @@ proxy_get_buffer_bytes(int32_t type, int32_t start, int32_t size,
495495
int32_t addr, int32_t size_addr)
496496
{
497497
ngx_log_t *log;
498-
const u_char *data;
499-
int32_t len;
500-
const ngx_str_t *conf;
498+
const u_char *data = NULL;
499+
int32_t len = 0;
500+
const ngx_str_t *buffer;
501501

502502
ngx_http_request_t *r;
503503
ngx_http_wasm_ctx_t *ctx;
@@ -506,9 +506,19 @@ proxy_get_buffer_bytes(int32_t type, int32_t start, int32_t size,
506506

507507
switch (type) {
508508
case PROXY_BUFFER_TYPE_PLUGIN_CONFIGURATION:
509-
conf = ngx_http_wasm_get_conf();
510-
data = conf->data;
511-
len = conf->len;
509+
buffer = ngx_http_wasm_get_conf();
510+
if (buffer != NULL) {
511+
data = buffer->data;
512+
len = buffer->len;
513+
}
514+
break;
515+
516+
case PROXY_BUFFER_TYPE_HTTP_REQUEST_BODY:
517+
buffer = ngx_http_wasm_get_body();
518+
if (buffer != NULL) {
519+
data = buffer->data;
520+
len = buffer->len;
521+
}
512522
break;
513523

514524
case PROXY_BUFFER_TYPE_HTTP_CALL_RESPONSE_BODY:

src/http/ngx_http_wasm_module.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ static ngx_str_t proxy_on_done = ngx_string("proxy_on_done");
4646
static ngx_str_t proxy_on_delete = ngx_string("proxy_on_delete");
4747
static ngx_str_t proxy_on_request_headers =
4848
ngx_string("proxy_on_request_headers");
49+
static ngx_str_t proxy_on_request_body =
50+
ngx_string("proxy_on_request_body");
4951
static ngx_str_t proxy_on_response_headers =
5052
ngx_string("proxy_on_response_headers");
5153
static ngx_str_t proxy_on_http_call_response =
@@ -647,7 +649,8 @@ ngx_http_wasm_handle_rc_before_proxy(ngx_http_wasm_main_conf_t *wmcf,
647649

648650
ngx_int_t
649651
ngx_http_wasm_on_http(ngx_http_wasm_plugin_ctx_t *hwp_ctx, ngx_http_request_t *r,
650-
ngx_http_wasm_phase_t type)
652+
ngx_http_wasm_phase_t type, const u_char *body, size_t size,
653+
int end_of_body)
651654
{
652655
ngx_int_t rc;
653656
ngx_log_t *log;
@@ -665,6 +668,12 @@ ngx_http_wasm_on_http(ngx_http_wasm_plugin_ctx_t *hwp_ctx, ngx_http_request_t *r
665668

666669
wmcf = ngx_http_get_module_main_conf(r, ngx_http_wasm_module);
667670
hwp_ctx->state->r = r;
671+
672+
if (body != NULL) {
673+
hwp_ctx->state->body.data = (u_char *) body;
674+
hwp_ctx->state->body.len = size;
675+
}
676+
668677
ngx_http_wasm_set_state(hwp_ctx->state);
669678

670679
http_ctx = ngx_http_wasm_fetch_http_ctx(hwp_ctx, r);
@@ -677,19 +686,29 @@ ngx_http_wasm_on_http(ngx_http_wasm_plugin_ctx_t *hwp_ctx, ngx_http_request_t *r
677686

678687
if (type == HTTP_RESPONSE_HEADERS) {
679688
cb_name = &proxy_on_response_headers;
689+
} else if (type == HTTP_REQUEST_BODY) {
690+
cb_name = &proxy_on_request_body;
680691
} else {
681692
cb_name = &proxy_on_request_headers;
682693
}
683694

684-
if (hwp_ctx->hw_plugin->abi_version == PROXY_WASM_ABI_VER_010) {
685-
rc = ngx_wasm_vm.call(hwp_ctx->hw_plugin->plugin,
686-
cb_name,
687-
true, NGX_WASM_PARAM_I32_I32, http_ctx->id, 0);
695+
if (type == HTTP_REQUEST_HEADERS || type == HTTP_RESPONSE_HEADERS) {
696+
if (hwp_ctx->hw_plugin->abi_version == PROXY_WASM_ABI_VER_010) {
697+
rc = ngx_wasm_vm.call(hwp_ctx->hw_plugin->plugin,
698+
cb_name,
699+
true, NGX_WASM_PARAM_I32_I32, http_ctx->id, 0);
700+
} else {
701+
rc = ngx_wasm_vm.call(hwp_ctx->hw_plugin->plugin,
702+
cb_name,
703+
true, NGX_WASM_PARAM_I32_I32_I32, http_ctx->id,
704+
0, 1);
705+
}
706+
688707
} else {
689708
rc = ngx_wasm_vm.call(hwp_ctx->hw_plugin->plugin,
690709
cb_name,
691710
true, NGX_WASM_PARAM_I32_I32_I32, http_ctx->id,
692-
0, 1);
711+
size, end_of_body);
693712
}
694713

695714
ngx_http_wasm_set_state(NULL);

src/http/ngx_http_wasm_state.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ static ngx_http_wasm_state_t *cur_state = NULL;
2323
void
2424
ngx_http_wasm_set_state(ngx_http_wasm_state_t *state)
2525
{
26+
if (state == NULL) {
27+
/* clear state data */
28+
cur_state->body.data = NULL;
29+
cur_state->body.len = 0;
30+
}
31+
2632
cur_state = state;
2733
}
2834

@@ -69,3 +75,14 @@ ngx_http_wasm_get_plugin_name(void)
6975

7076
return cur_state->plugin_name;
7177
}
78+
79+
80+
const ngx_str_t *
81+
ngx_http_wasm_get_body(void)
82+
{
83+
if (cur_state == NULL) {
84+
return NULL;
85+
}
86+
87+
return &cur_state->body;
88+
}

src/http/ngx_http_wasm_state.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
typedef struct {
2626
ngx_str_t conf;
27+
ngx_str_t body;
2728
ngx_http_request_t *r;
2829
ngx_str_t *plugin_name;
2930
} ngx_http_wasm_state_t;
@@ -34,6 +35,7 @@ const ngx_str_t *ngx_http_wasm_get_conf(void);
3435
ngx_http_request_t *ngx_http_wasm_get_req(void);
3536
ngx_log_t *ngx_http_wasm_get_log(void);
3637
ngx_str_t *ngx_http_wasm_get_plugin_name(void);
38+
const ngx_str_t *ngx_http_wasm_get_body(void);
3739

3840

3941
#endif // NGX_HTTP_WASM_STATE_H

0 commit comments

Comments
 (0)