From 95a1fbf528f72fba6e204f18ae981222e30d60cb Mon Sep 17 00:00:00 2001 From: Caio Casimiro Date: Wed, 20 Sep 2023 11:58:39 +0100 Subject: [PATCH] wip --- .../hfuncs/102-proxy_send_local_response.t | 4 + t/04-openresty/ffi/103-proxy_wasm_attach.t | 4 + t/05-others/010-connection_drop.t | 335 ++++++++++++++++++ .../proxy-wasm-tests/hostcalls/src/filter.rs | 6 + .../proxy-wasm-tests/on-phases/src/filter.rs | 18 +- 5 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 t/05-others/010-connection_drop.t diff --git a/t/03-proxy_wasm/hfuncs/102-proxy_send_local_response.t b/t/03-proxy_wasm/hfuncs/102-proxy_send_local_response.t index 269e9f5a2..e9f90253e 100644 --- a/t/03-proxy_wasm/hfuncs/102-proxy_send_local_response.t +++ b/t/03-proxy_wasm/hfuncs/102-proxy_send_local_response.t @@ -143,6 +143,7 @@ qr/.*? on_request_headers, 2 headers, .* .*? testing in "RequestHeaders", .* .*? on_response_headers, 5 headers, .* .*? on_response_body, 0 bytes, eof: true, .* +.*? on_done.* .*? on_log.*/ --- no_error_log [error] @@ -248,6 +249,7 @@ qr/.*? on_request_headers, 2 headers, .* .*? testing in "RequestHeaders", .* .*? on_response_headers, 16 headers, .* .*? on_response_body, 0 bytes, eof: true, .* +.*? on_done.* .*? on_log.*/ --- no_error_log [error] @@ -436,7 +438,9 @@ qr/.*? on_request_headers, \d+ headers.* .*? on_response_headers, \d+ headers.* .*? on_response_body, \d+ bytes, eof: true.* .*? on_response_body, \d+ bytes, eof: true.* +.*? on_done.* .*? on_log.* +.*? on_done.* .*? on_log.*/ --- no_error_log [error] diff --git a/t/04-openresty/ffi/103-proxy_wasm_attach.t b/t/04-openresty/ffi/103-proxy_wasm_attach.t index a18828d9c..9b7a0ef9d 100644 --- a/t/04-openresty/ffi/103-proxy_wasm_attach.t +++ b/t/04-openresty/ffi/103-proxy_wasm_attach.t @@ -105,6 +105,7 @@ qr/^[^#]*#0 on_vm_start[^#]* #\d+ on_response_headers, 5 headers[^#]* #\d+ on_response_body, 3 bytes, eof: false[^#]* #\d+ on_response_body, 0 bytes, eof: true[^#]* +#\d+ on_done[^#]* #\d+ on_log[^#]*$/ --- error_log eval qr/\[error\] .*? previous plan already attached/ @@ -156,6 +157,7 @@ qr/^[^#]*#0 on_vm_start[^#]* #\d+ on_response_headers, 5 headers[^#]* #\d+ on_response_body, 3 bytes, eof: false[^#]* #\d+ on_response_body, 0 bytes, eof: true[^#]* +#\d+ on_done[^#]* #\d+ on_log[^#]*$/ --- no_error_log [error] @@ -207,6 +209,7 @@ qr/^[^#]*#0 on_vm_start[^#]* #\d+ on_response_headers, 5 headers[^#]* #\d+ on_response_body, 3 bytes, eof: false[^#]* #\d+ on_response_body, 0 bytes, eof: true[^#]* +#\d+ on_done[^#]* #\d+ on_log[^#]*$/ --- no_error_log [error] @@ -258,6 +261,7 @@ qr/^[^#]*#0 on_vm_start[^#]* #\d+ on_response_headers, 5 headers[^#]* #\d+ on_response_body, 3 bytes, eof: false[^#]* #\d+ on_response_body, 0 bytes, eof: true[^#]* +#\d+ on_done[^#]* #\d+ on_log[^#]*$/ --- no_error_log [error] diff --git a/t/05-others/010-connection_drop.t b/t/05-others/010-connection_drop.t new file mode 100644 index 000000000..e5a5259d5 --- /dev/null +++ b/t/05-others/010-connection_drop.t @@ -0,0 +1,335 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasm; + +plan tests => repeat_each() * (blocks() * 4); + +run_tests(); + +__DATA__ + +=== TEST 1: client connection drop - proxy_wasm & echo, chained filters +Filters executing on the request will have their response entrypoints invoked. + +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: on_phases +--- config + location /t { + proxy_wasm on_phases; + proxy_wasm on_phases; + echo ok; + } +--- shutdown +--- ignore_response +--- grep_error_log eval: qr/#\d+ on_(response|log|done).*/ +--- grep_error_log_out eval +qr/\A#\d+ on_response_headers, 5 headers.* +#\d+ on_response_headers, 5 headers.* +#\d+ on_response_body, 3 bytes, eof: false.* +#\d+ on_response_body, 3 bytes, eof: false.* +#\d+ on_response_body, 0 bytes, eof: true.* +#\d+ on_response_body, 0 bytes, eof: true.* +#\d+ on_done.* +#\d+ on_log.* +#\d+ on_done.* +#\d+ on_log.*\Z/ +--- no_error_log +[error] +[crit] +[emerg] + + + +=== TEST 2: client connection drop - proxy_wasm & proxy_pass, chained filters +Filters executing on the request will have only their on_log and on_done +entrypoints invoked. +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- wasm_modules: on_phases +--- http_config eval +qq{ + server { + listen unix:$ENV{TEST_NGINX_UNIX_SOCKET}; + + location / { + return 200; + } + } +} +--- config + location /t { + proxy_wasm on_phases; + proxy_wasm on_phases; + proxy_pass http://unix:$TEST_NGINX_UNIX_SOCKET:/; + } +--- shutdown +--- ignore_response +--- grep_error_log eval: qr/\[info\] .*? on_(response|log|done).*/ +--- grep_error_log_out eval +qr/\[info\] .*? on_done.* +\[info\] .*? on_log.*/ +--- no_error_log eval +[ + qr/\[info\] .*? on_response.*/, + "[error]", + "[crit]" +] + + + +=== TEST 3: client connection drop - proxy_wasm & dispatch_http_call(), chained filters +Filters executing on the request and that have dispatched HTTP calls will +have their on_http_call_response entrypoint invoked. +--- skip_eval: 4: $ENV{TEST_NGINX_USE_HUP} == 1 +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: hostcalls +--- http_config eval +qq{ + server { + listen unix:$ENV{TEST_NGINX_UNIX_SOCKET}; + + location /status/200 { + return 200; + } + + location /status/201 { + return 201; + } + } +} +--- config + location /t { + proxy_wasm hostcalls 'test=/t/dispatch_http_call \ + host=unix:$TEST_NGINX_UNIX_SOCKET \ + path=/status/200'; + proxy_wasm hostcalls 'test=/t/dispatch_http_call \ + host=unix:$TEST_NGINX_UNIX_SOCKET \ + path=/status/201'; + echo ok; + } +--- shutdown +--- ignore_response +--- grep_error_log eval: qr/\*\d+.*?on_http_call_response.*/ +--- grep_error_log_out eval +qr/\A\*\d+ .*? on_http_call_response \(id: \d+, status: 200[^*].* +\*\d+ .*? on_http_call_response \(id: \d+, status: 201[^*].*\Z/ +--- no_error_log +[error] +[crit] +[emerg] + + + +=== TEST 4: client connection drop - proxy_wasm, send_local_response() +Filters running on the same request will have their response entrypoints invoked. +--- wasm_modules: hostcalls on_phases +--- config + location /t { + proxy_wasm on_phases; + proxy_wasm hostcalls 'test=/t/send_local_response/body'; + proxy_wasm on_phases; + } +--- shutdown +--- ignore_response +--- grep_error_log eval: qr/\[info\] .*? on_(response|log|done).*/ +--- grep_error_log_out eval +qr/.*\["hostcalls" #1\].* on_response_headers.* +.*\["on_phases" #2\].* on_response_headers.* +.*\["on_phases" #1\].* on_response_body.* +.*\["hostcalls" #1\].* on_response_body.* +.*\["on_phases" #2\].* on_response_body.* +.*\["on_phases" #1\].* on_done.* +.*\["on_phases" #1\].* on_log.* +.*\["hostcalls" #1\].* on_done.* +.*\["hostcalls" #1\].* on_log.* +.*\["on_phases" #2\].* on_done.* +.*\["on_phases" #2\].* on_log.*/ +--- no_error_log eval +[ + qr/.*\["on_phases" #1\].* on_response_headers.*/, + "[error]", + "[crit]", +] + + + +=== TEST 5: client connection drop - wasm_call & echo, wasm_filter +Wasm functions configured to execute on content/header_filter/body_filter phases +will be invoked. +--- skip_no_debug: 4 +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: ngx_rust_tests +--- config + location /t { + wasm_call content ngx_rust_tests log_notice_hello; + wasm_call header_filter ngx_rust_tests log_notice_hello; + wasm_call body_filter ngx_rust_tests log_notice_hello; + echo ok; + } +--- shutdown +--- ignore_response +--- grep_error_log eval: qr/\[debug\] .*? \*\d wasm ops calling .* in .* phase.*/ +--- grep_error_log_out eval +qr/\A.* wasm ops calling "ngx_rust_tests.log_notice_hello" in "content" phase.* +.* wasm ops calling "ngx_rust_tests.log_notice_hello" in "header_filter" phase.* +.* wasm ops calling "ngx_rust_tests.log_notice_hello" in "body_filter" phase.* +.* wasm ops calling "ngx_rust_tests.log_notice_hello" in "body_filter" phase.*\Z/ +--- no_error_log +[error] +[crit] +[emerg] + + + +=== TEST 6: client connection drop - wasm_call & proxy_pass, wasm_filter +Only wasm functions configured to execute in content phase will be invoked. +--- skip_no_debug: 4 +--- wasm_modules: ngx_rust_tests +--- http_config eval +qq{ + server { + listen unix:$ENV{TEST_NGINX_UNIX_SOCKET}; + + location / { + return 201; + } + } +} +--- config + location /t { + wasm_call content ngx_rust_tests log_notice_hello; + wasm_call header_filter ngx_rust_tests log_notice_hello; + wasm_call body_filter ngx_rust_tests log_notice_hello; + proxy_pass http://unix:$TEST_NGINX_UNIX_SOCKET:/; + } +--- shutdown +--- ignore_response +--- grep_error_log eval: qr/\[debug\] .*? \*\d wasm ops calling .* in .* phase.*/ +--- grep_error_log_out eval +qr/\[debug\] .* wasm ops calling "ngx_rust_tests.log_notice_hello" in "content" phase.*/ +--- no_error_log eval +[ + qr/\[debug\] .* wasm ops calling .* in "(header_filter|body_filter)" phase.*/, + "[error]", + "[crit]", +] + + + +=== TEST 7: upstream connection drop - proxy_wasm & proxy_pass, chained filters +Client receives a 502 response, all response phases are invoked. +--- wasm_modules: on_phases +--- tcp_listen: $TEST_NGINX_UNIX_SOCKET +--- tcp_shutdown: 2 +--- tcp_reply eval +sub { + return ["HTTP/1.1 100 OK\r\n", + "Connection: close\r\n", + "Content-Length: 0\r\n", + "\r\n"]; +} +--- config + location /t { + proxy_wasm on_phases; + proxy_wasm on_phases; + proxy_pass http://unix:$TEST_NGINX_UNIX_SOCKET:/; + } +--- error_code: 502 +--- grep_error_log eval: qr/\[info\] .*? on_(response|log|done).*/ +--- grep_error_log_out eval +qr/\A.*?\["on_phases" #1\].*? on_response_headers.* +.*?\["on_phases" #2\].*? on_response_headers.* +.*?\["on_phases" #1\].*? on_response_body.* +.*?\["on_phases" #2\].*? on_response_body.* +.*?\["on_phases" #1\].*? on_done.* +.*?\["on_phases" #1\].*? on_log.* +.*?\["on_phases" #2\].*? on_done.* +.*?\["on_phases" #2\].*? on_log.*\Z/ +--- no_error_log +[crit] +[emerg] + + + +=== TEST 8: upstream connection drop - proxy_wasm - dispatch_http_call(), on_request_headers +on_http_call_response is invoked along with all response entrypoints. +--- skip_valgrind: 4 +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: hostcalls +--- tcp_listen: $TEST_NGINX_UNIX_SOCKET +--- tcp_shutdown: 2 +--- tcp_reply eval +sub { + return ["HTTP/1.1 100 OK\r\n", + "Connection: close\r\n", + "Content-Length: 0\r\n", + "\r\n"]; +} +--- config + location /t { + proxy_wasm hostcalls 'test=/t/dispatch_http_call \ + host=unix:$TEST_NGINX_UNIX_SOCKET'; + proxy_wasm hostcalls; + echo ok; + } +--- grep_error_log eval: qr/\[info\] .*? on_(http_call_response|response|log|done).*/ +--- grep_error_log_out eval +qr/\A.* on_http_call_response \(id: 0, status: , headers: 0, body_bytes: 0, trailers: 0, op: \).* +.* on_response_headers.* +.* on_response_headers.* +.* on_response_body.* +.* on_response_body.* +.* on_response_body.* +.* on_response_body.* +.* on_done.* +.* on_log.* +.* on_done.* +.* on_log.*\Z/ +--- no_error_log +[crit] +[emerg] + + + +=== TEST 9: upstream connection drop - proxy_wasm - dispatch_http_call(), on_request_body +on_http_call_response is invoked along with all response entrypoints. +--- skip_valgrind: 4 +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: hostcalls +--- tcp_listen: $TEST_NGINX_UNIX_SOCKET +--- tcp_shutdown: 2 +--- tcp_reply eval +sub { + return ["HTTP/1.1 100 OK\r\n", + "Connection: close\r\n", + "Content-Length: 0\r\n", + "\r\n"]; +} +--- config + location /t { + proxy_wasm hostcalls 'on=request_body \ + test=/t/dispatch_http_call \ + host=unix:$TEST_NGINX_UNIX_SOCKET'; + proxy_wasm hostcalls; + echo ok; + } +--- request +POST /t +Hello world +--- grep_error_log eval: qr/\[info\] .*? on_(http_call_response|response|log|done).*/ +--- grep_error_log_out eval +qr/\A.* on_http_call_response \(id: 0, status: , headers: 0, body_bytes: 0, trailers: 0, op: \).* +.* on_response_headers.* +.* on_response_headers.* +.* on_response_body.* +.* on_response_body.* +.* on_response_body.* +.* on_response_body.* +.* on_done.* +.* on_log.* +.* on_done.* +.* on_log.*\Z/ +--- no_error_log +[crit] +[emerg] diff --git a/t/lib/proxy-wasm-tests/hostcalls/src/filter.rs b/t/lib/proxy-wasm-tests/hostcalls/src/filter.rs index 3c305ee85..3c61dcc14 100644 --- a/t/lib/proxy-wasm-tests/hostcalls/src/filter.rs +++ b/t/lib/proxy-wasm-tests/hostcalls/src/filter.rs @@ -105,6 +105,12 @@ impl Context for TestHttp { self.resume_http_request() } + + fn on_done(&mut self) -> bool { + info!("[hostcalls] on_done"); + + true + } } impl HttpContext for TestHttp { diff --git a/t/lib/proxy-wasm-tests/on-phases/src/filter.rs b/t/lib/proxy-wasm-tests/on-phases/src/filter.rs index 447cc1367..11fc304c3 100644 --- a/t/lib/proxy-wasm-tests/on-phases/src/filter.rs +++ b/t/lib/proxy-wasm-tests/on-phases/src/filter.rs @@ -109,7 +109,23 @@ impl OnPhases { } } -impl Context for OnPhases {} +impl Context for OnPhases { + fn on_done(&mut self) -> bool { + info!("#{} on_done", self.context_id); + + let log_msg = self + .config + .get("log_msg") + .map_or(String::new(), |s| s.to_string()); + + if !log_msg.is_empty() { + info!("#{} log_msg: {}", self.context_id, log_msg); + } + + true + } +} + impl HttpContext for OnPhases { fn on_http_request_headers(&mut self, nheaders: usize, _eof: bool) -> Action { info!(