Skip to content

Commit

Permalink
feat(response-rewrite): support brotli when use filters.regex option (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
yuweizzz authored Jan 4, 2024
1 parent 88107db commit ab67b09
Show file tree
Hide file tree
Showing 2 changed files with 303 additions and 2 deletions.
59 changes: 59 additions & 0 deletions apisix/plugins/response-rewrite.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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: ",
Expand Down
246 changes: 244 additions & 2 deletions t/plugin/response-rewrite3.t
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -238,7 +277,6 @@ Content-Encoding:
if code >= 300 then
ngx.status = code
return
end
ngx.say(body)
}
Expand Down Expand Up @@ -296,7 +334,6 @@ Content-Encoding:
if code >= 300 then
ngx.status = code
return
end
ngx.say(body)
}
Expand Down Expand Up @@ -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:

0 comments on commit ab67b09

Please sign in to comment.