|  | # | 
|  | # 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(); | 
|  |  | 
|  | run_tests; | 
|  |  | 
|  | __DATA__ | 
|  |  | 
|  | === TEST 1: sanity | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local plugin = require("apisix.plugins.limit-req") | 
|  | local ok, err = plugin.check_schema({ | 
|  | rate = 1, | 
|  | burst = 0, | 
|  | rejected_code = 503, | 
|  | key = 'remote_addr', | 
|  | policy = 'redis', | 
|  | redis_host = '127.0.0.1' | 
|  | }) | 
|  | if not ok then | 
|  | ngx.say(err) | 
|  | end | 
|  |  | 
|  | ngx.say("done") | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | done | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 2: add plugin with redis cluster with ssl | 
|  | --- 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": { | 
|  | "limit-req": { | 
|  | "rate": 4, | 
|  | "burst": 1, | 
|  | "rejected_code": 503, | 
|  | "key": "remote_addr", | 
|  | "policy": "redis-cluster", | 
|  | "redis_cluster_name": "test", | 
|  | "redis_cluster_nodes": [ | 
|  | "127.0.0.1:7000", | 
|  | "127.0.0.1:7001", | 
|  | "127.0.0.1:7002" | 
|  | ], | 
|  | "redis_cluster_ssl": true, | 
|  | "redis_cluster_ssl_verify": false | 
|  | } | 
|  | }, | 
|  | "upstream": { | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | }, | 
|  | "type": "roundrobin" | 
|  | }, | 
|  | "desc": "upstream_node", | 
|  | "uri": "/hello" | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 3: not exceeding the burst | 
|  | --- pipelined_requests eval | 
|  | ["GET /hello", "GET /hello", "GET /hello", "GET /hello"] | 
|  | --- error_code eval | 
|  | [200, 200, 200, 200] | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 4: exceeding the burst | 
|  | --- pipelined_requests eval | 
|  | ["GET /hello", "GET /hello", "GET /hello", "GET /hello", "GET /hello", "GET /hello", "GET /hello", "GET /hello", "GET /hello"] | 
|  | --- error_code eval | 
|  | [200, 200, 200, 200, 200, 200, 200, 200, 200, 503] | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 5: update plugin | 
|  | --- 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": { | 
|  | "limit-req": { | 
|  | "rate": 0.1, | 
|  | "burst": 0.1, | 
|  | "rejected_code": 503, | 
|  | "key": "remote_addr", | 
|  | "policy": "redis-cluster", | 
|  | "redis_cluster_name": "test", | 
|  | "redis_cluster_nodes": [ | 
|  | "127.0.0.1:5000", | 
|  | "127.0.0.1:5002" | 
|  | ] | 
|  | } | 
|  | }, | 
|  | "upstream": { | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | }, | 
|  | "type": "roundrobin" | 
|  | }, | 
|  | "uri": "/hello" | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 6: exceeding the burst | 
|  | --- pipelined_requests eval | 
|  | ["GET /hello", "GET /hello", "GET /hello", "GET /hello"] | 
|  | --- error_code eval | 
|  | [200, 503, 503, 503] | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 7: wrong 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, | 
|  | [[{ | 
|  | "plugins": { | 
|  | "limit-req": { | 
|  | "rate": -1, | 
|  | "burst": 0.1, | 
|  | "rejected_code": 503, | 
|  | "key": "remote_addr", | 
|  | "policy": "redis-cluster", | 
|  | "redis_cluster_name": "test", | 
|  | "redis_cluster_nodes": [ | 
|  | "127.0.0.1:5000", | 
|  | "127.0.0.1:5002" | 
|  | ] | 
|  | } | 
|  | }, | 
|  | "upstream": { | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | }, | 
|  | "type": "roundrobin" | 
|  | }, | 
|  | "uri": "/hello" | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.print(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- error_code: 400 | 
|  | --- response_body | 
|  | {"error_msg":"failed to check the configuration of plugin limit-req err: property \"rate\" validation failed: expected -1 to be greater than 0"} | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 8: disable plugin | 
|  | --- 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": { | 
|  | }, | 
|  | "upstream": { | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | }, | 
|  | "type": "roundrobin" | 
|  | }, | 
|  | "uri": "/hello" | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 9: exceeding the burst | 
|  | --- pipelined_requests eval | 
|  | ["GET /hello", "GET /hello", "GET /hello", "GET /hello"] | 
|  | --- error_code eval | 
|  | [200, 200, 200, 200] | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 10: set route (key: server_addr) | 
|  | --- 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": { | 
|  | "limit-req": { | 
|  | "rate": 4, | 
|  | "burst": 2, | 
|  | "rejected_code": 503, | 
|  | "key": "server_addr", | 
|  | "policy": "redis-cluster", | 
|  | "redis_cluster_name": "test", | 
|  | "redis_cluster_nodes": [ | 
|  | "127.0.0.1:5000", | 
|  | "127.0.0.1:5002" | 
|  | ] | 
|  | } | 
|  | }, | 
|  | "upstream": { | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | }, | 
|  | "type": "roundrobin" | 
|  | }, | 
|  | "desc": "upstream_node", | 
|  | "uri": "/hello" | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 11: default rejected_code | 
|  | --- 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": { | 
|  | "limit-req": { | 
|  | "rate": 4, | 
|  | "burst": 2, | 
|  | "key": "remote_addr", | 
|  | "policy": "redis-cluster", | 
|  | "redis_cluster_name": "test", | 
|  | "redis_cluster_nodes": [ | 
|  | "127.0.0.1:5000", | 
|  | "127.0.0.1:5002" | 
|  | ] | 
|  | } | 
|  | }, | 
|  | "upstream": { | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | }, | 
|  | "type": "roundrobin" | 
|  | }, | 
|  | "desc": "upstream_node", | 
|  | "uri": "/hello" | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 12: consumer binds the limit-req plugin and `key` is `consumer_name` | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local t = require("lib.test_admin").test | 
|  | local code, body = t('/apisix/admin/consumers', | 
|  | ngx.HTTP_PUT, | 
|  | [[{ | 
|  | "username": "new_consumer", | 
|  | "plugins": { | 
|  | "key-auth": { | 
|  | "key": "auth-jack" | 
|  | }, | 
|  | "limit-req": { | 
|  | "rate": 3, | 
|  | "burst": 2, | 
|  | "rejected_code": 403, | 
|  | "key": "consumer_name", | 
|  | "policy": "redis-cluster", | 
|  | "redis_cluster_name": "test", | 
|  | "redis_cluster_nodes": [ | 
|  | "127.0.0.1:5000", | 
|  | "127.0.0.1:5002" | 
|  | ] | 
|  | } | 
|  | } | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 13: route add "key-auth" plugin | 
|  | --- 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": { | 
|  | "key-auth": {} | 
|  | }, | 
|  | "upstream": { | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | }, | 
|  | "type": "roundrobin" | 
|  | }, | 
|  | "desc": "upstream_node", | 
|  | "uri": "/hello" | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 14: not exceeding the burst | 
|  | --- pipelined_requests eval | 
|  | ["GET /hello", "GET /hello", "GET /hello"] | 
|  | --- more_headers | 
|  | apikey: auth-jack | 
|  | --- error_code eval | 
|  | [200, 200, 200] | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 15: update the limit-req plugin | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local t = require("lib.test_admin").test | 
|  | local code, body = t('/apisix/admin/consumers', | 
|  | ngx.HTTP_PUT, | 
|  | [[{ | 
|  | "username": "new_consumer", | 
|  | "plugins": { | 
|  | "key-auth": { | 
|  | "key": "auth-jack" | 
|  | }, | 
|  | "limit-req": { | 
|  | "rate": 0.1, | 
|  | "burst": 0.1, | 
|  | "rejected_code": 403, | 
|  | "key": "consumer_name", | 
|  | "policy": "redis-cluster", | 
|  | "redis_cluster_name": "test", | 
|  | "redis_cluster_nodes": [ | 
|  | "127.0.0.1:5000", | 
|  | "127.0.0.1:5002" | 
|  | ] | 
|  | } | 
|  | } | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | ngx.status = code | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 16: exceeding the burst | 
|  | --- pipelined_requests eval | 
|  | ["GET /hello", "GET /hello", "GET /hello", "GET /hello"] | 
|  | --- more_headers | 
|  | apikey: auth-jack | 
|  | --- error_code eval | 
|  | [403, 403, 403, 403] | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 17: key is consumer_name | 
|  | --- 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": { | 
|  | "limit-req": { | 
|  | "rate": 2, | 
|  | "burst": 1, | 
|  | "key": "consumer_name", | 
|  | "policy": "redis-cluster", | 
|  | "redis_cluster_name": "test", | 
|  | "redis_cluster_nodes": [ | 
|  | "127.0.0.1:5000", | 
|  | "127.0.0.1:5002" | 
|  | ] | 
|  | } | 
|  | }, | 
|  | "upstream": { | 
|  | "nodes": { | 
|  | "127.0.0.1:1980": 1 | 
|  | }, | 
|  | "type": "roundrobin" | 
|  | }, | 
|  | "desc": "upstream_node", | 
|  | "uri": "/hello" | 
|  | }]] | 
|  | ) | 
|  |  | 
|  | if code >= 300 then | 
|  | ngx.status = code | 
|  | end | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 18: get "consumer_name" is empty | 
|  | --- request | 
|  | GET /hello | 
|  | --- response_body | 
|  | hello world | 
|  | --- error_log | 
|  | The value of the configured key is empty, use client IP instead | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 19: delete consumer | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local t = require("lib.test_admin").test | 
|  | local code, body = t('/apisix/admin/consumers/new_consumer', ngx.HTTP_DELETE) | 
|  |  | 
|  | ngx.status = code | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 20: delete route | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local t = require("lib.test_admin").test | 
|  | local code, body = t('/apisix/admin/routes/1', ngx.HTTP_DELETE) | 
|  |  | 
|  | ngx.status =code | 
|  | ngx.say(body) | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body | 
|  | passed | 
|  |  | 
|  |  | 
|  |  | 
|  | === TEST 21: check_schema failed (the `rate` attribute is equal to 0) | 
|  | --- config | 
|  | location /t { | 
|  | content_by_lua_block { | 
|  | local plugin = require("apisix.plugins.limit-req") | 
|  | local ok, err = plugin.check_schema({rate = 0, burst = 0, rejected_code = 503, key = 'remote_addr'}) | 
|  | if not ok then | 
|  | ngx.say(err) | 
|  | end | 
|  |  | 
|  | ngx.say("done") | 
|  | } | 
|  | } | 
|  | --- request | 
|  | GET /t | 
|  | --- response_body eval | 
|  | qr/property \"rate\" validation failed: expected 0 to be greater than 0/ |