From 78ff6460fde8225c0eeec806d9f287991253d18c Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Wed, 8 Nov 2023 18:35:38 -0800 Subject: [PATCH] feat(proxy-wasm) strengthen host functions context checks --- Cargo.lock | 8 + Cargo.toml | 1 + src/common/proxy_wasm/ngx_proxy_wasm.c | 33 ++- src/common/proxy_wasm/ngx_proxy_wasm_host.c | 150 ++++++++++-- .../proxy_wasm/ngx_http_proxy_wasm_dispatch.c | 12 +- t/03-proxy_wasm/hfuncs/100-proxy_log.t | 45 +--- .../hfuncs/101-proxy_get_current_time.t | 4 +- .../hfuncs/114-proxy_set_http_request_body.t | 58 ----- .../hfuncs/116-proxy_set_http_response_body.t | 57 ----- .../hfuncs/130-proxy_dispatch_http.t | 36 +-- .../hfuncs/contexts/002-set_tick_period.t | 184 +++++++++++++++ .../hfuncs/contexts/100-proxy_log.t | 191 ++++++++++++++++ .../113-proxy_get_http_request_body.t | 190 ++++++++++++++++ .../114-proxy_set_http_request_body.t | 186 +++++++++++++++ .../115-proxy_get_http_response_body.t | 189 ++++++++++++++++ .../116-proxy_set_http_response_body.t | 189 ++++++++++++++++ .../hfuncs/contexts/130-proxy_dispatch_http.t | 175 ++++++++++++++ ...31-proxy_get_http_dispatch_response_body.t | 29 +++ .../ffi/200-proxy_wasm_and_lua_sanity.t | 6 +- t/05-others/010-client_connection_abort.t | 7 +- t/05-others/011-upstream_connection_abort.t | 8 +- t/TestWasm.pm | 7 + .../context-checks/Cargo.toml | 12 + .../context-checks/src/hostcalls.rs | 178 +++++++++++++++ .../context-checks/src/lib.rs | 213 ++++++++++++++++++ 25 files changed, 1922 insertions(+), 246 deletions(-) create mode 100644 t/03-proxy_wasm/hfuncs/contexts/002-set_tick_period.t create mode 100644 t/03-proxy_wasm/hfuncs/contexts/100-proxy_log.t create mode 100644 t/03-proxy_wasm/hfuncs/contexts/113-proxy_get_http_request_body.t create mode 100644 t/03-proxy_wasm/hfuncs/contexts/114-proxy_set_http_request_body.t create mode 100644 t/03-proxy_wasm/hfuncs/contexts/115-proxy_get_http_response_body.t create mode 100644 t/03-proxy_wasm/hfuncs/contexts/116-proxy_set_http_response_body.t create mode 100644 t/03-proxy_wasm/hfuncs/contexts/130-proxy_dispatch_http.t create mode 100644 t/03-proxy_wasm/hfuncs/contexts/131-proxy_get_http_dispatch_response_body.t create mode 100644 t/lib/proxy-wasm-tests/context-checks/Cargo.toml create mode 100644 t/lib/proxy-wasm-tests/context-checks/src/hostcalls.rs create mode 100644 t/lib/proxy-wasm-tests/context-checks/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index c2077db5b..3c66063c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,6 +168,14 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "context-checks" +version = "0.1.0" +dependencies = [ + "log", + "proxy-wasm 0.2.1", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" diff --git a/Cargo.toml b/Cargo.toml index 0aa52f776..e005eb0ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "t/lib/proxy-wasm-tests/rust-sdk-ver-zero-one", "t/lib/proxy-wasm-tests/benchmarks", "t/lib/proxy-wasm-tests/instance-lifecycle", + "t/lib/proxy-wasm-tests/context-checks", ] exclude = [ "lib/ngx-wasm-rs", diff --git a/src/common/proxy_wasm/ngx_proxy_wasm.c b/src/common/proxy_wasm/ngx_proxy_wasm.c index f3c1d9e81..287091f98 100644 --- a/src/common/proxy_wasm/ngx_proxy_wasm.c +++ b/src/common/proxy_wasm/ngx_proxy_wasm.c @@ -501,6 +501,7 @@ action2rc(ngx_proxy_wasm_ctx_t *pwctx, case NGX_HTTP_REWRITE_PHASE: case NGX_HTTP_ACCESS_PHASE: case NGX_HTTP_CONTENT_PHASE: + case NGX_WASM_BACKGROUND_PHASE: ngx_log_debug6(NGX_LOG_DEBUG_WASM, pwctx->log, 0, "proxy_wasm pausing in \"%V\" phase " "(filter: %l/%l, step: %d, action: %d, " @@ -683,6 +684,7 @@ ngx_proxy_wasm_run_step(ngx_proxy_wasm_exec_t *pwexec, ngx_int_t rc; ngx_proxy_wasm_err_e ecode; ngx_proxy_wasm_action_e action = NGX_PROXY_WASM_ACTION_CONTINUE; + ngx_proxy_wasm_exec_t *out; ngx_proxy_wasm_ctx_t *pwctx = pwexec->parent; ngx_proxy_wasm_filter_t *filter = pwexec->filter; #if (NGX_DEBUG) @@ -700,10 +702,12 @@ ngx_proxy_wasm_run_step(ngx_proxy_wasm_exec_t *pwexec, if (pwexec->ictx == NULL || pwexec->ictx->instance->trapped) { #endif ecode = ngx_proxy_wasm_create_context(filter, pwctx, pwexec->id, - pwexec, NULL); + pwexec, &out); if (ecode != NGX_PROXY_WASM_ERR_NONE) { return ecode; } + + pwexec = out; #if 1 } #endif @@ -842,6 +846,9 @@ get_instance(ngx_proxy_wasm_filter_t *filter, dd("get instance in store: %p", store); + /* store initialized */ + ngx_wasm_assert(store->pool); + for (q = ngx_queue_head(&store->busy); q != ngx_queue_sentinel(&store->busy); q = ngx_queue_next(q)) @@ -988,9 +995,6 @@ ngx_proxy_wasm_create_context(ngx_proxy_wasm_filter_t *filter, ictx = in->ictx; } else { - /* store initialized */ - ngx_wasm_assert(store->pool); - ictx = get_instance(filter, store, log); if (ictx == NULL) { goto error; @@ -1187,10 +1191,15 @@ ngx_proxy_wasm_create_context(ngx_proxy_wasm_filter_t *filter, pwexec->started = 1; } - } - if (out) { - *out = pwexec; + if (out) { + *out = pwexec; + } + + } else { + if (out) { + *out = rexec; + } } return NGX_PROXY_WASM_ERR_NONE; @@ -1245,19 +1254,9 @@ ngx_proxy_wasm_on_done(ngx_proxy_wasm_exec_t *pwexec) pwexec->index + 1, pwexec->parent->nfilters); #if 0 - /** - * Currently, dispatches are synchronous hence will always - * have been executed when on_done is invoked. - */ #ifdef NGX_WASM_HTTP call = pwexec->call; if (call) { - ngx_log_debug3(NGX_LOG_DEBUG_WASM, pwexec->log, 0, - "proxy_wasm \"%V\" filter (%l/%l) " - "cancelling HTTP dispatch", - pwexec->filter->name, pwexec->index + 1, - pwexec->parent->nfilters); - ngx_http_proxy_wasm_dispatch_destroy(call); pwexec->call = NULL; diff --git a/src/common/proxy_wasm/ngx_proxy_wasm_host.c b/src/common/proxy_wasm/ngx_proxy_wasm_host.c index a5be0a1a3..3fb19deed 100644 --- a/src/common/proxy_wasm/ngx_proxy_wasm_host.c +++ b/src/common/proxy_wasm/ngx_proxy_wasm_host.c @@ -26,21 +26,42 @@ static ngx_int_t ngx_proxy_wasm_hfuncs_no_http(ngx_wavm_instance_t *instance, static ngx_chain_t * ngx_proxy_wasm_get_buffer_helper(ngx_wavm_instance_t *instance, - ngx_proxy_wasm_buffer_type_e buf_type, unsigned *none) + ngx_proxy_wasm_buffer_type_e buf_type, unsigned *none, char **trapmsg) { #ifdef NGX_WASM_HTTP ngx_chain_t *cl; ngx_http_wasm_req_ctx_t *rctx; ngx_http_request_t *r; + ngx_proxy_wasm_ctx_t *pwctx; + ngx_proxy_wasm_exec_t *pwexec; - rctx = ngx_http_proxy_wasm_get_rctx(instance); - r = rctx->r; + pwexec = ngx_proxy_wasm_instance2pwexec(instance); + pwctx = pwexec->parent; #endif switch (buf_type) { #ifdef NGX_WASM_HTTP case NGX_PROXY_WASM_BUFFER_HTTP_REQUEST_BODY: + + /* check context */ + + switch (pwctx->step) { + case NGX_PROXY_WASM_STEP_REQ_HEADERS: + case NGX_PROXY_WASM_STEP_REQ_BODY: + case NGX_PROXY_WASM_STEP_LOG: + break; + default: + *trapmsg = "can only get request body during " + "\"on_request_body\", \"on_log\""; + return NULL; + } + + /* get */ + + rctx = ngx_http_proxy_wasm_get_rctx(instance); + r = rctx->r; + if (r->request_body == NULL || r->request_body->bufs == NULL) { @@ -61,6 +82,22 @@ ngx_proxy_wasm_get_buffer_helper(ngx_wavm_instance_t *instance, return r->request_body->bufs; case NGX_PROXY_WASM_BUFFER_HTTP_RESPONSE_BODY: + + /* check context */ + + switch (pwctx->step) { + case NGX_PROXY_WASM_STEP_RESP_BODY: + break; + default: + *trapmsg = "can only get response body during " + "\"on_response_body\""; + return NULL; + } + + /* get */ + + rctx = ngx_http_proxy_wasm_get_rctx(instance); + cl = rctx->resp_chunk; if (cl == NULL) { /* no body */ @@ -74,9 +111,21 @@ ngx_proxy_wasm_get_buffer_helper(ngx_wavm_instance_t *instance, { ngx_wasm_http_reader_ctx_t *reader; ngx_http_proxy_wasm_dispatch_t *call; - ngx_proxy_wasm_exec_t *pwexec; - pwexec = ngx_proxy_wasm_instance2pwexec(instance); + /* check context */ + + switch (pwctx->step) { + case NGX_PROXY_WASM_STEP_DISPATCH_RESPONSE: + case NGX_PROXY_WASM_STEP_LOG: + break; + default: + *trapmsg = "can only get dispatch response body during " + "\"on_http_dispatch_response\""; + return NULL; + } + + /* get */ + call = pwexec->call; if (call == NULL) { return NULL; @@ -207,11 +256,10 @@ ngx_proxy_wasm_hfuncs_set_tick_period(ngx_wavm_instance_t *instance, ngx_event_t *ev; ngx_proxy_wasm_exec_t *rexec = ngx_proxy_wasm_instance2pwexec(instance); - ngx_wasm_assert(rexec->root_id == NGX_PROXY_WASM_ROOT_CTX_ID); - if (rexec->root_id != NGX_PROXY_WASM_ROOT_CTX_ID) { - /* ignore */ - return ngx_proxy_wasm_result_ok(rets); + return ngx_proxy_wasm_result_trap(rexec, + "can only set tick_period in " + "root context", rets, NGX_WAVM_OK); } if (ngx_exiting) { @@ -254,6 +302,7 @@ ngx_proxy_wasm_hfuncs_get_buffer(ngx_wavm_instance_t *instance, { size_t offset, max_len, len, chunk_len; unsigned none = 0; + char *trapmsg = NULL; u_char *start = NULL; ngx_chain_t *cl = NULL; ngx_buf_t *buf; @@ -282,8 +331,14 @@ ngx_proxy_wasm_hfuncs_get_buffer(ngx_wavm_instance_t *instance, break; default: - cl = ngx_proxy_wasm_get_buffer_helper(instance, buf_type, &none); + cl = ngx_proxy_wasm_get_buffer_helper(instance, buf_type, &none, + &trapmsg); if (cl == NULL) { + if (trapmsg) { + return ngx_proxy_wasm_result_trap(pwexec, trapmsg, + rets, NGX_WAVM_BAD_USAGE); + } + if (none) { return ngx_proxy_wasm_result_notfound(rets); } @@ -304,7 +359,7 @@ ngx_proxy_wasm_hfuncs_get_buffer(ngx_wavm_instance_t *instance, if (!len) { /* eof */ - return ngx_proxy_wasm_result_notfound(rets); + return ngx_proxy_wasm_result_ok(rets); } p = ngx_proxy_wasm_alloc(pwexec, len); @@ -376,9 +431,10 @@ ngx_proxy_wasm_hfuncs_set_buffer(ngx_wavm_instance_t *instance, ngx_wavm_ptr_t *buf_data; ngx_http_wasm_req_ctx_t *rctx; ngx_proxy_wasm_exec_t *pwexec; + ngx_proxy_wasm_ctx_t *pwctx; - rctx = ngx_http_proxy_wasm_get_rctx(instance); pwexec = ngx_proxy_wasm_instance2pwexec(instance); + pwctx = pwexec->parent; offset = args[1].of.i32; max = args[2].of.i32; @@ -400,6 +456,26 @@ ngx_proxy_wasm_hfuncs_set_buffer(ngx_wavm_instance_t *instance, #ifdef NGX_WASM_HTTP case NGX_PROXY_WASM_BUFFER_HTTP_REQUEST_BODY: + + /* check context */ + + switch (pwctx->step) { + case NGX_PROXY_WASM_STEP_REQ_HEADERS: + case NGX_PROXY_WASM_STEP_REQ_BODY: + break; + default: + return ngx_proxy_wasm_result_trap(pwexec, + "can only set request body " + "during \"on_request_body\"", + rets, NGX_WAVM_BAD_USAGE); + } + + /* set */ + + rctx = ngx_http_proxy_wasm_get_rctx(instance); + + ngx_wasm_assert(rctx); + if (offset == 0 && max == 0 && buf_len > 0) { rc = ngx_http_wasm_prepend_req_body(rctx, &s); @@ -407,15 +483,29 @@ ngx_proxy_wasm_hfuncs_set_buffer(ngx_wavm_instance_t *instance, rc = ngx_http_wasm_set_req_body(rctx, &s, offset, max); } - if (rc == NGX_ABORT) { + ngx_wasm_assert(rc != NGX_ABORT); + break; + + case NGX_PROXY_WASM_BUFFER_HTTP_RESPONSE_BODY: + + /* check context */ + + switch (pwctx->step) { + case NGX_PROXY_WASM_STEP_RESP_BODY: + break; + default: return ngx_proxy_wasm_result_trap(pwexec, - "cannot set request body", + "can only set response body " + "during \"on_response_body\"", rets, NGX_WAVM_BAD_USAGE); } - break; + /* set */ + + rctx = ngx_http_proxy_wasm_get_rctx(instance); + + ngx_wasm_assert(rctx); - case NGX_PROXY_WASM_BUFFER_HTTP_RESPONSE_BODY: if (offset == 0 && max == 0 && buf_len > 0) { rc = ngx_http_wasm_prepend_resp_body(rctx, &s); @@ -423,12 +513,7 @@ ngx_proxy_wasm_hfuncs_set_buffer(ngx_wavm_instance_t *instance, rc = ngx_http_wasm_set_resp_body(rctx, &s, offset, max); } - if (rc == NGX_ABORT) { - return ngx_proxy_wasm_result_trap(pwexec, - "cannot set response body", - rets, NGX_WAVM_BAD_USAGE); - } - + ngx_wasm_assert(rc != NGX_ABORT); break; #endif @@ -972,12 +1057,33 @@ ngx_proxy_wasm_hfuncs_dispatch_http_call(ngx_wavm_instance_t *instance, uint32_t *callout_id, timeout; ngx_str_t host, body; ngx_proxy_wasm_marshalled_map_t headers, trailers; + ngx_proxy_wasm_ctx_t *pwctx; ngx_proxy_wasm_exec_t *pwexec; ngx_http_wasm_req_ctx_t *rctx; ngx_http_proxy_wasm_dispatch_t *call = NULL; pwexec = ngx_proxy_wasm_instance2pwexec(instance); rctx = ngx_http_proxy_wasm_get_rctx(instance); + pwctx = pwexec->parent; + + /* check context */ + + switch (pwctx->step) { + case NGX_PROXY_WASM_STEP_REQ_HEADERS: + case NGX_PROXY_WASM_STEP_REQ_BODY: + case NGX_PROXY_WASM_STEP_TICK: + case NGX_PROXY_WASM_STEP_DISPATCH_RESPONSE: + break; + default: + return ngx_proxy_wasm_result_trap(pwexec, + "can only send HTTP dispatch " + "during " + "\"on_request_headers\", " + "\"on_request_body\", " + "\"on_dispatch_response\", " + "\"on_tick\"", + rets, NGX_WAVM_BAD_USAGE); + } host.len = args[1].of.i32; host.data = NGX_WAVM_HOST_LIFT_SLICE(instance, args[0].of.i32, host.len); diff --git a/src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c b/src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c index 6b5c37243..41d967a87 100644 --- a/src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c +++ b/src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c @@ -155,7 +155,6 @@ ngx_http_proxy_wasm_dispatch(ngx_proxy_wasm_exec_t *pwexec, /* rctx or fake request */ if (rctx == NULL) { - ngx_wasm_assert(pwexec->in_tick); ngx_wasm_assert(pwexec->root_id == NGX_PROXY_WASM_ROOT_CTX_ID); ngx_wasm_assert(pwexec->parent->id == NGX_PROXY_WASM_ROOT_CTX_ID); @@ -825,6 +824,11 @@ ngx_http_proxy_wasm_dispatch_resume_handler(ngx_wasm_socket_tcp_t *sock) /* save step */ step = pwexec->parent->step; +#ifdef NGX_WASM_HTTP + pwexec->parent->phase = ngx_wasm_phase_lookup(&ngx_http_wasm_subsystem, + NGX_WASM_BACKGROUND_PHASE); +#endif + ecode = ngx_proxy_wasm_run_step(pwexec, NGX_PROXY_WASM_STEP_DISPATCH_RESPONSE); if (ecode != NGX_PROXY_WASM_ERR_NONE) { @@ -838,6 +842,12 @@ ngx_http_proxy_wasm_dispatch_resume_handler(ngx_wasm_socket_tcp_t *sock) /* resume current step if unfinished */ rc = ngx_proxy_wasm_resume(pwexec->parent, pwexec->parent->phase, step); + if (rc == NGX_AGAIN) { + goto done; + + } else if (rc != NGX_OK) { + goto error; + } } else { /* another call was setup during the callback */ diff --git a/t/03-proxy_wasm/hfuncs/100-proxy_log.t b/t/03-proxy_wasm/hfuncs/100-proxy_log.t index ac6ef8c27..dc78ad99e 100644 --- a/t/03-proxy_wasm/hfuncs/100-proxy_log.t +++ b/t/03-proxy_wasm/hfuncs/100-proxy_log.t @@ -36,50 +36,7 @@ ok -=== TEST 2: proxy_wasm - proxy_log() x on_phases ---- load_nginx_modules: ngx_http_echo_module ---- wasm_modules: hostcalls ---- config - location /t/A { - proxy_wasm hostcalls 'on=request_headers \ - test=/t/log/levels'; - echo A; - } - - location /t/B { - proxy_wasm hostcalls 'on=response_headers \ - test=/t/log/levels'; - echo B; - } - - location /t { - proxy_wasm hostcalls 'on=log \ - test=/t/log/levels'; - echo_location /t/A; - echo_location /t/B; - echo C; - } ---- request -GET /t ---- response_body -A -B -C ---- error_log eval -[ - qr/testing in "RequestHeaders"/, - qr/\[error\] .*? proxy_log error/, - qr/testing in "ResponseHeaders"/, - qr/\[error\] .*? proxy_log error/, - qr/testing in "Log"/, - qr/\[error\] .*? proxy_log error/, -] ---- no_error_log -[alert] - - - -=== TEST 3: proxy_wasm - proxy_log() bad log level +=== TEST 2: proxy_wasm - proxy_log() bad log level --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config diff --git a/t/03-proxy_wasm/hfuncs/101-proxy_get_current_time.t b/t/03-proxy_wasm/hfuncs/101-proxy_get_current_time.t index e2c310970..45dde40a0 100644 --- a/t/03-proxy_wasm/hfuncs/101-proxy_get_current_time.t +++ b/t/03-proxy_wasm/hfuncs/101-proxy_get_current_time.t @@ -24,8 +24,6 @@ should produce a log with the current time (ms as ~ns) --- response_body ok --- error_log eval -[ - qr/\[info\] .*? now: 2.*? UTC/, -] +qr/\[info\] .*? now: 2.*? UTC/, --- no_error_log [error] diff --git a/t/03-proxy_wasm/hfuncs/114-proxy_set_http_request_body.t b/t/03-proxy_wasm/hfuncs/114-proxy_set_http_request_body.t index 1c31f21b1..310dbf035 100644 --- a/t/03-proxy_wasm/hfuncs/114-proxy_set_http_request_body.t +++ b/t/03-proxy_wasm/hfuncs/114-proxy_set_http_request_body.t @@ -204,61 +204,3 @@ HelloWorld [error] [crit] [alert] - - - -=== TEST 7: proxy_wasm - set_http_request_body() x on_phases ---- load_nginx_modules: ngx_http_echo_module ---- wasm_modules: hostcalls ---- config - location /request_headers { - # ok - proxy_wasm hostcalls 'on=request_headers \ - test=/t/set_request_body \ - value=from_request_headers'; - echo $request_body; - } - - location /request_body { - # ok - proxy_wasm hostcalls 'on=request_body \ - test=/t/set_request_body \ - value=from_request_body'; - echo $request_body; - } - - location /response_headers { - # cannot set request body - proxy_wasm hostcalls 'on=response_headers \ - test=/t/set_request_body'; - echo $request_body; - } - - location /log { - # not executed (subrequest) - proxy_wasm hostcalls 'on=log \ - test=/t/set_request_body'; - echo $request_body; - } - - location /t { - echo_subrequest POST /request_headers -b 'orig'; - echo_subrequest POST /request_body -b 'orig'; - echo_subrequest POST /response_headers -b 'orig'; - echo_subrequest POST /log -b 'orig'; - - # cannot resume - proxy_wasm hostcalls 'on=response_body test=/t/log/request_body'; - } ---- response_body eval -qr/from_request_headers -from_request_body -[\s\S]+500 Internal Server Error/ ---- grep_error_log eval: qr/(.*?cannot set|\[.*?failed resuming).*/ ---- grep_error_log_out eval -qr/.*?host trap \(bad usage\): cannot set request body.* -\[info\] .*? \*\d+ .*? filter chain failed resuming: previous error \(instance trapped\).*? subrequest: "\/response_headers".* -\z/ ---- no_error_log -[alert] -[stderr] diff --git a/t/03-proxy_wasm/hfuncs/116-proxy_set_http_response_body.t b/t/03-proxy_wasm/hfuncs/116-proxy_set_http_response_body.t index 15ce88076..f003cee2a 100644 --- a/t/03-proxy_wasm/hfuncs/116-proxy_set_http_response_body.t +++ b/t/03-proxy_wasm/hfuncs/116-proxy_set_http_response_body.t @@ -94,12 +94,8 @@ on_response_body, 0 bytes, eof: true.*/ --- config location /t { echo fail; - proxy_wasm hostcalls 'on=response_body \ test=/t/set_response_body value='; - - proxy_wasm hostcalls 'on=log \ - test=/t/log/response_body'; } --- response_headers Transfer-Encoding: chunked @@ -108,7 +104,6 @@ Content-Length: --- grep_error_log eval: qr/(on_response_body,|response body chunk).*/ --- grep_error_log_out eval qr/on_response_body, 5 bytes, eof: false.* -on_response_body, 0 bytes, eof: true.* on_response_body, 0 bytes, eof: true.*/ --- no_error_log [error] @@ -133,8 +128,6 @@ on_response_body, 0 bytes, eof: true.*/ location /t { echo_subrequest GET /subrequest; - proxy_wasm hostcalls 'on=response_headers \ - test=/t/log/response_body'; } --- response_headers Transfer-Encoding: chunked @@ -148,7 +141,6 @@ overriding response body chunk while Content-Length header already sent.* on_response_body, 11 bytes, eof: false.* response body chunk: "HelloWorld\\n".* on_response_body, 0 bytes, eof: true.* -on_response_body, 0 bytes, eof: true.* on_response_body, 0 bytes, eof: true.*/ --- no_error_log [error] @@ -305,52 +297,3 @@ on_response_body, 0 bytes, eof: true.*/ --- no_error_log [error] [crit] - - - -=== TEST 7: proxy_wasm - set_http_response_body() x on_phases -should not be usable anywhere else than on_http_response_body -should not be retrievable after on_http_response_body since buffers are consumed ---- load_nginx_modules: ngx_http_echo_module ---- wasm_modules: hostcalls ---- config - proxy_wasm_isolation filter; - - location /request_headers { - internal; - echo; - proxy_wasm hostcalls 'on=request_headers \ - test=/t/set_response_body'; - proxy_wasm hostcalls 'on=request_headers \ - test=/t/log/response_body'; - } - - location /response_headers { - internal; - echo; - proxy_wasm hostcalls 'on=response_headers \ - test=/t/set_response_body'; - proxy_wasm hostcalls 'on=response_headers \ - test=/t/log/response_body'; - } - - location /t { - echo_subrequest GET /request_headers; - echo_subrequest GET /response_headers; - proxy_wasm hostcalls 'on=log test=/t/set_response_body'; - } ---- response_headers -Transfer-Encoding: chunked -Content-Length: ---- response_body eval -qr/500 Internal Server Error/ ---- grep_error_log eval: qr/(.*?cannot set|\[.*?failed resuming).*/ ---- grep_error_log_out eval -qr/.*?host trap \(bad usage\): cannot set response body.* -\[info\] .*? \*\d+ .*? filter chain failed resuming: previous error \(instance trapped\).*? subrequest: "\/request_headers".* -.*?host trap \(bad usage\): cannot set response body.* -\[info\] .*? \*\d+ .*? filter chain failed resuming: previous error \(instance trapped\).*? subrequest: "\/response_headers".* -.*?host trap \(bad usage\): cannot set response body.*/ ---- no_error_log -[alert] -[stderr] diff --git a/t/03-proxy_wasm/hfuncs/130-proxy_dispatch_http.t b/t/03-proxy_wasm/hfuncs/130-proxy_dispatch_http.t index bf0c0772f..0cc417f22 100644 --- a/t/03-proxy_wasm/hfuncs/130-proxy_dispatch_http.t +++ b/t/03-proxy_wasm/hfuncs/130-proxy_dispatch_http.t @@ -289,7 +289,7 @@ ok --- wasm_modules: hostcalls --- config location /dispatched { - return 200 "Hello world"; + return 200 "Hello back"; } location /t { @@ -1171,31 +1171,7 @@ qr/^\*\d+ .*? on_http_call_response \(id: \d+[^*]* -=== TEST 46: proxy_wasm - dispatch_http_call() on log step ---- load_nginx_modules: ngx_http_echo_module ---- wasm_modules: hostcalls ---- config - location /dispatched { - return 200 "Hello world"; - } - - location /t { - proxy_wasm hostcalls 'on=log \ - test=/t/dispatch_http_call \ - host=127.0.0.1:$TEST_NGINX_SERVER_PORT \ - path=/dispatched'; - echo fail; - } ---- response_body -fail ---- error_log eval -qr/(\[error\]|Uncaught RuntimeError|\s+).*?dispatch failed: bad step/ ---- no_error_log -[crit] - - - -=== TEST 47: proxy_wasm - dispatch_http_call() supports get_http_call_response_headers() +=== TEST 46: proxy_wasm - dispatch_http_call() supports get_http_call_response_headers() --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -1219,7 +1195,7 @@ X-Callout-Header: callout-header-value -=== TEST 48: proxy_wasm - dispatch_http_call() get :status dispatch response header +=== TEST 47: proxy_wasm - dispatch_http_call() get :status dispatch response header --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -1262,7 +1238,7 @@ qr/^\*\d+ .*? on_http_call_response \(id: \d+, status: 200[^*]* -=== TEST 49: proxy_wasm - dispatch_http_call() with dispatched request body +=== TEST 48: proxy_wasm - dispatch_http_call() with dispatched request body --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -1288,7 +1264,7 @@ helloworld -=== TEST 50: proxy_wasm - dispatch_http_call() override Content-Length +=== TEST 49: proxy_wasm - dispatch_http_call() override Content-Length --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -1315,7 +1291,7 @@ helloworl -=== TEST 51: proxy_wasm - dispatch_http_call() cannot override hard-coded request headers +=== TEST 50: proxy_wasm - dispatch_http_call() cannot override hard-coded request headers --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls diff --git a/t/03-proxy_wasm/hfuncs/contexts/002-set_tick_period.t b/t/03-proxy_wasm/hfuncs/contexts/002-set_tick_period.t new file mode 100644 index 000000000..b055ddba1 --- /dev/null +++ b/t/03-proxy_wasm/hfuncs/contexts/002-set_tick_period.t @@ -0,0 +1,184 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +skip_hup(); +skip_no_debug(); +skip_valgrind(); + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: proxy_wasm contexts - set_tick_period on_vm_start +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm 'set_tick_period'; + } +--- config + location /t { + proxy_wasm context_checks; + return 200; + } +--- ignore_response_body +--- error_log +set_tick_period status: 0 +--- no_error_log +[error] +[crit] + + + +=== TEST 2: proxy_wasm contexts - set_tick_period on_configure +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_configure=set_tick_period'; + return 200; + } +--- ignore_response_body +--- error_log +set_tick_period status: 0 +--- no_error_log +[error] +[crit] + + + +=== TEST 3: proxy_wasm contexts - set_tick_period on_tick +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_tick=set_tick_period'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +tick_period already set +--- no_error_log +[crit] + + + +=== TEST 4: proxy_wasm contexts - set_tick_period on_http_dispatch_response +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_http_dispatch_response=set_tick_period \ + host=127.0.0.1:$TEST_NGINX_SERVER_PORT'; + return 200; + } + + location /dispatch { + return 200; + } +--- ignore_response_body +--- error_log +can only set tick_period in root context +--- no_error_log +[crit] +[alert] + + + +=== TEST 5: proxy_wasm contexts - set_tick_period on_request_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_headers=set_tick_period'; + return 200; + } +--- error_code: 500 +--- ignore_response_body +--- error_log +can only set tick_period in root context +--- no_error_log +[crit] +[alert] + + + +=== TEST 6: proxy_wasm contexts - set_tick_period on_request_body +--- load_nginx_modules: ngx_http_echo_module +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_request_body=set_tick_period'; + echo ok; + } +--- request +POST /t +payload +--- error_code: 500 +--- ignore_response_body +--- error_log +can only set tick_period in root context +--- no_error_log +[crit] +[alert] + + + +=== TEST 7: proxy_wasm contexts - set_tick_period on_response_headers +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_response_headers=set_tick_period'; + return 200; + } +--- ignore_response_body +--- error_log +can only set tick_period in root context +--- no_error_log +[crit] +[alert] + + + +=== TEST 8: proxy_wasm contexts - set_tick_period on_response_body +--- load_nginx_modules: ngx_http_echo_module +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_response_body=set_tick_period'; + echo ok; + } +--- ignore_response_body +--- error_log +can only set tick_period in root context +--- no_error_log +[crit] +[alert] + + + +=== TEST 9: proxy_wasm contexts - set_tick_period on_log +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_log=set_tick_period'; + return 200; + } +--- ignore_response_body +--- error_log +can only set tick_period in root context +--- no_error_log +[crit] +[alert] diff --git a/t/03-proxy_wasm/hfuncs/contexts/100-proxy_log.t b/t/03-proxy_wasm/hfuncs/contexts/100-proxy_log.t new file mode 100644 index 000000000..7e7002078 --- /dev/null +++ b/t/03-proxy_wasm/hfuncs/contexts/100-proxy_log.t @@ -0,0 +1,191 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +skip_hup(); +skip_no_debug(); +skip_valgrind(); + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: proxy_wasm contexts - proxy_log on_vm_start +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm 'proxy_log'; + } +--- config + location /t { + proxy_wasm context_checks; + return 200; + } +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] + + + +=== TEST 2: proxy_wasm contexts - proxy_log on_configure +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_configure=proxy_log'; + return 200; + } +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] + + + +=== TEST 3: proxy_wasm contexts - proxy_log on_tick +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_tick=proxy_log'; + return 200; + } +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] + + + +=== TEST 4: proxy_wasm contexts - proxy_log on_http_dispatch_response +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_http_dispatch_response=proxy_log \ + host=127.0.0.1:$TEST_NGINX_SERVER_PORT'; + return 200; + } + + location /dispatch { + return 200; + } +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] + + + +=== TEST 5: proxy_wasm contexts - proxy_log on_request_headers +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_request_headers=proxy_log'; + return 200; + } +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] + + + +=== TEST 6: proxy_wasm contexts - proxy_log on_request_body +--- load_nginx_modules: ngx_http_echo_module +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_request_body=proxy_log'; + echo ok; + } +--- request +POST /t +payload +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] + + + +=== TEST 7: proxy_wasm contexts - proxy_log on_response_headers +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_response_headers=proxy_log'; + return 200; + } +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] + + + +=== TEST 8: proxy_wasm contexts - proxy_log on_response_body +--- load_nginx_modules: ngx_http_echo_module +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_response_body=proxy_log'; + echo ok; + } +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] + + + +=== TEST 9: proxy_wasm contexts - proxy_log on_log +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_log=proxy_log'; + return 200; + } +--- ignore_response_body +--- error_log +proxy_log msg +--- no_error_log +[error] +[crit] diff --git a/t/03-proxy_wasm/hfuncs/contexts/113-proxy_get_http_request_body.t b/t/03-proxy_wasm/hfuncs/contexts/113-proxy_get_http_request_body.t new file mode 100644 index 000000000..4eeb96b97 --- /dev/null +++ b/t/03-proxy_wasm/hfuncs/contexts/113-proxy_get_http_request_body.t @@ -0,0 +1,190 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +skip_hup(); +skip_no_debug(); +skip_valgrind(); + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: proxy_wasm contexts - get_http_request_body on_vm_start +'daemon off' must be set to check exit_code is 2 +Valgrind mode already writes 'daemon off' +HUP mode does not catch the worker exit_code +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- main_config eval +qq{ + wasm { + module context_checks $ENV{TEST_NGINX_CRATES_DIR}/context_checks.wasm 'get_request_body_buffer'; + } +}.($ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;') +--- config + location /t { + proxy_wasm context_checks; + return 200; + } +--- ignore_response_body +--- error_log +[error] +[emerg] +can only get request body during "on_request_body", "on_log" +--- no_error_log +--- must_die: 2 + + + +=== TEST 2: proxy_wasm contexts - get_http_request_body on_configure +'daemon off' must be set to check exit_code is 2 +Valgrind mode already writes 'daemon off' +HUP mode does not catch the worker exit_code +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- main_config eval +qq{ + wasm { + module context_checks $ENV{TEST_NGINX_CRATES_DIR}/context_checks.wasm; + } +}.($ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;') +--- config + location /t { + proxy_wasm context_checks 'on_configure=get_request_body_buffer'; + return 200; + } + +--- ignore_response_body +--- error_log +[error] +[emerg] +can only get request body during "on_request_body", "on_log" +--- must_die: 2 + + + +=== TEST 3: proxy_wasm contexts - get_http_request_body on_tick +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_tick=get_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only get request body during "on_request_body", "on_log" +--- no_error_log +[crit] + + + +=== TEST 4: proxy_wasm contexts - get_http_request_body on_http_dispatch_response +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_http_dispatch_response=get_request_body_buffer \ + host=127.0.0.1:$TEST_NGINX_SERVER_PORT'; + return 200; + } + + location /dispatch { + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only get request body during "on_request_body", "on_log" +--- no_error_log +[crit] + + + +=== TEST 5: proxy_wasm contexts - get_http_request_body on_request_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_headers=get_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +get_request_body_buffer status: 1 +--- no_error_log +[error] +[crit] + + + +=== TEST 6: proxy_wasm contexts - get_http_request_body on_request_body +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_body=get_request_body_buffer'; + echo ok; + } +--- request +POST /t +payload +--- ignore_response_body +--- error_log +get_request_body_buffer status: 0 +--- no_error_log +[error] +[crit] + + + +=== TEST 7: proxy_wasm contexts - get_http_request_body on_response_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_headers=get_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only get request body during "on_request_body", "on_log" +--- no_error_log +[crit] + + + +=== TEST 8: proxy_wasm contexts - get_http_request_body on_response_body +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_body=get_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only get request body during "on_request_body", "on_log" +--- no_error_log +[crit] + + + +=== TEST 9: proxy_wasm contexts - get_http_request_body on_log +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_log=get_request_body_buffer'; + echo ok; + } +--- request +POST /t +payload +--- ignore_response_body +--- error_log +get_request_body_buffer status: 0 +--- no_error_log +[error] +[crit] diff --git a/t/03-proxy_wasm/hfuncs/contexts/114-proxy_set_http_request_body.t b/t/03-proxy_wasm/hfuncs/contexts/114-proxy_set_http_request_body.t new file mode 100644 index 000000000..8d886fd20 --- /dev/null +++ b/t/03-proxy_wasm/hfuncs/contexts/114-proxy_set_http_request_body.t @@ -0,0 +1,186 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +skip_hup(); +skip_no_debug(); +skip_valgrind(); + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: proxy_wasm contexts - set_http_request_body on_vm_start +'daemon off' must be set to check exit_code is 2 +Valgrind mode already writes 'daemon off' +HUP mode does not catch the worker exit_code +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- main_config eval +qq{ + wasm { + module context_checks $ENV{TEST_NGINX_CRATES_DIR}/context_checks.wasm 'set_request_body_buffer'; + } +}.($ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;') +--- config + location /t { + proxy_wasm context_checks; + return 200; + } +--- ignore_response_body +--- error_log +[error] +[emerg] +can only set request body during "on_request_body" +--- no_error_log +--- must_die: 2 + + + +=== TEST 2: proxy_wasm contexts - set_http_request_body on_configure +'daemon off' must be set to check exit_code is 2 +Valgrind mode already writes 'daemon off' +HUP mode does not catch the worker exit_code +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- main_config eval +qq{ + wasm { + module context_checks $ENV{TEST_NGINX_CRATES_DIR}/context_checks.wasm; + } +}.($ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;') +--- config + location /t { + proxy_wasm context_checks 'on_configure=set_request_body_buffer'; + return 200; + } + +--- ignore_response_body +--- error_log +[error] +[emerg] +can only set request body during "on_request_body" +--- must_die: 2 + + + +=== TEST 3: proxy_wasm contexts - set_http_request_body on_tick +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_tick=set_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set request body during "on_request_body" +--- no_error_log +[crit] + + + +=== TEST 4: proxy_wasm contexts - set_http_request_body on_http_dispatch_response +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_http_dispatch_response=set_request_body_buffer \ + host=127.0.0.1:$TEST_NGINX_SERVER_PORT'; + return 200; + } + + location /dispatch { + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set request body during "on_request_body" +--- no_error_log +[crit] + + + +=== TEST 5: proxy_wasm contexts - set_http_request_body on_request_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_headers=set_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +set_request_body_buffer status: 0 +--- no_error_log +[error] +[crit] + + + +=== TEST 6: proxy_wasm contexts - set_http_request_body on_request_body +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_body=set_request_body_buffer'; + echo ok; + } +--- request +POST /t +payload +--- ignore_response_body +--- error_log +set_request_body_buffer status: 0 +--- no_error_log +[error] +[crit] + + + +=== TEST 7: proxy_wasm contexts - set_http_request_body on_response_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_headers=set_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set request body during "on_request_body" +--- no_error_log +[crit] + + + +=== TEST 8: proxy_wasm contexts - set_http_request_body on_response_body (request_body_buffer) +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_body=set_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set request body during "on_request_body" +--- no_error_log +[crit] + + + +=== TEST 9: proxy_wasm contexts - set_http_request_body on_log +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_log=set_request_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set request body during "on_request_body" +--- no_error_log +[crit] diff --git a/t/03-proxy_wasm/hfuncs/contexts/115-proxy_get_http_response_body.t b/t/03-proxy_wasm/hfuncs/contexts/115-proxy_get_http_response_body.t new file mode 100644 index 000000000..6697b8ee3 --- /dev/null +++ b/t/03-proxy_wasm/hfuncs/contexts/115-proxy_get_http_response_body.t @@ -0,0 +1,189 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +skip_hup(); +skip_no_debug(); +skip_valgrind(); + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: proxy_wasm contexts - get_http_response_body on_vm_start (response_body_buffer) +'daemon off' must be set to check exit_code is 2 +Valgrind mode already writes 'daemon off' +HUP mode does not catch the worker exit_code +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- main_config eval +qq{ + wasm { + module context_checks $ENV{TEST_NGINX_CRATES_DIR}/context_checks.wasm 'get_response_body_buffer'; + } +}.($ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;') +--- config + location /t { + proxy_wasm context_checks; + return 200; + } +--- ignore_response_body +--- error_log +[error] +[emerg] +can only get response body during "on_response_body" +--- no_error_log +--- must_die: 2 + + + +=== TEST 2: proxy_wasm contexts - get_http_response_body on_configure +'daemon off' must be set to check exit_code is 2 +Valgrind mode already writes 'daemon off' +HUP mode does not catch the worker exit_code +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- main_config eval +qq{ + wasm { + module context_checks $ENV{TEST_NGINX_CRATES_DIR}/context_checks.wasm; + } +}.($ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;') +--- config + location /t { + proxy_wasm context_checks 'on_configure=get_response_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +[emerg] +can only get response body during "on_response_body" +--- must_die: 2 + + + +=== TEST 3: proxy_wasm contexts - get_http_response_body on_tick +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_tick=get_response_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only get response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 4: proxy_wasm contexts - get_http_response_body on_http_dispatch_response +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_http_dispatch_response=get_response_body_buffer \ + host=127.0.0.1:$TEST_NGINX_SERVER_PORT'; + return 200; + } + + location /dispatch { + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only get response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 5: proxy_wasm contexts - get_http_response_body on_request_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_headers=get_response_body_buffer'; + return 200; + } +--- error_code: 500 +--- ignore_response_body +--- error_log +[error] +can only get response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 6: proxy_wasm contexts - get_http_response_body on_request_body +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_body=get_response_body_buffer'; + echo ok; + } +--- request +POST /t +payload +--- error_code: 500 +--- ignore_response_body +--- error_log +[error] +can only get response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 7: proxy_wasm contexts - get_http_response_body on_response_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_headers=get_response_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only get response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 8: proxy_wasm contexts - get_http_response_body on_response_body +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_body=get_response_body_buffer'; + echo ok; + } +--- ignore_response_body +--- error_log +get_response_body_buffer status: 0 +--- no_error_log +[error] +[crit] + + + +=== TEST 9: proxy_wasm contexts - get_http_response_body on_log +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_log=get_response_body_buffer'; + echo ok; + } +--- ignore_response_body +--- error_log +[error] +can only get response body during "on_response_body" +--- no_error_log +[crit] diff --git a/t/03-proxy_wasm/hfuncs/contexts/116-proxy_set_http_response_body.t b/t/03-proxy_wasm/hfuncs/contexts/116-proxy_set_http_response_body.t new file mode 100644 index 000000000..2d7dd3dcf --- /dev/null +++ b/t/03-proxy_wasm/hfuncs/contexts/116-proxy_set_http_response_body.t @@ -0,0 +1,189 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +skip_hup(); +skip_no_debug(); +skip_valgrind(); + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: proxy_wasm contexts - set_http_response_body on_vm_start +'daemon off' must be set to check exit_code is 2 +Valgrind mode already writes 'daemon off' +HUP mode does not catch the worker exit_code +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- main_config eval +qq{ + wasm { + module context_checks $ENV{TEST_NGINX_CRATES_DIR}/context_checks.wasm 'set_response_body_buffer'; + } +}.($ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;') +--- config + location /t { + proxy_wasm context_checks; + return 200; + } +--- ignore_response_body +--- error_log +[error] +[emerg] +can only set response body during "on_response_body" +--- no_error_log +--- must_die: 2 + + + +=== TEST 2: proxy_wasm contexts - set_http_response_body on_configure +'daemon off' must be set to check exit_code is 2 +Valgrind mode already writes 'daemon off' +HUP mode does not catch the worker exit_code +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- main_config eval +qq{ + wasm { + module context_checks $ENV{TEST_NGINX_CRATES_DIR}/context_checks.wasm; + } +}.($ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;') +--- config + location /t { + proxy_wasm context_checks 'on_configure=set_response_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +[emerg] +can only set response body during "on_response_body" +--- must_die: 2 + + + +=== TEST 3: proxy_wasm contexts - set_http_response_body on_tick +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_tick=set_response_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 4: proxy_wasm contexts - set_http_response_body on_http_dispatch_response +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_http_dispatch_response=set_response_body_buffer \ + host=127.0.0.1:$TEST_NGINX_SERVER_PORT'; + return 200; + } + + location /dispatch { + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 5: proxy_wasm contexts - set_http_response_body on_request_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_headers=set_response_body_buffer'; + return 200; + } +--- error_code: 500 +--- ignore_response_body +--- error_log +[error] +can only set response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 6: proxy_wasm contexts - set_http_response_body on_request_body +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_body=set_response_body_buffer'; + echo ok; + } +--- request +POST /t +payload +--- error_code: 500 +--- ignore_response_body +--- error_log +[error] +can only set response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 7: proxy_wasm contexts - set_http_response_body on_response_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_headers=set_response_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set response body during "on_response_body" +--- no_error_log +[crit] + + + +=== TEST 8: proxy_wasm contexts - set_http_response_body on_response_body +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_body=set_response_body_buffer'; + return 200; + } +--- error_code: +--- ignore_response_body +--- error_log +set_response_body_buffer status: 0 +--- no_error_log +[error] +[crit] + + + +=== TEST 9: proxy_wasm contexts - set_http_response_body on_log +should not be retrievable after on_response_body since buffers are consumed +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_log=set_response_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only set response body during "on_response_body" +--- no_error_log +[crit] diff --git a/t/03-proxy_wasm/hfuncs/contexts/130-proxy_dispatch_http.t b/t/03-proxy_wasm/hfuncs/contexts/130-proxy_dispatch_http.t new file mode 100644 index 000000000..51992b502 --- /dev/null +++ b/t/03-proxy_wasm/hfuncs/contexts/130-proxy_dispatch_http.t @@ -0,0 +1,175 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +skip_hup(); +skip_no_debug(); +skip_valgrind(); + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: proxy_wasm contexts - dispatch_http_call on_vm_start +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm 'dispatch_http_call'; + } +--- config + location /t { + proxy_wasm context_checks; + return 200; + } +--- must_die: 0 +--- error_log +[error] +can only send HTTP dispatch during "on_request_headers", "on_request_body", "on_dispatch_response", "on_tick" +--- no_error_log +[crit] + + + +=== TEST 2: proxy_wasm contexts - dispatch_http_call on_configure +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_configure=dispatch_http_call'; + return 200; + } +--- must_die: 0 +--- error_log +[error] +can only send HTTP dispatch during "on_request_headers", "on_request_body", "on_dispatch_response", "on_tick" +--- no_error_log +[crit] + + + +=== TEST 3: proxy_wasm contexts - dispatch_http_call on_tick +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_tick=dispatch_http_call'; + return 200; + } +--- error_log +dispatch failed: no :method +--- no_error_log +[crit] +[emerg] + + + +=== TEST 4: proxy_wasm contexts - dispatch_http_call on_http_dispatch_response +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_http_dispatch_response=dispatch_http_call \ + host=127.0.0.1:$TEST_NGINX_SERVER_PORT'; + return 200; + } + + location /dispatch { + return 200; + } +--- ignore_response_body +--- error_log +dispatch failed: no :method +--- no_error_log +[crit] +[alert] + + + +=== TEST 5: proxy_wasm contexts - dispatch_http_call on_request_headers +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_request_headers=dispatch_http_call'; + return 200; + } +--- error_code: 500 +--- ignore_response_body +--- error_log +dispatch failed: no :method +--- no_error_log +[crit] +[alert] + + + +=== TEST 6: proxy_wasm contexts - dispatch_http_call on_request_body +--- load_nginx_modules: ngx_http_echo_module +--- main_config + wasm { + module context_checks $TEST_NGINX_CRATES_DIR/context_checks.wasm; + } +--- config + location /t { + proxy_wasm context_checks 'on_request_body=dispatch_http_call'; + echo ok; + } +--- request +POST /t +payload +--- error_code: 500 +--- ignore_response_body +--- error_log +dispatch failed: no :method +--- no_error_log +[crit] +[alert] + + + +=== TEST 7: proxy_wasm contexts - dispatch_http_call on_response_headers +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_headers=dispatch_http_call'; + echo ok; + } +--- error_code: 500 +--- ignore_response_body +--- error_log +[error] +can only send HTTP dispatch during "on_request_headers", "on_request_body", "on_dispatch_response", "on_tick" +--- no_error_log +[crit] + + + +=== TEST 8: proxy_wasm contexts - dispatch_http_call on_response_body +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_response_body=dispatch_http_call'; + echo ok; + } +--- ignore_response_body +--- error_log +[error] +can only send HTTP dispatch during "on_request_headers", "on_request_body", "on_dispatch_response", "on_tick" +--- no_error_log +[crit] + + + +=== TEST 9: proxy_wasm contexts - dispatch_http_call on_log +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_log=dispatch_http_call'; + return 200; + } +--- error_log +[error] +can only send HTTP dispatch during "on_request_headers", "on_request_body", "on_dispatch_response", "on_tick" +--- no_error_log +[crit] diff --git a/t/03-proxy_wasm/hfuncs/contexts/131-proxy_get_http_dispatch_response_body.t b/t/03-proxy_wasm/hfuncs/contexts/131-proxy_get_http_dispatch_response_body.t new file mode 100644 index 000000000..335182ca4 --- /dev/null +++ b/t/03-proxy_wasm/hfuncs/contexts/131-proxy_get_http_dispatch_response_body.t @@ -0,0 +1,29 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +skip_hup(); +skip_no_debug(); +skip_valgrind(); + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: proxy_wasm contexts - get_http_dispatch_response_body on_tick +--- wasm_modules: context_checks +--- config + location /t { + proxy_wasm context_checks 'on_tick=get_dispatch_response_body_buffer'; + return 200; + } +--- ignore_response_body +--- error_log +[error] +can only get dispatch response body during "on_http_dispatch_response" +--- no_error_log +[crit] diff --git a/t/04-openresty/ffi/200-proxy_wasm_and_lua_sanity.t b/t/04-openresty/ffi/200-proxy_wasm_and_lua_sanity.t index 161bbed3c..60a18aaf4 100644 --- a/t/04-openresty/ffi/200-proxy_wasm_and_lua_sanity.t +++ b/t/04-openresty/ffi/200-proxy_wasm_and_lua_sanity.t @@ -245,7 +245,7 @@ qr/on_http_call_response \(id: \d+, status: 200, headers: 5, body_bytes: \d+, tr --- grep_error_log eval: qr/\*\d+.*?\[proxy-wasm\].*?(resuming|freeing).*/ --- grep_error_log_out eval qr/\A\*\d+ .*? filter 1\/1 resuming "on_request_headers" step in "rewrite" phase[^#*]* -\*\d+ .*? filter 1\/1 resuming "on_dispatch_response" step in "access" phase[^#*]* +\*\d+ .*? filter 1\/1 resuming "on_dispatch_response" step in "background" phase[^#*]* \*\d+ .*? filter 1\/1 resuming "on_response_headers" step in "header_filter" phase[^#*]* \*\d+ .*? filter 1\/1 resuming "on_response_body" step in "body_filter" phase[^#*]* \*\d+ .*? filter 1\/1 resuming "on_log" step in "log" phase[^#*]* @@ -308,7 +308,7 @@ qr/on_http_call_response \(id: \d+, status: 200, headers: 5, body_bytes: \d+, tr --- grep_error_log eval: qr/\*\d+.*?\[proxy-wasm\].*?(resuming|freeing).*/ --- grep_error_log_out eval qr/\A\*\d+ .*? filter 1\/1 resuming "on_request_headers" step in "rewrite" phase[^#*]* -\*\d+ .*? filter 1\/1 resuming "on_dispatch_response" step in "access" phase[^#*]* +\*\d+ .*? filter 1\/1 resuming "on_dispatch_response" step in "background" phase[^#*]* \*\d+ .*? filter 1\/1 resuming "on_response_headers" step in "header_filter" phase[^#*]* \*\d+ .*? filter 1\/1 resuming "on_response_body" step in "body_filter" phase[^#*]* \*\d+ .*? filter 1\/1 resuming "on_response_body" step in "body_filter" phase[^#*]* @@ -377,7 +377,7 @@ qr/\A\*\d+ .*? filter 1\/1 resuming "on_request_headers" step in "rewrite" phase --- grep_error_log eval: qr/\*\d+.*?\[proxy-wasm\].*?(resuming|freeing).*/ --- grep_error_log_out eval qr/\A\*\d+ .*? filter 1\/1 resuming "on_request_headers" step in "rewrite" phase[^#*]* -\*\d+ .*? filter 1\/1 resuming "on_dispatch_response" step in "access" phase[^#*]* +\*\d+ .*? filter 1\/1 resuming "on_dispatch_response" step in "background" phase[^#*]* \*\d+ .*? filter chain failed resuming: previous error \(dispatch failure\)[^#*]* \*\d+ .*? filter freeing context #\d+ \(1\/1\)[^#*]*\Z/ diff --git a/t/05-others/010-client_connection_abort.t b/t/05-others/010-client_connection_abort.t index d49637f5a..71111b674 100644 --- a/t/05-others/010-client_connection_abort.t +++ b/t/05-others/010-client_connection_abort.t @@ -4,12 +4,9 @@ use strict; use lib '.'; use t::TestWasm; -if ($ENV{TEST_NGINX_USE_HUP}) { - plan(skip_all => "unavailable in HUP mode"); +skip_hup(); -} else { - plan tests => repeat_each() * (blocks() * 4); -} +plan tests => repeat_each() * (blocks() * 4); run_tests(); diff --git a/t/05-others/011-upstream_connection_abort.t b/t/05-others/011-upstream_connection_abort.t index 86703b0c7..1a17fd98a 100644 --- a/t/05-others/011-upstream_connection_abort.t +++ b/t/05-others/011-upstream_connection_abort.t @@ -4,14 +4,10 @@ use strict; use lib '.'; use t::TestWasm; +skip_hup(); skip_valgrind(); -if ($ENV{TEST_NGINX_USE_HUP}) { - plan(skip_all => "unavailable in HUP mode"); - -} else { - plan tests => repeat_each() * (blocks() * 4); -} +plan tests => repeat_each() * (blocks() * 4); run_tests(); diff --git a/t/TestWasm.pm b/t/TestWasm.pm index 14638bec4..9493a58e2 100644 --- a/t/TestWasm.pm +++ b/t/TestWasm.pm @@ -31,6 +31,7 @@ our @EXPORT = qw( skip_no_debug skip_no_tinygo skip_valgrind + skip_hup ); $ENV{TEST_NGINX_USE_HUP} ||= 0; @@ -64,6 +65,12 @@ sub skip_valgrind (@) { } } +sub skip_hup { + if ($ENV{TEST_NGINX_USE_HUP} == 1) { + plan(skip_all => "skipped in HUP mode"); + } +} + sub skip_no_debug { if ($nginxV !~ m/--with-debug/) { plan(skip_all => "--with-debug required (NGX_BUILD_DEBUG=1)"); diff --git a/t/lib/proxy-wasm-tests/context-checks/Cargo.toml b/t/lib/proxy-wasm-tests/context-checks/Cargo.toml new file mode 100644 index 000000000..65f7feee9 --- /dev/null +++ b/t/lib/proxy-wasm-tests/context-checks/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "context-checks" +version = "0.1.0" +authors = ["Thibault Charbonnier "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +proxy-wasm = "0.2" +log = "0.4" diff --git a/t/lib/proxy-wasm-tests/context-checks/src/hostcalls.rs b/t/lib/proxy-wasm-tests/context-checks/src/hostcalls.rs new file mode 100644 index 000000000..d24c05f30 --- /dev/null +++ b/t/lib/proxy-wasm-tests/context-checks/src/hostcalls.rs @@ -0,0 +1,178 @@ +use crate::*; +use log::*; +use proxy_wasm::types::*; +use std::ptr::null_mut; + +#[allow(improper_ctypes)] +extern "C" { + fn proxy_log(level: u32, message_data: *const u8, message_size: usize) -> Status; +} + +pub fn log_something(_ctx: &TestContext) { + let msg = "proxy_log msg"; + unsafe { + let status = proxy_log(2, msg.as_ptr(), msg.len()); + info!("proxy_log status: {}", status as u32); + } +} + +#[allow(improper_ctypes)] +extern "C" { + fn proxy_set_tick_period_milliseconds(period: u32) -> Status; +} + +pub fn set_tick_period(_ctx: &TestContext) { + unsafe { + let status = proxy_set_tick_period_milliseconds(10000); + info!("set_tick_period status: {}", status as u32); + } +} + +#[allow(improper_ctypes)] +extern "C" { + fn proxy_set_buffer_bytes( + buffer_type: u32, + start: usize, + size: usize, + buffer_data: *const u8, + buffer_size: usize, + ) -> Status; +} + +pub fn set_request_body_buffer(_ctx: &TestContext) { + let v = String::default(); + + unsafe { + let status = proxy_set_buffer_bytes( + BufferType::HttpRequestBody as u32, + 0, + 0, + v.as_ptr(), + v.len(), + ); + + info!("set_request_body_buffer status: {}", status as u32); + } +} + +pub fn set_response_body_buffer(_ctx: &TestContext) { + let v = String::default(); + + unsafe { + let status = proxy_set_buffer_bytes( + BufferType::HttpResponseBody as u32, + 0, + 0, + v.as_ptr(), + v.len(), + ); + + info!("set_response_body_buffer status: {}", status as u32); + } +} + +#[allow(improper_ctypes)] +extern "C" { + fn proxy_get_buffer_bytes( + buffer_type: u32, + start: usize, + max_size: usize, + return_buffer_data: *mut *mut u8, + return_buffer_size: *mut usize, + ) -> Status; +} + +pub fn get_request_body_buffer(_ctx: &TestContext) { + let mut return_data: *mut u8 = null_mut(); + let mut return_size: usize = 0; + + unsafe { + let status = proxy_get_buffer_bytes( + BufferType::HttpRequestBody as u32, + 0, + 0, + &mut return_data, + &mut return_size, + ); + + info!("get_request_body_buffer status: {}", status as u32); + } +} + +pub fn get_response_body_buffer(_ctx: &TestContext) { + let mut return_data: *mut u8 = null_mut(); + let mut return_size: usize = 0; + + unsafe { + let status = proxy_get_buffer_bytes( + BufferType::HttpResponseBody as u32, + 0, + 0, + &mut return_data, + &mut return_size, + ); + + info!("get_response_body_buffer status: {}", status as u32); + } +} + +pub fn get_dispatch_response_body_buffer(_ctx: &TestContext) { + let mut return_data: *mut u8 = null_mut(); + let mut return_size: usize = 0; + + unsafe { + let status = proxy_get_buffer_bytes( + BufferType::HttpCallResponseBody as u32, + 0, + 0, + &mut return_data, + &mut return_size, + ); + + info!( + "get_dispatch_response_body_buffer status: {}", + status as u32 + ); + } +} + +#[allow(improper_ctypes)] +extern "C" { + fn proxy_http_call( + upstream_data: *const u8, + upstream_size: usize, + headers_data: *const u8, + headers_size: usize, + body_data: *const u8, + body_size: usize, + trailers_data: *const u8, + trailers_size: usize, + timeout: u32, + return_token: *mut u32, + ) -> Status; +} + +pub fn dispatch_http_call(_ctx: &TestContext) { + let upstream = ""; + let serialized_headers = ""; + let serialized_trailers = ""; + let body = ""; + let mut return_token: u32 = 0; + + unsafe { + let status = proxy_http_call( + upstream.as_ptr(), + 0, + serialized_headers.as_ptr(), + 0, + body.as_ptr(), + 0, + serialized_trailers.as_ptr(), + 0, + 0, + &mut return_token, + ); + + info!("dispatch_http_call status: {}", status as u32); + } +} diff --git a/t/lib/proxy-wasm-tests/context-checks/src/lib.rs b/t/lib/proxy-wasm-tests/context-checks/src/lib.rs new file mode 100644 index 000000000..8241b1c75 --- /dev/null +++ b/t/lib/proxy-wasm-tests/context-checks/src/lib.rs @@ -0,0 +1,213 @@ +mod hostcalls; + +use crate::hostcalls::*; +use log::*; +use proxy_wasm::{traits::*, types::*}; +use std::collections::HashMap; +use std::time::Duration; + +pub struct TestContext { + config: HashMap, +} + +impl TestContext { + fn get_config(&self, name: &str) -> Option<&str> { + self.config.get(name).map(|s| s.as_str()) + } + + fn check_host_function(&self, name: &str) { + match name { + "proxy_log" => log_something(self), + "set_tick_period" => set_tick_period(self), + "set_request_body_buffer" => set_request_body_buffer(self), + "set_response_body_buffer" => set_response_body_buffer(self), + "get_request_body_buffer" => get_request_body_buffer(self), + "get_response_body_buffer" => get_response_body_buffer(self), + "get_dispatch_response_body_buffer" => get_dispatch_response_body_buffer(self), + "dispatch_http_call" => dispatch_http_call(self), + _ => (), + } + } +} + +struct TestRoot { + tester: TestContext, +} + +struct TestHttp { + tester: TestContext, +} + +proxy_wasm::main! {{ + proxy_wasm::set_log_level(LogLevel::Trace); + proxy_wasm::set_root_context(|_| -> Box { + Box::new(TestRoot { + tester: TestContext { + config: HashMap::new(), + } + }) + }); +}} + +impl HttpContext for TestHttp { + fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action { + if let Some(name) = self.tester.get_config("on_request_headers") { + self.tester.check_host_function(name); + } else if self + .tester + .get_config("on_http_dispatch_response") + .is_some() + { + let _ = self.dispatch_http_call( + self.tester.get_config("host").unwrap_or(""), + vec![(":path", "/dispatch"), (":method", "GET")], + None, + vec![], + Duration::from_secs(0), + ); + + return Action::Pause; + } + + Action::Continue + } + + fn on_http_request_body(&mut self, _: usize, _: bool) -> Action { + if let Some(name) = self.tester.get_config("on_request_body") { + self.tester.check_host_function(name); + } + + Action::Continue + } + + fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action { + if let Some(name) = self.tester.get_config("on_response_headers") { + self.tester.check_host_function(name); + } + + Action::Continue + } + + fn on_http_response_body(&mut self, _: usize, _: bool) -> Action { + if let Some(name) = self.tester.get_config("on_response_body") { + self.tester.check_host_function(name); + } + + Action::Continue + } + + fn on_log(&mut self) { + if let Some(name) = self.tester.get_config("on_log") { + self.tester.check_host_function(name); + } + } +} + +impl Context for TestHttp { + fn on_http_call_response( + &mut self, + token_id: u32, + nheaders: usize, + body_size: usize, + ntrailers: usize, + ) { + let status = self.get_http_call_response_header(":status"); + + info!( + "on_http_call_response (id: {}, status: {}, headers: {}, body_bytes: {}, trailers: {})", + token_id, + status.unwrap_or("".to_string()), + nheaders, + body_size, + ntrailers + ); + + if let Some(name) = self.tester.get_config("on_http_dispatch_response") { + self.tester.check_host_function(name); + } + } +} + +impl RootContext for TestRoot { + fn on_vm_start(&mut self, _: usize) -> bool { + info!("on_vm_start"); + + if let Some(config) = self.get_vm_configuration() { + match std::str::from_utf8(&config) { + Ok(text) => { + info!("vm config: {}", text); + self.tester.check_host_function(text); + } + _ => info!("cannot parse vm config"), + } + } + + true + } + + fn on_configure(&mut self, _: usize) -> bool { + info!("on_configure"); + + if let Some(config_bytes) = self.get_plugin_configuration() { + let config_str = String::from_utf8(config_bytes).unwrap(); + self.tester.config = config_str + .split_whitespace() + .filter_map(|s| s.split_once('=')) + .map(|(k, v)| (k.to_string(), v.to_string())) + .collect(); + } else { + self.tester.config = HashMap::new(); + } + + if self.tester.get_config("on_tick").is_some() { + self.set_tick_period(Duration::from_millis(100)); + } + + if let Some(name) = self.tester.get_config("on_configure") { + self.tester.check_host_function(name); + } + + true + } + + fn on_tick(&mut self) { + info!("on_tick",); + + if let Some(name) = self.tester.get_config("on_tick") { + self.tester.check_host_function(name); + } + } + + fn get_type(&self) -> Option { + Some(ContextType::HttpContext) + } + + fn create_http_context(&self, _: u32) -> Option> { + Some(Box::new(TestHttp { + tester: TestContext { + config: self.tester.config.clone(), + }, + })) + } +} + +impl Context for TestRoot { + fn on_http_call_response( + &mut self, + token_id: u32, + nheaders: usize, + body_size: usize, + ntrailers: usize, + ) { + let status = self.get_http_call_response_header(":status"); + + info!( + "on_root_http_call_response (id: {}, status: {}, headers: {}, body_bytes: {}, trailers: {})", + token_id, status.unwrap_or("".to_string()), nheaders, body_size, ntrailers + ); + + if let Some(name) = self.tester.get_config("on_http_dispatch_response") { + self.tester.check_host_function(name); + } + } +}