Skip to content

Commit 8c95d3b

Browse files
authored
feat: run http_request_headers filter (#14)
1 parent 02c60ad commit 8c95d3b

File tree

13 files changed

+244
-35
lines changed

13 files changed

+244
-35
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ if not ctx then
6363
end
6464
```
6565

66+
### on_http_request_headers
67+
68+
`syntax: ok, err = proxy_wasm.on_http_request_headers(plugin_ctx)`
69+
70+
Run the HTTP request headers filter in the plugin of the given plugin ctx.
71+
72+
```lua
73+
local plugin, err = proxy_wasm.load("t/testdata/plugin_lifecycle/main.go.wasm")
74+
if not plugin then
75+
ngx.log(ngx.ERR, "failed to load wasm ", err)
76+
return
77+
end
78+
local ctx, err = wasm.on_configure(plugin, '{"body":512}')
79+
if not ctx then
80+
ngx.log(ngx.ERR, "failed to create plugin ctx ", err)
81+
return
82+
end
83+
assert(wasm.on_http_request_headers(ctx))
84+
```
85+
6686
## proxy-wasm ABI
6787

6888
Implemented proxy-wasm ABI can be found in [proxy_wasm_abi](./proxy_wasm_abi.md).

proxy_wasm_abi.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,23 @@ Called when the host environment starts the plugin. Its configuration (`plugin_c
8787
might be retrieved using `proxy_get_buffer`.
8888

8989

90+
## HTTP (L7) extensions
91+
92+
### `proxy_on_request_headers`
93+
94+
* params:
95+
- `i32 (uint32_t) context_id`
96+
- `i32 (size_t) num_headers`
97+
- `i32 (bool) end_of_stream`
98+
* returns:
99+
- `i32 (proxy_action_t) next_action`
100+
101+
Called when HTTP request headers are received from the client. TODO: Headers can be retrieved using
102+
`proxy_get_map` and/or `proxy_get_map_value`.
103+
104+
TODO: pass a correct `num_headers` but not 0.
105+
106+
90107
# Functions implemented in the host environment
91108

92109
All functions implemented in the host environment return `proxy_result_t`, which indicates the

src/http/ngx_http_wasm_api.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,19 @@ proxy_set_effective_context(int32_t id)
4747
int32_t
4848
proxy_log(int32_t log_level, int32_t addr, int32_t size)
4949
{
50-
const u_char *p;
51-
ngx_uint_t host_log_level = NGX_LOG_ERR;
50+
const u_char *p;
51+
ngx_uint_t host_log_level = NGX_LOG_ERR;
52+
ngx_http_request_t *r;
53+
ngx_log_t *log;
54+
55+
r = ngx_http_wasm_get_req();
56+
if (r == NULL) {
57+
log = ngx_cycle->log;
58+
} else {
59+
log = r->connection->log;
60+
}
5261

53-
p = ngx_wasm_vm.get_memory(ngx_cycle->log, addr, size);
62+
p = ngx_wasm_vm.get_memory(log, addr, size);
5463
if (p == NULL) {
5564
return PROXY_RESULT_INVALID_MEMORY_ACCESS;
5665
}
@@ -81,7 +90,7 @@ proxy_log(int32_t log_level, int32_t addr, int32_t size)
8190
break;
8291
}
8392

84-
ngx_log_error(host_log_level, ngx_cycle->log, 0, "%*s", size, p);
93+
ngx_log_error(host_log_level, log, 0, "%*s", size, p);
8594

8695
return PROXY_RESULT_OK;
8796
}
@@ -100,8 +109,14 @@ proxy_get_buffer_bytes(int32_t type, int32_t start, int32_t length,
100109
u_char *buf;
101110

102111
const ngx_str_t *conf;
112+
ngx_http_request_t *r;
103113

104-
log = ngx_cycle->log;
114+
r = ngx_http_wasm_get_req();
115+
if (r == NULL) {
116+
log = ngx_cycle->log;
117+
} else {
118+
log = r->connection->log;
119+
}
105120

106121
switch (type) {
107122
case PROXY_BUFFER_TYPE_PLUGIN_CONFIGURATION:

src/http/ngx_http_wasm_ctx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ typedef struct {
3535

3636

3737
typedef struct {
38-
ngx_http_wasm_http_ctx_t *http_ctx;
38+
ngx_array_t *http_ctxs;
3939
} ngx_http_wasm_ctx_t;
4040

4141

src/http/ngx_http_wasm_module.c

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ static ngx_str_t proxy_on_context_create = ngx_string("proxy_on_context_create")
2020
static ngx_str_t proxy_on_configure = ngx_string("proxy_on_configure");
2121
static ngx_str_t proxy_on_done = ngx_string("proxy_on_done");
2222
static ngx_str_t proxy_on_delete = ngx_string("proxy_on_delete");
23+
static ngx_str_t proxy_on_request_headers =
24+
ngx_string("proxy_on_request_headers");
2325

2426

2527
typedef struct {
@@ -348,6 +350,7 @@ ngx_http_wasm_on_configure(ngx_http_wasm_plugin_t *hw_plugin, const char *conf,
348350
if (hwp_ctx->state == NULL) {
349351
goto free_hwp_ctx;
350352
}
353+
hwp_ctx->state->r = NULL;
351354

352355
state_conf = (u_char *) (hwp_ctx->state + 1);
353356
/* copy conf so we can access it anytime */
@@ -360,6 +363,9 @@ ngx_http_wasm_on_configure(ngx_http_wasm_plugin_t *hw_plugin, const char *conf,
360363

361364
rc = ngx_wasm_vm.call(plugin, &proxy_on_configure, true,
362365
NGX_WASM_PARAM_I32_I32, ctx_id, size);
366+
367+
ngx_http_wasm_set_state(NULL);
368+
363369
if (rc <= 0) {
364370
ngx_log_error(NGX_LOG_ERR, log, 0, "failed to configure plugin context %d, rc: %d",
365371
ctx_id, rc);
@@ -431,42 +437,47 @@ static void
431437
ngx_http_wasm_cleanup(void *data)
432438
{
433439
ngx_int_t rc;
440+
ngx_uint_t i;
434441
ngx_http_wasm_ctx_t *ctx = data;
435-
ngx_http_wasm_http_ctx_t *http_ctx = ctx->http_ctx;
442+
ngx_array_t *http_ctxs = ctx->http_ctxs;
436443
uint32_t ctx_id;
444+
ngx_http_wasm_http_ctx_t *http_ctx;
437445
ngx_http_wasm_plugin_ctx_t *hwp_ctx;
438446
void *plugin;
439447
ngx_log_t *log;
440448

441449
log = ngx_cycle->log;
442450

443-
if (http_ctx == NULL) {
451+
if (http_ctxs == NULL) {
444452
return;
445453
}
446454

447-
ctx_id = http_ctx->id;
448-
hwp_ctx = http_ctx->hwp_ctx;
449-
plugin = hwp_ctx->hw_plugin->plugin;
455+
for (i = 0; i < http_ctxs->nelts; i++) {
456+
http_ctx = ((ngx_http_wasm_http_ctx_t **) http_ctxs->elts)[i];
457+
ctx_id = http_ctx->id;
458+
hwp_ctx = http_ctx->hwp_ctx;
459+
plugin = hwp_ctx->hw_plugin->plugin;
450460

451-
ngx_queue_remove(&http_ctx->queue);
452-
ngx_queue_insert_head(&hwp_ctx->free, &http_ctx->queue);
461+
ngx_queue_remove(&http_ctx->queue);
462+
ngx_queue_insert_head(&hwp_ctx->free, &http_ctx->queue);
453463

454-
rc = ngx_wasm_vm.call(plugin, &proxy_on_done, true, NGX_WASM_PARAM_I32, ctx_id);
455-
if (rc <= 0) {
456-
ngx_log_error(NGX_LOG_ERR, log, 0, "failed to mark context %d as done, rc: %d",
457-
ctx_id, rc);
458-
}
464+
rc = ngx_wasm_vm.call(plugin, &proxy_on_done, true, NGX_WASM_PARAM_I32, ctx_id);
465+
if (rc <= 0) {
466+
ngx_log_error(NGX_LOG_ERR, log, 0, "failed to mark context %d as done, rc: %d",
467+
ctx_id, rc);
468+
}
459469

460-
rc = ngx_wasm_vm.call(plugin, &proxy_on_delete, false, NGX_WASM_PARAM_I32, ctx_id);
461-
if (rc != NGX_OK) {
462-
ngx_log_error(NGX_LOG_ERR, log, 0, "failed to delete context %d, rc: %d",
463-
ctx_id, rc);
464-
}
470+
rc = ngx_wasm_vm.call(plugin, &proxy_on_delete, false, NGX_WASM_PARAM_I32, ctx_id);
471+
if (rc != NGX_OK) {
472+
ngx_log_error(NGX_LOG_ERR, log, 0, "failed to delete context %d, rc: %d",
473+
ctx_id, rc);
474+
}
465475

466-
ngx_log_error(NGX_LOG_INFO, log, 0, "free http context %d", ctx_id);
476+
ngx_log_error(NGX_LOG_INFO, log, 0, "free http context %d", ctx_id);
467477

468-
if (hwp_ctx->done) {
469-
ngx_http_wasm_free_plugin_ctx(hwp_ctx);
478+
if (hwp_ctx->done) {
479+
ngx_http_wasm_free_plugin_ctx(hwp_ctx);
480+
}
470481
}
471482
}
472483

@@ -505,19 +516,41 @@ ngx_http_wasm_get_module_ctx(ngx_http_request_t *r)
505516
ngx_http_wasm_http_ctx_t *
506517
ngx_http_wasm_fetch_http_ctx(ngx_http_wasm_plugin_ctx_t *hwp_ctx, ngx_http_request_t *r)
507518
{
519+
ngx_uint_t i;
508520
ngx_http_wasm_ctx_t *ctx;
521+
ngx_http_wasm_http_ctx_t *http_ctx;
522+
ngx_http_wasm_http_ctx_t **p;
509523

510524

511525
ctx = ngx_http_wasm_get_module_ctx(r);
512526
if (ctx == NULL) {
513527
return NULL;
514528
}
515529

516-
if (ctx->http_ctx == NULL) {
517-
ctx->http_ctx = ngx_http_wasm_create_http_ctx(hwp_ctx, r);
530+
if (ctx->http_ctxs == NULL) {
531+
ctx->http_ctxs = ngx_array_create(r->pool, 1, sizeof(ngx_http_wasm_ctx_t *));
532+
if (ctx->http_ctxs == NULL) {
533+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no memory");
534+
return NULL;
535+
}
518536
}
519537

520-
return ctx->http_ctx;
538+
p = ctx->http_ctxs->elts;
539+
540+
for (i = 0; i < ctx->http_ctxs->nelts; i++) {
541+
if (p[i]->hwp_ctx == hwp_ctx) {
542+
return p[i];
543+
}
544+
}
545+
546+
http_ctx = ngx_http_wasm_create_http_ctx(hwp_ctx, r);
547+
if (http_ctx == NULL) {
548+
return NULL;
549+
}
550+
551+
p = ngx_array_push(ctx->http_ctxs);
552+
*p = http_ctx;
553+
return http_ctx;
521554
}
522555

523556

@@ -536,12 +569,19 @@ ngx_http_wasm_on_http(ngx_http_wasm_plugin_ctx_t *hwp_ctx, ngx_http_request_t *r
536569
return NGX_DECLINED;
537570
}
538571

539-
rc = NGX_OK;
572+
hwp_ctx->state->r = r;
573+
ngx_http_wasm_set_state(hwp_ctx->state);
540574

541575
http_ctx = ngx_http_wasm_fetch_http_ctx(hwp_ctx, r);
542576
if (http_ctx == NULL) {
577+
ngx_http_wasm_set_state(NULL);
543578
return NGX_DECLINED;
544579
}
545580

581+
rc = ngx_wasm_vm.call(hwp_ctx->hw_plugin->plugin,
582+
&proxy_on_request_headers,
583+
true, NGX_WASM_PARAM_I32_I32_I32, http_ctx->id,
584+
0, 1);
585+
ngx_http_wasm_set_state(NULL);
546586
return rc;
547587
}

src/http/ngx_http_wasm_state.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "ngx_http_wasm_state.h"
22

33

4-
static ngx_http_wasm_state_t *cur_state;
4+
static ngx_http_wasm_state_t *cur_state = NULL;
55

66

77
void
@@ -14,5 +14,20 @@ ngx_http_wasm_set_state(ngx_http_wasm_state_t *state)
1414
const ngx_str_t *
1515
ngx_http_wasm_get_conf(void)
1616
{
17+
if (cur_state == NULL) {
18+
return NULL;
19+
}
20+
1721
return &cur_state->conf;
1822
}
23+
24+
25+
ngx_http_request_t *
26+
ngx_http_wasm_get_req(void)
27+
{
28+
if (cur_state == NULL) {
29+
return NULL;
30+
}
31+
32+
return cur_state->r;
33+
}

src/http/ngx_http_wasm_state.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@
33

44

55
#include <ngx_core.h>
6+
#include <ngx_http.h>
67

78

89
typedef struct {
9-
ngx_str_t conf;
10+
ngx_str_t conf;
11+
ngx_http_request_t *r;
1012
} ngx_http_wasm_state_t;
1113

1214

1315
void ngx_http_wasm_set_state(ngx_http_wasm_state_t *state);
1416
const ngx_str_t *ngx_http_wasm_get_conf(void);
17+
ngx_http_request_t *ngx_http_wasm_get_req(void);
1518

1619

1720
#endif // NGX_HTTP_WASM_STATE_H

src/vm/vm.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
#include <ngx_core.h>
77

88

9-
#define NGX_WASM_PARAM_VOID 1
10-
#define NGX_WASM_PARAM_I32 2
11-
#define NGX_WASM_PARAM_I32_I32 3
9+
#define NGX_WASM_PARAM_VOID 1
10+
#define NGX_WASM_PARAM_I32 2
11+
#define NGX_WASM_PARAM_I32_I32 3
12+
#define NGX_WASM_PARAM_I32_I32_I32 4
1213

1314

1415
typedef struct {

src/vm/wasmtime.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ static ngx_str_t vm_name = ngx_string("wasmtime");
1919
static wasm_engine_t *vm_engine;
2020
static wasmtime_val_t param_int32[1] = {{ .kind = WASMTIME_I32 }};
2121
static wasmtime_val_t param_int32_int32[2] = {{ .kind = WASMTIME_I32 }, { .kind = WASMTIME_I32 }};
22+
static wasmtime_val_t param_int32_int32_int32[3] = {
23+
{ .kind = WASMTIME_I32 }, { .kind = WASMTIME_I32 }, { .kind = WASMTIME_I32 }
24+
};
2225
static ngx_wasm_wasmtime_plugin_t *cur_plugin;
2326

2427

@@ -242,6 +245,14 @@ ngx_wasm_wasmtime_call(void *data, ngx_str_t *name, bool has_result, int param_t
242245
param_num = 2;
243246
break;
244247

248+
case NGX_WASM_PARAM_I32_I32_I32:
249+
params = param_int32_int32_int32;
250+
params[0].of.i32 = va_arg(args, int32_t);
251+
params[1].of.i32 = va_arg(args, int32_t);
252+
params[2].of.i32 = va_arg(args, int32_t);
253+
param_num = 3;
254+
break;
255+
245256
default:
246257
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "unknown param type: %d", param_type);
247258
return NGX_ERROR;

0 commit comments

Comments
 (0)