This is an automated email from the ASF dual-hosted git repository.
monkeydluffy 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 ab67b095b feat(response-rewrite): support brotli when use
filters.regex option (#10733)
ab67b095b is described below
commit ab67b095bf7200274b37af5c589fc093858d98e8
Author: yuweizzz <[email protected]>
AuthorDate: Thu Jan 4 14:47:22 2024 +0800
feat(response-rewrite): support brotli when use filters.regex option
(#10733)
---
apisix/plugins/response-rewrite.lua | 59 +++++++++
t/plugin/response-rewrite3.t | 246 +++++++++++++++++++++++++++++++++++-
2 files changed, 303 insertions(+), 2 deletions(-)
diff --git a/apisix/plugins/response-rewrite.lua
b/apisix/plugins/response-rewrite.lua
index d9aa816ce..ee9746fa3 100644
--- a/apisix/plugins/response-rewrite.lua
+++ b/apisix/plugins/response-rewrite.lua
@@ -29,6 +29,7 @@ local type = type
local pcall = pcall
local zlib = require("ffi-zlib")
local str_buffer = require("string.buffer")
+local is_br_libs_loaded, brotli = pcall(require, "brotli")
local lrucache = core.lrucache.new({
@@ -227,6 +228,58 @@ local function inflate_gzip(data)
end
+local function brotli_stream_decode(read_inputs, write_outputs)
+ -- read 64k data per times
+ local read_size = 64 * 1024
+ local decompressor = brotli.decompressor:new()
+
+ local chunk, ok, res
+ repeat
+ chunk = read_inputs(read_size)
+ if chunk then
+ ok, res = pcall(function()
+ return decompressor:decompress(chunk)
+ end)
+ else
+ ok, res = pcall(function()
+ return decompressor:finish()
+ end)
+ end
+ if not ok then
+ return false, res
+ end
+ write_outputs(res)
+ until not chunk
+
+ return true, nil
+end
+
+
+local function brotli_decode(data)
+ local inputs = str_buffer.new():set(data)
+ local outputs = str_buffer.new()
+
+ local read_inputs = function(size)
+ local data = inputs:get(size)
+ if data == "" then
+ return nil
+ end
+ return data
+ end
+
+ local write_outputs = function(data)
+ return outputs:put(data)
+ end
+
+ local ok, err = brotli_stream_decode(read_inputs, write_outputs)
+ if not ok then
+ return nil, err
+ end
+
+ return outputs:get()
+end
+
+
function _M.check_schema(conf)
local ok, err = core.schema.check(schema, conf)
if not ok then
@@ -294,6 +347,12 @@ function _M.body_filter(conf, ctx)
core.log.error("filters may not work as expected, inflate gzip
err: ", err)
return
end
+ elseif ctx.response_encoding == "br" and is_br_libs_loaded then
+ body, err = brotli_decode(body)
+ if err ~= nil then
+ core.log.error("filters may not work as expected, brotli
decode err: ", err)
+ return
+ end
elseif ctx.response_encoding ~= nil then
core.log.error("filters may not work as expected ",
"due to unsupported compression encoding type: ",
diff --git a/t/plugin/response-rewrite3.t b/t/plugin/response-rewrite3.t
index 904508cc8..dc43074f2 100644
--- a/t/plugin/response-rewrite3.t
+++ b/t/plugin/response-rewrite3.t
@@ -53,6 +53,45 @@ add_block_preprocessor(sub {
}
}
}
+
+ server {
+ listen 11452;
+ location /brotli_hello {
+ content_by_lua_block {
+ ngx.req.read_body()
+ local s = "hello world hello world hello world"
+ ngx.header['Content-Length'] = #s + 1
+ ngx.say(s)
+ }
+ header_filter_by_lua_block {
+ local conf = {
+ comp_level = 6,
+ http_version = 1.1,
+ lgblock = 0,
+ lgwin = 19,
+ min_length = 1,
+ mode = 0,
+ types = "*",
+ }
+ local brotli = require("apisix.plugins.brotli")
+ brotli.header_filter(conf, ngx.ctx)
+ }
+ body_filter_by_lua_block {
+ local conf = {
+ comp_level = 6,
+ http_version = 1.1,
+ lgblock = 0,
+ lgwin = 19,
+ min_length = 1,
+ mode = 0,
+ types = "*",
+ }
+ local brotli = require("apisix.plugins.brotli")
+ brotli.body_filter(conf, ngx.ctx)
+ }
+ }
+ }
+
_EOC_
$block->set_value("http_config", $http_config);
@@ -238,7 +277,6 @@ Content-Encoding:
if code >= 300 then
ngx.status = code
- return
end
ngx.say(body)
}
@@ -296,7 +334,6 @@ Content-Encoding:
if code >= 300 then
ngx.status = code
- return
end
ngx.say(body)
}
@@ -433,3 +470,208 @@ Content-Encoding: deflate
X-Server-id: 3
X-Server-status: on
Content-Type:
+
+
+
+=== TEST 15: set route use brotli upstream
+--- 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": "/brotli_hello",
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:11452": 1
+ },
+ "type": "roundrobin"
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 16: should return brotli body
+--- request
+GET /brotli_hello
+--- more_headers
+Accept-Encoding: br
+--- response_headers
+Content-Encoding: br
+
+
+
+=== TEST 17: set route use brotli upstream and response-rewrite body conf
+--- 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": "/brotli_hello",
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:11452": 1
+ },
+ "type": "roundrobin"
+ },
+ "plugins": {
+ "response-rewrite": {
+ "vars": [
+ ["status","==",200]
+ ],
+ "body": "new body\n"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 18: should rewrite body and clear Content-Encoding header
+--- request
+GET /brotli_hello
+--- more_headers
+Accept-Encoding: br
+--- response_body
+new body
+--- response_headers
+Content-Encoding:
+
+
+
+=== TEST 19: set route use brotli upstream and response-rewrite filter conf
+--- 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": "/brotli_hello",
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:11452": 1
+ },
+ "type": "roundrobin"
+ },
+ "plugins": {
+ "response-rewrite": {
+ "vars": [
+ ["status","==",200]
+ ],
+ "filters": [
+ {
+ "regex": "hello",
+ "replace": "test"
+ }
+ ]
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 20: brotli decode support, should rewrite body and clear
Content-Encoding header
+--- request
+GET /brotli_hello
+--- more_headers
+Accept-Encoding: br
+--- response_body
+test world hello world hello world
+--- response_headers
+Content-Encoding:
+
+
+
+=== TEST 21: set route use response-write plugin but not use filter conf or
body conf
+--- 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": "/brotli_hello",
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:11452": 1
+ },
+ "type": "roundrobin"
+ },
+ "plugins": {
+ "response-rewrite": {
+ "vars": [
+ ["status","==",200]
+ ],
+ "headers": {
+ "set": {
+ "X-Server-id": 3,
+ "X-Server-status": "on",
+ "Content-Type": ""
+ }
+ }
+ }
+ }
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 22: should keep Content-Encoding
+--- request
+GET /brotli_hello
+--- more_headers
+Accept-Encoding: br
+--- response_headers
+Content-Encoding: br
+X-Server-id: 3
+X-Server-status: on
+Content-Type: