From 15b1537620b854480660c4bc22954f6d1f65df89 Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Thu, 7 Dec 2023 16:59:14 +0800 Subject: [PATCH 01/11] base func --- apisix-master-0.rockspec | 3 ++- apisix/plugins/response-rewrite.lua | 36 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/apisix-master-0.rockspec b/apisix-master-0.rockspec index d4e4b71a0db5..df977a881591 100644 --- a/apisix-master-0.rockspec +++ b/apisix-master-0.rockspec @@ -79,7 +79,8 @@ dependencies = { "nanoid = 0.1-1", "lua-resty-mediador = 0.1.2-1", "lua-resty-ldap = 0.1.0-0", - "lua-resty-t1k = 1.1.0" + "lua-resty-t1k = 1.1.0", + "lua-ffi-zlib = 0.6-0" } build = { diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index 20458c4fcf82..337a1589660f 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -19,6 +19,7 @@ local expr = require("resty.expr.v1") local re_compile = require("resty.core.regex").re_match_compile local plugin_name = "response-rewrite" local ngx = ngx +local ngx_header = ngx.header local re_match = ngx.re.match local re_sub = ngx.re.sub local re_gsub = ngx.re.gsub @@ -26,6 +27,8 @@ local pairs = pairs local ipairs = ipairs local type = type local pcall = pcall +local zlib = require("ffi-zlib") +local str_buffer = require("string.buffer") local lrucache = core.lrucache.new({ @@ -199,6 +202,31 @@ local function check_set_headers(headers) end +local function inflate_gzip(data) + local inputs = buffer.new():set(data) + local outputs = 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 = zlib.inflateGzip(read_inputs, write_outputs) + if not ok then + return nil, err + end + + return output_buffer:get() +end + + function _M.check_schema(conf) local ok, err = core.schema.check(schema, conf) if not ok then @@ -260,6 +288,13 @@ function _M.body_filter(conf, ctx) end local err + if ctx.response_encoding == "gzip" then + body, err = inflate_gzip(body) + if err ~= nil then + core.log.error("inflate gzip body failed, err:" .. err) + end + end + for _, filter in ipairs(conf.filters) do if filter.scope == "once" then body, _, err = re_sub(body, filter.regex, filter.replace, filter.options) @@ -331,6 +366,7 @@ function _M.header_filter(conf, ctx) ngx.status = conf.status_code end + ctx.response_encoding = ngx_header["Content-Encoding"] -- if filters have no any match, response body won't be modified. if conf.filters or conf.body then core.response.clear_header_as_body_modified() From 414f8adec1ffa8f0b9b9585cd29eb4593719158a Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Thu, 7 Dec 2023 17:00:51 +0800 Subject: [PATCH 02/11] lint --- apisix/plugins/response-rewrite.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index 337a1589660f..d480e0df29dc 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -202,7 +202,7 @@ local function check_set_headers(headers) end -local function inflate_gzip(data) +local function inflate_gzip(data) local inputs = buffer.new():set(data) local outputs = buffer.new() From 625831e9e5af7c309203c79967302bac48e541cb Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Thu, 7 Dec 2023 19:02:35 +0800 Subject: [PATCH 03/11] temp t file --- t/plugin/response-rewrite3.t | 154 +++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 t/plugin/response-rewrite3.t diff --git a/t/plugin/response-rewrite3.t b/t/plugin/response-rewrite3.t new file mode 100644 index 000000000000..bb74a8c7c5e1 --- /dev/null +++ b/t/plugin/response-rewrite3.t @@ -0,0 +1,154 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +BEGIN { + if ($ENV{TEST_NGINX_CHECK_LEAK}) { + $SkipReason = "unavailable for the hup tests"; + + } else { + $ENV{TEST_NGINX_USE_HUP} = 1; + undef $ENV{TEST_NGINX_USE_STAP}; + } +} + +use t::APISIX 'no_plan'; + +repeat_each(1); +no_long_string(); +no_shuffle(); +no_root_location(); + +add_block_preprocessor(sub { + my ($block) = @_; + + if (!defined $block->request) { + $block->set_value("request", "GET /t"); + } +}); + +run_tests; + +__DATA__ + +=== TEST 4: set header(rewrite header and 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, + [[{ + "plugins": { + "gzip": { + "types": "*" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/echo" + }]] + ) + + if code >= 300 then + ngx.status = code + return + end + + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "plugins": { + "redirect": { + "uri": "/echo" + }, + "response-rewrite": { + "vars": [ + ["status","==",200] + ], + "filters": [ + { + "regex": "hello", + "replace": "test" + } + ] + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/with_header" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + + +=== TEST 5: check body with deleted header +--- config + location /t { + content_by_lua_block { + local http = require "resty.http" + local uri = "http://127.0.0.1:" .. ngx.var.server_port + .. "/with_header" + + local httpc = http.new() + local res, err = httpc:request_uri(uri, {method = "GET"}) + if not res then + ngx.say(err) + return + end + + if res.headers['Content-Type'] then + ngx.say('fail content-type should not be exist, now is'..res.headers['Content-Type']) + return + end + + if res.headers['X-Server-status'] ~= 'on' then + ngx.say('fail X-Server-status needs to be on') + return + end + + if res.headers['X-Server-id'] ~= '3' then + ngx.say('fail X-Server-id needs to be 3') + return + end + + ngx.print(res.body) + ngx.exit(200) + } + } +--- request +GET /t +--- response_body +new body From c9f09d7bd0cd931849d426ce3ed62951783cb9b4 Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Fri, 8 Dec 2023 17:30:41 +0800 Subject: [PATCH 04/11] update t file --- apisix/plugins/response-rewrite.lua | 12 +- t/plugin/response-rewrite3.t | 292 +++++++++++++++++++++++++--- 2 files changed, 274 insertions(+), 30 deletions(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index d480e0df29dc..07f2977d1bd7 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -288,11 +288,15 @@ function _M.body_filter(conf, ctx) end local err + --- need to fix here + core.log.error(ctx.response_encoding) if ctx.response_encoding == "gzip" then body, err = inflate_gzip(body) if err ~= nil then - core.log.error("inflate gzip body failed, err:" .. err) + core.log.error("filters may not work as expected, inflate gzip err:" .. err) end + else + core.log.error("filters may not work as expected due to unsupported compression encoding type") end for _, filter in ipairs(conf.filters) do @@ -366,10 +370,14 @@ function _M.header_filter(conf, ctx) ngx.status = conf.status_code end - ctx.response_encoding = ngx_header["Content-Encoding"] + local response_encoding = ngx_header["Content-Encoding"] -- if filters have no any match, response body won't be modified. if conf.filters or conf.body then core.response.clear_header_as_body_modified() + ctx.response_encoding = response_encoding + -- if response body won't be modified and response body is compressed + elseif response_encoding ~= nil then + core.response.add_header("Content-Encoding", ctx.response_encoding) end if not conf.headers then diff --git a/t/plugin/response-rewrite3.t b/t/plugin/response-rewrite3.t index bb74a8c7c5e1..6b1165be9e5f 100644 --- a/t/plugin/response-rewrite3.t +++ b/t/plugin/response-rewrite3.t @@ -43,7 +43,7 @@ run_tests; __DATA__ -=== TEST 4: set header(rewrite header and body) +=== TEST 1: set gzip route and response-rewrite route, use response-rewrite body conf --- config location /t { content_by_lua_block { @@ -53,7 +53,8 @@ __DATA__ [[{ "plugins": { "gzip": { - "types": "*" + "types": "*", + "min_length": 1 } }, "upstream": { @@ -62,7 +63,7 @@ __DATA__ }, "type": "roundrobin" }, - "uri": "/echo" + "uri": "/hello" }]] ) @@ -75,8 +76,80 @@ __DATA__ ngx.HTTP_PUT, [[{ "plugins": { - "redirect": { - "uri": "/echo" + "proxy-rewrite": { + "uri": "/hello", + "headers": { + "set": { + "Accept-Encoding": "gzip" + } + } + }, + "response-rewrite": { + "vars": [ + ["status","==",200] + ], + "body": "new body\n" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/rewrited_hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 2: gzip route should return compressed body +--- request +GET /hello +--- more_headers +Accept-Encoding: gzip +--- response_headers +Content-Encoding: gzip + + + +=== TEST 3: response-rewrite route should rewrite body and not Content-Encoding +--- request +GET /rewrited_hello +--- response_body +new body +--- response_headers +Content-Encoding: + + + +=== TEST 4: set response-rewrite route, use 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/2', + ngx.HTTP_PUT, + [[{ + "plugins": { + "proxy-rewrite": { + "uri": "/hello", + "headers": { + "set": { + "Accept-Encoding": "gzip" + } + } }, "response-rewrite": { "vars": [ @@ -96,7 +169,7 @@ __DATA__ }, "type": "roundrobin" }, - "uri": "/with_header" + "uri": "/rewrited_hello" }]] ) @@ -113,42 +186,205 @@ passed +=== TEST 5: response-rewrite route should rewrite body and not Content-Encoding +--- request +GET /rewrited_hello +--- response_body +test world +--- response_headers +Content-Encoding: + -=== TEST 5: check body with deleted header + +=== TEST 6: set response-rewrite route use filter conf and route for mock unsupport compression encoding type --- config location /t { content_by_lua_block { - local http = require "resty.http" - local uri = "http://127.0.0.1:" .. ngx.var.server_port - .. "/with_header" - - local httpc = http.new() - local res, err = httpc:request_uri(uri, {method = "GET"}) - if not res then - ngx.say(err) - return - end + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "response-rewrite": { + "headers": { + "set": { + "Content-Encoding": "br" + } + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) - if res.headers['Content-Type'] then - ngx.say('fail content-type should not be exist, now is'..res.headers['Content-Type']) + if code >= 300 then + ngx.status = code return end - if res.headers['X-Server-status'] ~= 'on' then - ngx.say('fail X-Server-status needs to be on') - return - end + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "plugins": { + "proxy-rewrite": { + "uri": "/hello" + }, + "response-rewrite": { + "vars": [ + ["status","==",200] + ], + "filters": [ + { + "regex": "hello", + "replace": "test" + } + ] + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/rewrited_hello" + }]] + ) - if res.headers['X-Server-id'] ~= '3' then - ngx.say('fail X-Server-id needs to be 3') - return + if code >= 300 then + ngx.status = code end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 7: response-rewrite route should try rewrite body and not Content-Encoding, report error +--- request +GET /rewrited_hello +--- response_headers +Content-Encoding: +--- error_log +filters may not work as expected due to unsupported compression encoding type + + + +=== TEST 8: set response-rewrite route use body conf and use the route for mock unsupport compression encoding type +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "plugins": { + "proxy-rewrite": { + "uri": "/hello" + }, + "response-rewrite": { + "vars": [ + ["status","==",200] + ], + "body": "new body\n" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/rewrited_hello" + }]] + ) - ngx.print(res.body) - ngx.exit(200) + if code >= 300 then + ngx.status = code + end + ngx.say(body) } } --- request GET /t --- response_body +passed + + + +=== TEST 9: response-rewrite route should rewrite body and not Content-Encoding +--- request +GET /rewrited_hello +--- response_body new body +--- response_headers +Content-Encoding: + + + +=== TEST 10: set response-rewrite route 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/2', + ngx.HTTP_PUT, + [[{ + "plugins": { + "proxy-rewrite": { + "uri": "/hello" + }, + "response-rewrite": { + "vars": [ + ["status","==",200] + ], + "headers": { + "set": { + "X-Server-id": 3, + "X-Server-status": "on", + "Content-Type": "" + } + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/rewrited_hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 11: body should keep Content-Encoding +--- request +GET /rewrited_hello +--- response_headers +Content-Encoding: br +X-Server-id: 3 +X-Server-status: on +Content-Type: From cac49ad9e7b9b69baf42aae574cfd5ff3b63ebcf Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Fri, 8 Dec 2023 17:36:16 +0800 Subject: [PATCH 05/11] fix lint --- t/plugin/response-rewrite3.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/plugin/response-rewrite3.t b/t/plugin/response-rewrite3.t index 6b1165be9e5f..80a02a9f200d 100644 --- a/t/plugin/response-rewrite3.t +++ b/t/plugin/response-rewrite3.t @@ -196,7 +196,7 @@ Content-Encoding: -=== TEST 6: set response-rewrite route use filter conf and route for mock unsupport compression encoding type +=== TEST 6: set response-rewrite route use filter conf and route for mock unsupported compression encoding type --- config location /t { content_by_lua_block { @@ -280,7 +280,7 @@ filters may not work as expected due to unsupported compression encoding type -=== TEST 8: set response-rewrite route use body conf and use the route for mock unsupport compression encoding type +=== TEST 8: set response-rewrite route use body conf and use the route for mock unsupported compression encoding type --- config location /t { content_by_lua_block { From b3eacdf7226045ed0c7f5393bbd72b13cdb5d44c Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Tue, 12 Dec 2023 00:17:40 +0800 Subject: [PATCH 06/11] in progress --- apisix/plugins/response-rewrite.lua | 7 +- t/plugin/response-rewrite3.t | 277 ++++------------------------ 2 files changed, 35 insertions(+), 249 deletions(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index 07f2977d1bd7..0d79360c0034 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -28,7 +28,6 @@ local ipairs = ipairs local type = type local pcall = pcall local zlib = require("ffi-zlib") -local str_buffer = require("string.buffer") local lrucache = core.lrucache.new({ @@ -203,6 +202,7 @@ end local function inflate_gzip(data) + local str_buffer = require("string.buffer") local inputs = buffer.new():set(data) local outputs = buffer.new() @@ -288,14 +288,13 @@ function _M.body_filter(conf, ctx) end local err - --- need to fix here - core.log.error(ctx.response_encoding) if ctx.response_encoding == "gzip" then + core.log.error("hit") body, err = inflate_gzip(body) if err ~= nil then core.log.error("filters may not work as expected, inflate gzip err:" .. err) end - else + elseif ctx.response_encoding ~= nil then core.log.error("filters may not work as expected due to unsupported compression encoding type") end diff --git a/t/plugin/response-rewrite3.t b/t/plugin/response-rewrite3.t index 80a02a9f200d..9e477c4e7e2c 100644 --- a/t/plugin/response-rewrite3.t +++ b/t/plugin/response-rewrite3.t @@ -43,7 +43,7 @@ run_tests; __DATA__ -=== TEST 1: set gzip route and response-rewrite route, use response-rewrite body conf +=== TEST 1: set route use response-rewrite body conf --- config location /t { content_by_lua_block { @@ -51,55 +51,23 @@ __DATA__ local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ - "plugins": { - "gzip": { - "types": "*", - "min_length": 1 - } - }, + "uri": "/hello", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" }, - "uri": "/hello" - }]] - ) - - if code >= 300 then - ngx.status = code - return - end - - local code, body = t('/apisix/admin/routes/2', - ngx.HTTP_PUT, - [[{ "plugins": { - "proxy-rewrite": { - "uri": "/hello", - "headers": { - "set": { - "Accept-Encoding": "gzip" - } - } - }, "response-rewrite": { "vars": [ ["status","==",200] ], "body": "new body\n" } - }, - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/rewrited_hello" + } }]] - ) + ) if code >= 300 then ngx.status = code @@ -113,20 +81,9 @@ GET /t passed - -=== TEST 2: gzip route should return compressed body +=== TEST 4: response-rewrite route should rewrite body and not Content-Encoding --- request GET /hello ---- more_headers -Accept-Encoding: gzip ---- response_headers -Content-Encoding: gzip - - - -=== TEST 3: response-rewrite route should rewrite body and not Content-Encoding ---- request -GET /rewrited_hello --- response_body new body --- response_headers @@ -134,69 +91,24 @@ Content-Encoding: -=== TEST 4: set response-rewrite route, use 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/2', - ngx.HTTP_PUT, - [[{ - "plugins": { - "proxy-rewrite": { - "uri": "/hello", - "headers": { - "set": { - "Accept-Encoding": "gzip" - } - } - }, - "response-rewrite": { - "vars": [ - ["status","==",200] - ], - "filters": [ - { - "regex": "hello", - "replace": "test" - } - ] - } - }, - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/rewrited_hello" - }]] - ) - - if code >= 300 then - ngx.status = code - end - ngx.say(body) - } - } ---- request -GET /t ---- response_body -passed - - - === TEST 5: response-rewrite route should rewrite body and not Content-Encoding +--- http_config +gzip on; +gzip_types *; +gzip_min_length 1; --- request -GET /rewrited_hello +GET /hello --- response_body -test world +new body +--- more_headers +Accept-Encoding: gzip --- response_headers Content-Encoding: -=== TEST 6: set response-rewrite route use filter conf and route for mock unsupported compression encoding type + +=== TEST 4: set response-rewrite route, use response-rewrite filter conf --- config location /t { content_by_lua_block { @@ -204,37 +116,14 @@ Content-Encoding: local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ - "plugins": { - "response-rewrite": { - "headers": { - "set": { - "Content-Encoding": "br" - } - } - } - }, + "uri": "/hello", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" }, - "uri": "/hello" - }]] - ) - - if code >= 300 then - ngx.status = code - return - end - - local code, body = t('/apisix/admin/routes/2', - ngx.HTTP_PUT, - [[{ "plugins": { - "proxy-rewrite": { - "uri": "/hello" - }, "response-rewrite": { "vars": [ ["status","==",200] @@ -242,20 +131,14 @@ Content-Encoding: "filters": [ { "regex": "hello", - "replace": "test" + "replace": "test", + "scope":"global" } ] } - }, - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/rewrited_hello" + } }]] - ) + ) if code >= 300 then ngx.status = code @@ -269,122 +152,26 @@ GET /t passed - -=== TEST 7: response-rewrite route should try rewrite body and not Content-Encoding, report error +=== TEST 6: response-rewrite route should rewrite body and not Content-Encoding --- request -GET /rewrited_hello +GET /hello +--- response_body +test world --- response_headers Content-Encoding: ---- error_log -filters may not work as expected due to unsupported compression encoding type - -=== TEST 8: set response-rewrite route use body conf and use the route for mock unsupported compression encoding type ---- config - location /t { - content_by_lua_block { - local t = require("lib.test_admin").test - local code, body = t('/apisix/admin/routes/2', - ngx.HTTP_PUT, - [[{ - "plugins": { - "proxy-rewrite": { - "uri": "/hello" - }, - "response-rewrite": { - "vars": [ - ["status","==",200] - ], - "body": "new body\n" - } - }, - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/rewrited_hello" - }]] - ) - if code >= 300 then - ngx.status = code - end - ngx.say(body) - } - } +=== TEST 7: response-rewrite route should rewrite body and not Content-Encoding +--- http_config +gzip on; +gzip_types *; +gzip_min_length 1; --- request -GET /t ---- response_body -passed - - - -=== TEST 9: response-rewrite route should rewrite body and not Content-Encoding ---- request -GET /rewrited_hello +GET /hello --- response_body new body +--- more_headers +Accept-Encoding: gzip --- response_headers Content-Encoding: - - - -=== TEST 10: set response-rewrite route 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/2', - ngx.HTTP_PUT, - [[{ - "plugins": { - "proxy-rewrite": { - "uri": "/hello" - }, - "response-rewrite": { - "vars": [ - ["status","==",200] - ], - "headers": { - "set": { - "X-Server-id": 3, - "X-Server-status": "on", - "Content-Type": "" - } - } - } - }, - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/rewrited_hello" - }]] - ) - - if code >= 300 then - ngx.status = code - end - ngx.say(body) - } - } ---- request -GET /t ---- response_body -passed - - - -=== TEST 11: body should keep Content-Encoding ---- request -GET /rewrited_hello ---- response_headers -Content-Encoding: br -X-Server-id: 3 -X-Server-status: on -Content-Type: From d514d3c8086e17822cade34505aaaf228bd7154a Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Tue, 12 Dec 2023 17:04:22 +0800 Subject: [PATCH 07/11] fix --- apisix/plugins/response-rewrite.lua | 19 +- t/plugin/response-rewrite3.t | 316 +++++++++++++++++++++++++--- 2 files changed, 297 insertions(+), 38 deletions(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index 0d79360c0034..69f32d50c994 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -28,6 +28,7 @@ local ipairs = ipairs local type = type local pcall = pcall local zlib = require("ffi-zlib") +local str_buffer = require("string.buffer") local lrucache = core.lrucache.new({ @@ -202,13 +203,12 @@ end local function inflate_gzip(data) - local str_buffer = require("string.buffer") - local inputs = buffer.new():set(data) - local outputs = buffer.new() + 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 + if data == "" then return nil end return data @@ -223,7 +223,7 @@ local function inflate_gzip(data) return nil, err end - return output_buffer:get() + return outputs:get() end @@ -289,13 +289,13 @@ function _M.body_filter(conf, ctx) local err if ctx.response_encoding == "gzip" then - core.log.error("hit") body, err = inflate_gzip(body) if err ~= nil then core.log.error("filters may not work as expected, inflate gzip err:" .. err) end elseif ctx.response_encoding ~= nil then - core.log.error("filters may not work as expected due to unsupported compression encoding type") + core.log.error("filters may not work as expected due to unsupported compression encoding type: " + .. ctx.response_encoding) end for _, filter in ipairs(conf.filters) do @@ -374,9 +374,10 @@ function _M.header_filter(conf, ctx) if conf.filters or conf.body then core.response.clear_header_as_body_modified() ctx.response_encoding = response_encoding + --- -- if response body won't be modified and response body is compressed - elseif response_encoding ~= nil then - core.response.add_header("Content-Encoding", ctx.response_encoding) + --elseif response_encoding ~= nil then + -- core.response.add_header("Content-Encoding", ctx.response_encoding) end if not conf.headers then diff --git a/t/plugin/response-rewrite3.t b/t/plugin/response-rewrite3.t index 9e477c4e7e2c..8e36343f0b1f 100644 --- a/t/plugin/response-rewrite3.t +++ b/t/plugin/response-rewrite3.t @@ -37,13 +37,32 @@ add_block_preprocessor(sub { if (!defined $block->request) { $block->set_value("request", "GET /t"); } + + my $http_config = $block->http_config // <<_EOC_; + server { + listen 11451; + gzip on; + gzip_types *; + gzip_min_length 1; + location /gzip_hello { + content_by_lua_block { + ngx.req.read_body() + local s = "hello world" + ngx.header['Content-Length'] = #s + 1 + ngx.say(s) + } + } + } +_EOC_ + + $block->set_value("http_config", $http_config); }); run_tests; __DATA__ -=== TEST 1: set route use response-rewrite body conf +=== TEST 1: set route use gzip upstream --- config location /t { content_by_lua_block { @@ -51,10 +70,51 @@ __DATA__ local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ - "uri": "/hello", + "uri": "/gzip_hello", "upstream": { "nodes": { - "127.0.0.1:1980": 1 + "127.0.0.1:11451": 1 + }, + "type": "roundrobin" + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 2: should return gzip body +--- request +GET /gzip_hello +--- more_headers +Accept-Encoding: gzip +--- response_headers +Content-Encoding: gzip + + + +=== TEST 3: set route use gzip 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": "/gzip_hello", + "upstream": { + "nodes": { + "127.0.0.1:11451": 1 }, "type": "roundrobin" }, @@ -81,9 +141,12 @@ GET /t passed -=== TEST 4: response-rewrite route should rewrite body and not Content-Encoding + +=== TEST 4: should rewrite body and clear Content-Encoding header --- request -GET /hello +GET /gzip_hello +--- more_headers +Accept-Encoding: gzip --- response_body new body --- response_headers @@ -91,24 +154,116 @@ Content-Encoding: -=== TEST 5: response-rewrite route should rewrite body and not Content-Encoding ---- http_config -gzip on; -gzip_types *; -gzip_min_length 1; +=== TEST 5: set route use gzip 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": "/gzip_hello", + "upstream": { + "nodes": { + "127.0.0.1:11451": 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 /hello +GET /t --- response_body -new body +passed + + + +=== TEST 6: gzip decode support, should rewrite body and clear Content-Encoding header +--- request +GET /gzip_hello --- more_headers Accept-Encoding: gzip +--- response_body +test world --- response_headers Content-Encoding: +=== TEST 7: set route use response-write body conf, and mock unsupported compression encoding type +--- 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": "/echo", + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "plugins": { + "response-rewrite": { + "vars": [ + ["status","==",200] + ], + "body": "new body\n" + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + return + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + -=== TEST 4: set response-rewrite route, use response-rewrite filter conf +=== TEST 8: use body conf will ignore encoding, should rewrite body and clear Content-Encoding header +--- request +POST /echo +fake body with mock content encoding header +--- more_headers +Content-Encoding: deflate +--- response_body +new body +--- response_headers +Content-Encoding: + + + +=== TEST 9: set route use response-write filter conf, and mock unsupported compression encoding type --- config location /t { content_by_lua_block { @@ -116,7 +271,7 @@ Content-Encoding: local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ - "uri": "/hello", + "uri": "/echo", "upstream": { "nodes": { "127.0.0.1:1980": 1 @@ -131,17 +286,17 @@ Content-Encoding: "filters": [ { "regex": "hello", - "replace": "test", - "scope":"global" + "replace": "test" } ] } } }]] - ) + ) if code >= 300 then ngx.status = code + return end ngx.say(body) } @@ -152,26 +307,129 @@ GET /t passed -=== TEST 6: response-rewrite route should rewrite body and not Content-Encoding + +=== TEST 10: use filter conf will report unsupported encoding type error --- request -GET /hello ---- response_body -test world +POST /echo +fake body with mock content encoding header +--- more_headers +Content-Encoding: deflate --- response_headers Content-Encoding: +--- error_log +filters may not work as expected due to unsupported compression encoding type -=== TEST 7: response-rewrite route should rewrite body and not Content-Encoding ---- http_config -gzip on; -gzip_types *; -gzip_min_length 1; +=== TEST 11: 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": "/gzip_hello", + "upstream": { + "nodes": { + "127.0.0.1:11451": 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 /hello +GET /t --- response_body -new body +passed + + + +=== TEST 12: should keep Content-Encoding +--- request +GET /gzip_hello --- more_headers Accept-Encoding: gzip --- response_headers -Content-Encoding: +Content-Encoding: gzip +X-Server-id: 3 +X-Server-status: on +Content-Type: + + + +=== TEST 13: set route use response-write plugin but not use filter conf or body conf, and mock unsupported compression encoding type +--- 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": "/echo", + "upstream": { + "nodes": { + "127.0.0.1:1980": 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 14: should keep Content-Encoding +--- request +POST /echo +fake body with mock content encoding header +--- more_headers +Content-Encoding: deflate +--- response_headers +Content-Encoding: deflate +X-Server-id: 3 +X-Server-status: on +Content-Type: From 40b1db3898aaa5c364c3156e4f2e5ea161aa7452 Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Tue, 12 Dec 2023 17:09:55 +0800 Subject: [PATCH 08/11] fix --- t/plugin/response-rewrite3.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/plugin/response-rewrite3.t b/t/plugin/response-rewrite3.t index 8e36343f0b1f..b8b2b5844235 100644 --- a/t/plugin/response-rewrite3.t +++ b/t/plugin/response-rewrite3.t @@ -378,7 +378,7 @@ Content-Type: -=== TEST 13: set route use response-write plugin but not use filter conf or body conf, and mock unsupported compression encoding type +=== TEST 13: response-write without filter conf or body conf, and mock unsupported compression encoding type --- config location /t { content_by_lua_block { From f53481178838995d265d9c15070a1c13fbc4dbf4 Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Tue, 12 Dec 2023 17:11:04 +0800 Subject: [PATCH 09/11] fix --- apisix/plugins/response-rewrite.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index 69f32d50c994..a39813ec5083 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -374,7 +374,6 @@ function _M.header_filter(conf, ctx) if conf.filters or conf.body then core.response.clear_header_as_body_modified() ctx.response_encoding = response_encoding - --- -- if response body won't be modified and response body is compressed --elseif response_encoding ~= nil then -- core.response.add_header("Content-Encoding", ctx.response_encoding) From ad3f2fdc74026150eb2352406ded22219cd4f8ba Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Tue, 12 Dec 2023 20:10:26 +0800 Subject: [PATCH 10/11] fin --- apisix/plugins/response-rewrite.lua | 13 ++++++------- t/plugin/response-rewrite3.t | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index a39813ec5083..2150bdbb8c88 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -291,11 +291,13 @@ function _M.body_filter(conf, ctx) if ctx.response_encoding == "gzip" then body, err = inflate_gzip(body) if err ~= nil then - core.log.error("filters may not work as expected, inflate gzip err:" .. err) + core.log.error("filters may not work as expected, inflate gzip 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: " - .. ctx.response_encoding) + core.log.error("filters may not work as expected due to unsupported compression encoding type: ", + ctx.response_encoding) + return end for _, filter in ipairs(conf.filters) do @@ -369,14 +371,11 @@ function _M.header_filter(conf, ctx) ngx.status = conf.status_code end - local response_encoding = ngx_header["Content-Encoding"] -- if filters have no any match, response body won't be modified. if conf.filters or conf.body then + local response_encoding = ngx_header["Content-Encoding"] core.response.clear_header_as_body_modified() ctx.response_encoding = response_encoding - -- if response body won't be modified and response body is compressed - --elseif response_encoding ~= nil then - -- core.response.add_header("Content-Encoding", ctx.response_encoding) end if not conf.headers then diff --git a/t/plugin/response-rewrite3.t b/t/plugin/response-rewrite3.t index b8b2b5844235..904508cc8963 100644 --- a/t/plugin/response-rewrite3.t +++ b/t/plugin/response-rewrite3.t @@ -317,7 +317,7 @@ Content-Encoding: deflate --- response_headers Content-Encoding: --- error_log -filters may not work as expected due to unsupported compression encoding type +filters may not work as expected due to unsupported compression encoding type: deflate From 6ec2d0740990dc0897f9e15a7482077e2b4f9826 Mon Sep 17 00:00:00 2001 From: yuweizzz Date: Wed, 13 Dec 2023 10:49:43 +0800 Subject: [PATCH 11/11] fix lint --- apisix/plugins/response-rewrite.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index 2150bdbb8c88..d9aa816ce3de 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -295,7 +295,8 @@ function _M.body_filter(conf, ctx) return end elseif ctx.response_encoding ~= nil then - core.log.error("filters may not work as expected due to unsupported compression encoding type: ", + core.log.error("filters may not work as expected ", + "due to unsupported compression encoding type: ", ctx.response_encoding) return end