From 76092d42ac3783e66f65be359214f855be0dd649 Mon Sep 17 00:00:00 2001 From: Caio Ramos Casimiro Date: Fri, 4 Aug 2023 11:53:51 +0100 Subject: [PATCH] feat(*) wasm_socket unix domain socket support --- .../proxy_wasm/ngx_http_proxy_wasm_dispatch.c | 33 +++++++ .../hfuncs/130-proxy_dispatch_http.t | 95 +++++++++++++------ 2 files changed, 100 insertions(+), 28 deletions(-) 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 97d9d3100..9c3d09fac 100644 --- a/src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c +++ b/src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c @@ -150,6 +150,9 @@ ngx_http_proxy_wasm_dispatch(ngx_proxy_wasm_exec_t *pwexec, ngx_http_wasm_req_ctx_t *rctxp = NULL; ngx_http_proxy_wasm_dispatch_t *call = NULL; unsigned enable_ssl = 0; +#if (NGX_HAVE_UNIX_DOMAIN) + static ngx_str_t uds_prefix = ngx_string("unix:"); +#endif /* rctx or fake request */ @@ -240,11 +243,24 @@ ngx_http_proxy_wasm_dispatch(ngx_proxy_wasm_exec_t *pwexec, } } +#if (NGX_HAVE_UNIX_DOMAIN) + if (host->len < uds_prefix.len || + !ngx_str_eq(p, uds_prefix.len, uds_prefix.data, uds_prefix.len)) + { + p = ngx_strlchr(p, last, ':'); + + if (p) { + port = ngx_atoi(p + 1, last - p); + } + + } +#else p = ngx_strlchr(p, last, ':'); if (p) { port = ngx_atoi(p + 1, last - p); } +#endif /* headers/trailers */ @@ -606,7 +622,24 @@ ngx_http_proxy_wasm_dispatch_request(ngx_http_proxy_wasm_dispatch_t *call) b->last = ngx_cpymem(b->last, ngx_http_proxy_wasm_host, sizeof(ngx_http_proxy_wasm_host) - 1); + +#if (NGX_HAVE_UNIX_DOMAIN) + static ngx_str_t uds = ngx_string("unix:"); + static ngx_str_t localhost = ngx_string("localhost"); + + if (call->authority.len > uds.len + && ngx_str_eq(call->authority.data, uds.len, uds.data, uds.len)) + { + b->last = ngx_cpymem(b->last, localhost.data, localhost.len); + + } else { + b->last = ngx_cpymem(b->last, call->authority.data, + call->authority.len); + } +#else b->last = ngx_cpymem(b->last, call->authority.data, call->authority.len); +#endif + *b->last++ = CR; *b->last++ = LF; 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 f9a4f7ec1..fad743395 100644 --- a/t/03-proxy_wasm/hfuncs/130-proxy_dispatch_http.t +++ b/t/03-proxy_wasm/hfuncs/130-proxy_dispatch_http.t @@ -263,7 +263,46 @@ Hello back -=== TEST 14: proxy_wasm - dispatch_http_call() resolver + hostname (IPv4) +=== TEST 14: proxy_wasm - dispatch_http_call() unix domain socket +--- backtraces: on +--- load_nginx_modules: ngx_http_echo_module +--- wasm_modules: hostcalls +--- http_config +server { + listen unix:/tmp/nginx.sock; + server_name localhost; + + location /headers { + echo $echo_client_request_headers; + } +} +--- config eval +qq{ + resolver $::ExtResolver ipv6=off; + resolver_timeout $::ExtTimeout; + resolver_add 127.0.0.1 localhost; + + location /t { + proxy_wasm hostcalls 'test=/t/dispatch_http_call \ + host=unix:/tmp/nginx.sock \ + headers=X-Thing:foo|X-Thing:bar|Hello:world + path=/headers \ + on_http_call_response=echo_response_body'; + echo fail; + } +} +--- response_body_like +.*? +\s*X-Thing: foo\s* +\s*X-Thing: bar\s* +\s*Hello: world\s* +--- no_error_log +[error] +[crit] + + + +=== TEST 15: proxy_wasm - dispatch_http_call() resolver + hostname (IPv4) Needs IPv4 resolution + external I/O to succeed. Succeeds on: - HTTP 200 (httpbin.org/headers success) @@ -297,7 +336,7 @@ qq{ -=== TEST 15: proxy_wasm - dispatch_http_call() resolver + hostname (IPv6), default port +=== TEST 16: proxy_wasm - dispatch_http_call() resolver + hostname (IPv6), default port Disabled on GitHub Actions due to IPv6 constraint. --- skip_eval: 4: system("ping6 -c 1 ::1 >/dev/null 2>&1") ne 0 || defined $ENV{GITHUB_ACTIONS} --- timeout eval: $::ExtTimeout @@ -324,7 +363,7 @@ qq{ -=== TEST 16: proxy_wasm - dispatch_http_call() resolver + hostname (IPv4) + port +=== TEST 17: proxy_wasm - dispatch_http_call() resolver + hostname (IPv4) + port --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- http_config @@ -361,7 +400,7 @@ qq{ -=== TEST 17: proxy_wasm - dispatch_http_call() resolver error (host not found) +=== TEST 18: proxy_wasm - dispatch_http_call() resolver error (host not found) --- timeout eval: $::ExtTimeout --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -385,7 +424,7 @@ qr/(\[error\]|Uncaught RuntimeError|\s+).*?dispatch failed: tcp socket - resolve -=== TEST 18: proxy_wasm - dispatch_http_call() IP + port (IPv4) +=== TEST 19: proxy_wasm - dispatch_http_call() IP + port (IPv4) --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -408,7 +447,7 @@ ok -=== TEST 19: proxy_wasm - dispatch_http_call() IP + port (IPv6) +=== TEST 20: proxy_wasm - dispatch_http_call() IP + port (IPv6) --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -433,7 +472,7 @@ ok -=== TEST 20: proxy_wasm - dispatch_http_call() many request headers (> 10) +=== TEST 21: proxy_wasm - dispatch_http_call() many request headers (> 10) --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -471,7 +510,7 @@ K: 11.* -=== TEST 21: proxy_wasm - dispatch_http_call() empty response body (HTTP 204) +=== TEST 22: proxy_wasm - dispatch_http_call() empty response body (HTTP 204) --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -500,7 +539,7 @@ tcp socket closing -=== TEST 22: proxy_wasm - dispatch_http_call() empty response body (Content-Length: 0) +=== TEST 23: proxy_wasm - dispatch_http_call() empty response body (Content-Length: 0) --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module ngx_http_headers_more_filter_module --- wasm_modules: hostcalls @@ -528,7 +567,7 @@ tcp socket closing -=== TEST 23: proxy_wasm - dispatch_http_call() no response body (HEAD) +=== TEST 24: proxy_wasm - dispatch_http_call() no response body (HEAD) --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -558,7 +597,7 @@ tcp socket closing -=== TEST 24: proxy_wasm - dispatch_http_call() "Content-Length" response body +=== TEST 25: proxy_wasm - dispatch_http_call() "Content-Length" response body --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -581,7 +620,7 @@ Hello world -=== TEST 25: proxy_wasm - dispatch_http_call() "Transfer-Encoding: chunked" response body +=== TEST 26: proxy_wasm - dispatch_http_call() "Transfer-Encoding: chunked" response body --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -606,7 +645,7 @@ Content-Length: 0.* -=== TEST 26: proxy_wasm - dispatch_http_call() large response +=== TEST 27: proxy_wasm - dispatch_http_call() large response --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -632,7 +671,7 @@ Content-Length: 0.* -=== TEST 27: proxy_wasm - dispatch_http_call() small wasm_socket_buffer_size +=== TEST 28: proxy_wasm - dispatch_http_call() small wasm_socket_buffer_size --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -660,7 +699,7 @@ tcp socket trying to receive data (max: 1) -=== TEST 28: proxy_wasm - dispatch_http_call() small wasm_socket_large_buffers +=== TEST 29: proxy_wasm - dispatch_http_call() small wasm_socket_large_buffers --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -687,7 +726,7 @@ Hello world -=== TEST 29: proxy_wasm - dispatch_http_call() too small wasm_socket_large_buffers +=== TEST 30: proxy_wasm - dispatch_http_call() too small wasm_socket_large_buffers --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -715,7 +754,7 @@ tcp socket - upstream response headers too large, increase wasm_socket_large_buf -=== TEST 30: proxy_wasm - dispatch_http_call() too small wasm_socket_large_buffers size +=== TEST 31: proxy_wasm - dispatch_http_call() too small wasm_socket_large_buffers size --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -743,7 +782,7 @@ tcp socket - upstream response headers too large, increase wasm_socket_large_buf -=== TEST 31: proxy_wasm - dispatch_http_call() not enough wasm_socket_large_buffers +=== TEST 32: proxy_wasm - dispatch_http_call() not enough wasm_socket_large_buffers --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- tcp_listen: 12345 @@ -774,7 +813,7 @@ sub { -=== TEST 32: proxy_wasm - dispatch_http_call() scarce wasm_socket_large_buffers +=== TEST 33: proxy_wasm - dispatch_http_call() scarce wasm_socket_large_buffers --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -802,7 +841,7 @@ tcp socket trying to receive data (max: 1023) -=== TEST 33: proxy_wasm - dispatch_http_call() TCP reader error +=== TEST 34: proxy_wasm - dispatch_http_call() TCP reader error --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- tcp_listen: 12345 @@ -826,7 +865,7 @@ qr/(\[error\]|Uncaught RuntimeError|\s+).*?dispatch failed: tcp socket - parser -=== TEST 34: proxy_wasm - dispatch_http_call() re-entrant after status line +=== TEST 35: proxy_wasm - dispatch_http_call() re-entrant after status line --- skip_no_debug: 4 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -854,7 +893,7 @@ tcp socket trying to receive data (max: 1017) -=== TEST 35: proxy_wasm - dispatch_http_call() trap in dispatch handler +=== TEST 36: proxy_wasm - dispatch_http_call() trap in dispatch handler --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -879,7 +918,7 @@ tcp socket trying to receive data (max: 1017) -=== TEST 36: proxy_wasm - dispatch_http_call() invalid response headers +=== TEST 37: proxy_wasm - dispatch_http_call() invalid response headers --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- tcp_listen: 12345 @@ -905,7 +944,7 @@ qr/(\[error\]|Uncaught RuntimeError|\s+).*?dispatch failed: tcp socket - parser -=== TEST 37: proxy_wasm - dispatch_http_call() async dispatch x2 +=== TEST 38: proxy_wasm - dispatch_http_call() async dispatch x2 --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -953,7 +992,7 @@ qr/(\[error\]|Uncaught RuntimeError|\s+).*?dispatch failed: tcp socket - parser -=== TEST 38: proxy_wasm - dispatch_http_call() can be chained by different filters +=== TEST 39: proxy_wasm - dispatch_http_call() can be chained by different filters So long as these filters do not produce content. --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls @@ -986,7 +1025,7 @@ qr/^\*\d+ .*? on_http_call_response \(id: \d+[^*]* -=== TEST 39: proxy_wasm - dispatch_http_call() on log step +=== TEST 40: proxy_wasm - dispatch_http_call() on log step --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -1010,7 +1049,7 @@ qr/(\[error\]|Uncaught RuntimeError|\s+).*?dispatch failed: bad step/ -=== TEST 40: proxy_wasm - dispatch_http_call() supports get_http_call_response_headers() +=== TEST 41: proxy_wasm - dispatch_http_call() supports get_http_call_response_headers() --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config @@ -1034,7 +1073,7 @@ X-Callout-Header: callout-header-value -=== TEST 41: proxy_wasm - dispatch_http_call() get :status dispatch response header +=== TEST 42: proxy_wasm - dispatch_http_call() get :status dispatch response header --- load_nginx_modules: ngx_http_echo_module --- wasm_modules: hostcalls --- config