|  | # | 
|  | # 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. | 
|  | # | 
|  | use t::APISIX 'no_plan'; | 
|  |  | 
|  | repeat_each(1); | 
|  | log_level('info'); | 
|  | no_root_location(); | 
|  | no_shuffle(); | 
|  |  | 
|  | add_block_preprocessor(sub { | 
|  | my ($block) = @_; | 
|  |  | 
|  | if (!$block->request) { | 
|  | $block->set_value("request", "GET /t"); | 
|  | } | 
|  |  | 
|  | my $extra_yaml_config = <<_EOC_; | 
|  | plugins: | 
|  | - brotli | 
|  | _EOC_ | 
|  |  | 
|  | $block->set_value("extra_yaml_config", $extra_yaml_config); | 
|  | }); | 
|  |  | 
|  | run_tests(); | 
|  |  | 
|  | __DATA__ | 
|  |  | 
|  | === TEST 1: sanity | 
|  | --- 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": { | 
|  | "type": "roundrobin", | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | } | 
|  | }, | 
|  | "plugins": { | 
|  | "brotli": { | 
|  | } | 
|  | } | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 2: hit, single Accept-Encoding | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 3: hit, single wildcard Accept-Encoding | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: * | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 4: not hit, single Accept-Encoding | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: gzip | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 5: hit, br in multi Accept-Encoding | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: gzip, br | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 6: hit, no br in multi Accept-Encoding, but wildcard | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: gzip, * | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 7: not hit, no br in multi Accept-Encoding | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: gzip, deflate | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 8: hit, multi Accept-Encoding with quality | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: gzip;q=0.5, br;q=0.6 | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 9: not hit, multi Accept-Encoding with quality and disable br | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: gzip;q=0.5, br;q=0 | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 10: hit, multi Accept-Encoding with quality and wildcard | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: gzip;q=0.8, deflate, sdch;q=0.6, *;q=0.1 | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  | Vary: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 11: default buffers and compress level | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local plugin = require("apisix.plugins.brotli") | 
|  | local core = require("apisix.core") | 
|  | local json = require("toolkit.json") | 
|  |  | 
|  | for _, conf in ipairs({ | 
|  | {}, | 
|  | {mode = 1}, | 
|  | {comp_level = 5}, | 
|  | {comp_level = 5, lgwin = 12}, | 
|  | {comp_level = 5, lgwin = 12, vary = true}, | 
|  | {comp_level = 5, lgwin = 12, lgblock = 16, vary = true}, | 
|  | {mode = 2, comp_level = 5, lgwin = 12, lgblock = 16, vary = true}, | 
|  | }) do | 
|  | local ok, err = plugin.check_schema(conf) | 
|  | if not ok then | 
|  | ngx.say(err) | 
|  | return | 
|  | end | 
|  | ngx.say(json.encode(conf)) | 
|  | end | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | {"comp_level":6,"http_version":1.1,"lgblock":0,"lgwin":19,"min_length":20,"mode":0,"types":["text/html"]} | 
|  | {"comp_level":6,"http_version":1.1,"lgblock":0,"lgwin":19,"min_length":20,"mode":1,"types":["text/html"]} | 
|  | {"comp_level":5,"http_version":1.1,"lgblock":0,"lgwin":19,"min_length":20,"mode":0,"types":["text/html"]} | 
|  | {"comp_level":5,"http_version":1.1,"lgblock":0,"lgwin":12,"min_length":20,"mode":0,"types":["text/html"]} | 
|  | {"comp_level":5,"http_version":1.1,"lgblock":0,"lgwin":12,"min_length":20,"mode":0,"types":["text/html"],"vary":true} | 
|  | {"comp_level":5,"http_version":1.1,"lgblock":16,"lgwin":12,"min_length":20,"mode":0,"types":["text/html"],"vary":true} | 
|  | {"comp_level":5,"http_version":1.1,"lgblock":16,"lgwin":12,"min_length":20,"mode":2,"types":["text/html"],"vary":true} | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 12: compress level | 
|  | --- 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", | 
|  | "vars": [["http_x", "==", "1"]], | 
|  | "upstream": { | 
|  | "type": "roundrobin", | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | } | 
|  | }, | 
|  | "plugins": { | 
|  | "brotli": { | 
|  | "comp_level": 0 | 
|  | } | 
|  | } | 
|  | }]=] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | return | 
|  | end | 
|  |  | 
|  | local code, body = t('/apisix/admin/routes/1', | 
|  | ngx.HTTP_PUT, | 
|  | [=[{ | 
|  | "uri": "/echo", | 
|  | "vars": [["http_x", "==", "2"]], | 
|  | "upstream": { | 
|  | "type": "roundrobin", | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | } | 
|  | }, | 
|  | "plugins": { | 
|  | "brotli": { | 
|  | "comp_level": 11 | 
|  | } | 
|  | } | 
|  | }]=] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | return | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 13: hit | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local http = require "resty.http" | 
|  | local uri = "http://127.0.0.1:" .. ngx.var.server_port | 
|  | .. "/echo" | 
|  | local httpc = http.new() | 
|  | local res, err = httpc:request_uri(uri, | 
|  | {method = "POST", headers = {x = "1"}, body = ("0123"):rep(1024)}) | 
|  | if not res then | 
|  | ngx.say(err) | 
|  | return | 
|  | end | 
|  | local less_compressed = res.body | 
|  | local res, err = httpc:request_uri(uri, | 
|  | {method = "POST", headers = {x = "2"}, body = ("0123"):rep(1024)}) | 
|  | if not res then | 
|  | ngx.say(err) | 
|  | return | 
|  | end | 
|  | if #less_compressed < 4096 and #less_compressed < #res.body then | 
|  | ngx.say("ok") | 
|  | end | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | ok | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 14: min length | 
|  | --- 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": { | 
|  | "type": "roundrobin", | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | } | 
|  | }, | 
|  | "plugins": { | 
|  | "brotli": { | 
|  | "min_length": 21 | 
|  | } | 
|  | } | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 15: not hit | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 16: http version | 
|  | --- 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": { | 
|  | "type": "roundrobin", | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | } | 
|  | }, | 
|  | "plugins": { | 
|  | "brotli": { | 
|  | "http_version": 1.1 | 
|  | } | 
|  | } | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 17: not hit | 
|  | --- request | 
|  | POST /echo HTTP/1.0 | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 18: hit again | 
|  | --- request | 
|  | POST /echo HTTP/1.1 | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 19: types | 
|  | --- 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": { | 
|  | "type": "roundrobin", | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | } | 
|  | }, | 
|  | "plugins": { | 
|  | "brotli": { | 
|  | "types": ["text/plain", "text/xml"] | 
|  | } | 
|  | } | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 20: not hit | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 21: hit again | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Content-Type: text/xml | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 22: hit with charset | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Content-Type: text/plain; charset=UTF-8 | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 23: match all types | 
|  | --- 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": { | 
|  | "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 24: hit | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Content-Type: video/3gpp | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 25: vary | 
|  | --- 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": { | 
|  | "type": "roundrobin", | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | } | 
|  | }, | 
|  | "plugins": { | 
|  | "brotli": { | 
|  | "vary": true | 
|  | } | 
|  | } | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 26: hit | 
|  | --- request | 
|  | POST /echo | 
|  | 0123456789 | 
|  | 012345678 | 
|  | --- more_headers | 
|  | Accept-Encoding: br | 
|  | Vary: upstream | 
|  | Content-Type: text/html | 
|  | --- response_headers | 
|  | Content-Encoding: br | 
|  | Vary: upstream, Accept-Encoding | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 27: schema check | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local t = require("lib.test_admin").test | 
|  | for _, case in ipairs({ | 
|  | {input = { | 
|  | types = {} | 
|  | }}, | 
|  | {input = { | 
|  | min_length = 0 | 
|  | }}, | 
|  | {input = { | 
|  | mode = 4 | 
|  | }}, | 
|  | {input = { | 
|  | comp_level = 12 | 
|  | }}, | 
|  | {input = { | 
|  | http_version = 2 | 
|  | }}, | 
|  | {input = { | 
|  | lgwin = 100 | 
|  | }}, | 
|  | {input = { | 
|  | lgblock = 8 | 
|  | }}, | 
|  | {input = { | 
|  | vary = 0 | 
|  | }} | 
|  | }) do | 
|  | local code, body = t('/apisix/admin/global_rules/1', | 
|  | ngx.HTTP_PUT, | 
|  | { | 
|  | id = "1", | 
|  | plugins = { | 
|  | ["brotli"] = case.input | 
|  | } | 
|  | } | 
|  | ) | 
|  | ngx.print(body) | 
|  | end | 
|  | } | 
|  | } | 
|  | --- response_body | 
|  | {"error_msg":"failed to check the configuration of plugin brotli err: property \"types\" validation failed: object matches none of the required"} | 
|  | {"error_msg":"failed to check the configuration of plugin brotli err: property \"min_length\" validation failed: expected 0 to be at least 1"} | 
|  | {"error_msg":"failed to check the configuration of plugin brotli err: property \"mode\" validation failed: expected 4 to be at most 2"} | 
|  | {"error_msg":"failed to check the configuration of plugin brotli err: property \"comp_level\" validation failed: expected 12 to be at most 11"} | 
|  | {"error_msg":"failed to check the configuration of plugin brotli err: property \"http_version\" validation failed: matches none of the enum values"} | 
|  | {"error_msg":"failed to check the configuration of plugin brotli err: property \"lgwin\" validation failed: matches none of the enum values"} | 
|  | {"error_msg":"failed to check the configuration of plugin brotli err: property \"lgblock\" validation failed: matches none of the enum values"} | 
|  | {"error_msg":"failed to check the configuration of plugin brotli err: property \"vary\" validation failed: wrong type: expected boolean, got number"} | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 28: body checksum | 
|  | --- 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": { | 
|  | "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 29: hit - decompressed respone body same as requset body | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local http = require "resty.http" | 
|  | local uri = "http://127.0.0.1:" .. ngx.var.server_port | 
|  | .. "/echo" | 
|  | local httpc = http.new() | 
|  | local req_body = ("abcdf01234"):rep(1024) | 
|  | local res, err = httpc:request_uri(uri, | 
|  | {method = "POST", headers = {["Accept-Encoding"] = "br"}, body = req_body}) | 
|  | if not res then | 
|  | ngx.say(err) | 
|  | return | 
|  | end | 
|  |  | 
|  | local brotli = require "brotli" | 
|  | local decompressor = brotli.decompressor:new() | 
|  | local chunk = decompressor:decompress(res.body) | 
|  | local chunk_fin = decompressor:finish() | 
|  | local chunks = chunk .. chunk_fin | 
|  | if #chunks == #req_body then | 
|  | ngx.say("ok") | 
|  | end | 
|  | } | 
|  | } | 
|  | --- 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 |