You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2022/03/07 02:13:08 UTC
[apisix] branch master updated: feat(Wasm): get response body (#6514)
This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new fede22e feat(Wasm): get response body (#6514)
fede22e is described below
commit fede22edb50b70a54f59f6ca244bc48c46ca93de
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Mon Mar 7 10:13:05 2022 +0800
feat(Wasm): get response body (#6514)
---
apisix/cli/ngx_tpl.lua | 1 +
apisix/wasm.lua | 35 +++++++++++++++
docs/en/latest/wasm.md | 1 +
t/APISIX.pm | 1 +
t/wasm/response-rewrite.t | 98 +++++++++++++++++++++++++++++++++++++++++
t/wasm/response-rewrite/main.go | 25 +++++++++++
6 files changed, 161 insertions(+)
diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua
index 186884f..aaac144 100644
--- a/apisix/cli/ngx_tpl.lua
+++ b/apisix/cli/ngx_tpl.lua
@@ -621,6 +621,7 @@ http {
{% if wasm then %}
set $wasm_process_req_body '';
+ set $wasm_process_resp_body '';
{% end %}
# http server location configuration snippet starts
diff --git a/apisix/wasm.lua b/apisix/wasm.lua
index d406089..56a44b8 100644
--- a/apisix/wasm.lua
+++ b/apisix/wasm.lua
@@ -112,6 +112,37 @@ local function header_filter_wrapper(self, conf, ctx)
core.log.error(name, ": failed to run wasm plugin: ", err)
return 503
end
+
+ -- $wasm_process_resp_body is predefined in ngx_tpl.lua
+ local handle_body = ngx_var.wasm_process_resp_body
+ if handle_body ~= '' then
+ -- reset the flag so we can use it for the next Wasm plugin
+ -- use ngx.var to bypass the cache
+ ngx_var.wasm_process_resp_body = ""
+ ctx["wasm_" .. name .. "_process_resp_body"] = true
+ end
+end
+
+
+local function body_filter_wrapper(self, conf, ctx)
+ local name = self.name
+
+ local enabled = ctx["wasm_" .. name .. "_process_resp_body"]
+ if not enabled then
+ return
+ end
+
+ local plugin_ctx, err = fetch_plugin_ctx(conf, ctx, self.plugin)
+ if not plugin_ctx then
+ core.log.error(name, ": failed to fetch wasm plugin ctx: ", err)
+ return
+ end
+
+ local ok, err = wasm.on_http_response_body(plugin_ctx)
+ if not ok then
+ core.log.error(name, ": failed to run wasm plugin: ", err)
+ return
+ end
end
@@ -151,6 +182,10 @@ function _M.require(attrs)
return header_filter_wrapper(mod, conf, ctx)
end
+ mod.body_filter = function (conf, ctx)
+ return body_filter_wrapper(mod, conf, ctx)
+ end
+
-- the returned values need to be the same as the Lua's 'require'
return true, mod
end
diff --git a/docs/en/latest/wasm.md b/docs/en/latest/wasm.md
index 52089dd..f0579c5 100644
--- a/docs/en/latest/wasm.md
+++ b/docs/en/latest/wasm.md
@@ -103,6 +103,7 @@ For example, when the first request hits the route which has Wasm plugin configu
* `proxy_on_http_request_headers`: run in the access/rewrite phase, depends on the configuration of `http_request_phase`.
* `proxy_on_http_request_body`: run in the same phase of `proxy_on_http_request_headers`. To run this callback, we need to set property `wasm_process_req_body` to non-empty value in `proxy_on_http_request_headers`. See `t/wasm/request-body/main.go` as an example.
* `proxy_on_http_response_headers`: run in the header_filter phase.
+* `proxy_on_http_response_body`: run in the body_filter phase. To run this callback, we need to set property `wasm_process_resp_body` to non-empty value in `proxy_on_http_response_headers`. See `t/wasm/response-rewrite/main.go` as an example.
## Example
diff --git a/t/APISIX.pm b/t/APISIX.pm
index bcd8daf..671ffe3 100644
--- a/t/APISIX.pm
+++ b/t/APISIX.pm
@@ -222,6 +222,7 @@ my $a6_ngx_vars = "";
if ($version =~ m/\/apisix-nginx-module/) {
$a6_ngx_vars = <<_EOC_;
set \$wasm_process_req_body '';
+ set \$wasm_process_resp_body '';
_EOC_
}
diff --git a/t/wasm/response-rewrite.t b/t/wasm/response-rewrite.t
index 250a07c..15b9bd1 100644
--- a/t/wasm/response-rewrite.t
+++ b/t/wasm/response-rewrite.t
@@ -42,6 +42,9 @@ wasm:
- name: wasm-response-rewrite
priority: 7997
file: t/wasm/response-rewrite/main.go.wasm
+ - name: wasm-response-rewrite2
+ priority: 7996
+ file: t/wasm/response-rewrite/main.go.wasm
_EOC_
$block->set_value("extra_yaml_config", $extra_yaml_config);
});
@@ -92,3 +95,98 @@ passed
GET /hello
--- response_headers
x-wasm: apisix
+
+
+
+=== TEST 3: log response body
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello",
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:1980": 1
+ }
+ },
+ "plugins": {
+ "wasm-response-rewrite": {
+ "conf": "{\"body\":\"a\"}"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 4: hit
+--- request
+GET /hello
+--- grep_error_log eval
+qr/get body .+/
+--- grep_error_log_out
+get body [hello world
+
+
+
+=== TEST 5: ensure the process body flag is plugin independent
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello",
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:1980": 1
+ }
+ },
+ "plugins": {
+ "wasm-response-rewrite": {
+ "conf": "{\"body\":\"a\"}"
+ },
+ "wasm-response-rewrite2": {
+ "conf": "{\"headers\":[{\"name\":\"x-wasm\",\"value\":\"apisix\"}]}"
+ }
+ }
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 6: hit
+--- request
+GET /hello
+--- grep_error_log eval
+qr/get body .+/
+--- grep_error_log_out
+get body [hello world
diff --git a/t/wasm/response-rewrite/main.go b/t/wasm/response-rewrite/main.go
index 41fa7b1..fb7b184 100644
--- a/t/wasm/response-rewrite/main.go
+++ b/t/wasm/response-rewrite/main.go
@@ -44,6 +44,7 @@ type header struct {
type pluginContext struct {
types.DefaultPluginContext
Headers []header
+ Body []byte
}
func (ctx *pluginContext) OnPluginStart(pluginConfigurationSize int) types.OnPluginStartStatus {
@@ -68,6 +69,9 @@ func (ctx *pluginContext) OnPluginStart(pluginConfigurationSize int) types.OnPlu
}
}
+ body := v.GetStringBytes("body")
+ ctx.Body = body
+
return types.OnPluginStartStatusOK
}
@@ -85,5 +89,26 @@ func (ctx *httpContext) OnHttpResponseHeaders(numHeaders int, endOfStream bool)
for _, hdr := range plugin.Headers {
proxywasm.ReplaceHttpResponseHeader(hdr.Name, hdr.Value)
}
+
+ if len(plugin.Body) > 0 {
+ proxywasm.SetProperty([]string{"wasm_process_resp_body"}, []byte("true"))
+ }
+
+ return types.ActionContinue
+}
+
+func (ctx *httpContext) OnHttpResponseBody(bodySize int, endOfStream bool) types.Action {
+ plugin := ctx.parent
+
+ if len(plugin.Body) > 0 && !endOfStream {
+ // TODO support changing body
+ body, err := proxywasm.GetHttpResponseBody(0, bodySize)
+ if err != nil {
+ proxywasm.LogErrorf("failed to get body: %v", err)
+ return types.ActionContinue
+ }
+ proxywasm.LogWarnf("get body [%s]", string(body))
+ }
+
return types.ActionContinue
}