diff --git a/apisix/plugins/brotli.lua b/apisix/plugins/brotli.lua index 9b4954aea6ac..4482fc0cd8dc 100644 --- a/apisix/plugins/brotli.lua +++ b/apisix/plugins/brotli.lua @@ -163,6 +163,12 @@ function _M.header_filter(conf, ctx) return end + local content_encoded = ngx_header["Content-Encoding"] + if content_encoded then + -- Don't compress if Content-Encoding is present in upstream data + return + end + local types = conf.types local content_type = ngx_header["Content-Type"] if not content_type then diff --git a/docs/en/latest/plugins/brotli.md b/docs/en/latest/plugins/brotli.md index eaf9cb2999dc..196fdb520234 100644 --- a/docs/en/latest/plugins/brotli.md +++ b/docs/en/latest/plugins/brotli.md @@ -47,6 +47,12 @@ sudo sh -c "echo /usr/local/brotli/lib >> /etc/ld.so.conf.d/brotli.conf" sudo ldconfig ``` +:::caution + +If the upstream is returning a compressed response, then the Brotli plugin won't be able to compress it. + +::: + ## Attributes | Name | Type | Required | Default | Valid values | Description | diff --git a/t/lib/server.lua b/t/lib/server.lua index c7386e1b7e84..7cc8101a3af7 100644 --- a/t/lib/server.lua +++ b/t/lib/server.lua @@ -591,4 +591,11 @@ function _M.clickhouse_logger_server() end +function _M.mock_compressed_upstream_response() + local s = "compressed_response" + ngx.header['Content-Encoding'] = 'gzip' + ngx.say(s) +end + + return _M diff --git a/t/plugin/brotli.t b/t/plugin/brotli.t index 5f7c6cae39a2..f0f69315430f 100644 --- a/t/plugin/brotli.t +++ b/t/plugin/brotli.t @@ -718,3 +718,68 @@ passed } --- response_body ok + + + +=== TEST 30: mock upstream compressed response +--- 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": "/mock_compressed_upstream_response", + "upstream": { + "type": "roundrobin", + "nodes": { + "127.0.0.1:1980": 1 + } + }, + "plugins": { + "brotli": { + "types": "*" + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } +} +--- response_body +passed + + + +=== TEST 31: hit - skip brotli compression of compressed upstream response +--- config + location /t { + content_by_lua_block { + local http = require "resty.http" + local uri = "http://127.0.0.1:" .. ngx.var.server_port + .. "/mock_compressed_upstream_response" + local httpc = http.new() + local req_body = ("abcdf01234"):rep(1024) + local res, err = httpc:request_uri(uri, + {method = "POST", headers = {["Accept-Encoding"] = "gzip, br"}, body = req_body}) + if not res then + ngx.say(err) + return + end + if res.headers["Content-Encoding"] == 'gzip' then + ngx.say("ok") + end + } + } +--- request +GET /t +--- more_headers +Accept-Encoding: gzip, br +Vary: upstream +Content-Type: text/html +--- response_body +ok