Re: [I] bug: limit-req: conf_type/conf_version suffix makes per-consumer rate limits effectively per-route [apisix]

2026-02-23 Thread via GitHub


Baoyuantop commented on issue #12946:
URL: https://github.com/apache/apisix/issues/12946#issuecomment-3949354952

   Hi @janiussyafiq, Thank you for reminding me, I have verified that this is 
indeed the case.
   
   The following test cases can be executed successfully.
   
   ```
   === TEST 1: setup consumer with limit-count and two routes (no limit-count 
on routes)
   --- config
   location /t {
   content_by_lua_block {
   local t = require("lib.test_admin").test
   t('/apisix/admin/consumers', ngx.HTTP_PUT, [[{
   "username": "jack",
   "plugins": {
   "key-auth": { "key": "auth-key" },
   "limit-count": {
   "count": 1,
   "time_window": 60,
   "rejected_code": 429,
   "key": "consumer_name"
   }
   }
   }]])
   -- route A
   t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{
   "uri": "/hello", "plugins": { "key-auth": {} },
   "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": 
"roundrobin" }
   }]])
   -- route B
   t('/apisix/admin/routes/2', ngx.HTTP_PUT, [[{
   "uri": "/hello1", "plugins": { "key-auth": {} },
   "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": 
"roundrobin" }
   }]])
   ngx.say("done")
   }
   }
   --- request
   GET /t
   --- response_body
   done
   
   
   
   === TEST 2: cross-route requests - limit-count on consumer should be shared 
globally
   --- pipelined_requests eval
   ["GET /hello", "GET /hello1"]
   --- more_headers
   apikey: auth-key
   --- error_code eval
   [200, 429]
   
   ```
   
   ```
   === TEST 1: setup consumer with limit-req and two routes (no limit-req on 
routes)
   --- config
   location /t {
   content_by_lua_block {
   local t = require("lib.test_admin").test
   t('/apisix/admin/consumers', ngx.HTTP_PUT, [[{
   "username": "jack",
   "plugins": {
   "key-auth": { "key": "auth-key" },
   "limit-req": {
   "rate": 0.1,
   "burst": 0,
   "rejected_code": 403,
   "key": "consumer_name"
   }
   }
   }]])
   -- route A
   t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{
   "uri": "/hello", "plugins": { "key-auth": {} },
   "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": 
"roundrobin" }
   }]])
   -- route B
   t('/apisix/admin/routes/2', ngx.HTTP_PUT, [[{
   "uri": "/hello1", "plugins": { "key-auth": {} },
   "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": 
"roundrobin" }
   }]])
   ngx.say("done")
   }
   }
   --- request
   GET /t
   --- response_body
   done
   
   
   
   === TEST 2: cross-route requests - limit-req on consumer should be shared 
globally
   --- pipelined_requests eval
   ["GET /hello", "GET /hello1"]
   --- more_headers
   apikey: auth-key
   --- error_code eval
   [200, 200]
   ```
   
   The limit-req and limit-count plugins exhibit inconsistent behavior; their 
key concatenation methods differ.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



Re: [I] bug: limit-req: conf_type/conf_version suffix makes per-consumer rate limits effectively per-route [apisix]

2026-02-19 Thread via GitHub


janiussyafiq commented on issue #12946:
URL: https://github.com/apache/apisix/issues/12946#issuecomment-3932007641

   Hi @Baoyuantop, just to let u know that the test u provided will also pass 
without the `group` config within `limit-count` plugin. I verified it by manual 
testing. Initially, my fix would be adding group config to `limit-req` plugin 
but since this behavior wouldn't require the group config to work, I'll 
implement the simpler fix w/o adding group config. 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



Re: [I] bug: limit-req: conf_type/conf_version suffix makes per-consumer rate limits effectively per-route [apisix]

2026-01-29 Thread via GitHub


falvaradorodriguez commented on issue #12946:
URL: https://github.com/apache/apisix/issues/12946#issuecomment-3816302646

   Hello @Baoyuantop,
   
   Thank you very much for your explanation. Sorry for indicate it as a bug. 
   
   In my specific case, what you mention is a limitation, and it would be very 
helpful to add the `group` parameter to this plugin as well. 
   
   My scenario is as follows. Each consumer has its own RPS configuration and 
monthly request quota. To achieve this, I need to configure the limit-req and 
limit-count plugins together. This limits me to using the limit-count plugin 
for RPS, as it is the only way I know to manage the monthly quota. The RPS 
configuration is common to the consumer, so if the `limit-req` plugin groups by 
route, my scenario is not possible. 
   
   I look forward to seeing if it is possible to add this feature to the 
project.
   
   Thanks a lot in advance.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



Re: [I] bug: limit-req: conf_type/conf_version suffix makes per-consumer rate limits effectively per-route [apisix]

2026-01-28 Thread via GitHub


Baoyuantop commented on issue #12946:
URL: https://github.com/apache/apisix/issues/12946#issuecomment-3815756300

   Hi @falvaradorodriguez, I have confirmed that this is expected behavior, not 
a bug.
   
   By default, each route in APISIX has its own separate rate-limiting counter. 
We later introduced the `group` configuration option in the `limit-count` 
plugin to achieve the scenario you described. However, this configuration 
option has not yet been added to other rate-limiting plugins.
   
   The following test cases have been verified to pass.
   ```
   === TEST 1: setup consumer with group and routes
   --- config
   location /t {
   content_by_lua_block {
   local t = require("lib.test_admin").test
   -- consumer with limit-count: count=1, time_window=60, 
group="jack-limit"
   t('/apisix/admin/consumers', ngx.HTTP_PUT, [[{
   "username": "jack",
   "plugins": {
   "key-auth": { "key": "auth-key" },
   "limit-count": {
   "count": 1,
   "time_window": 60,
   "rejected_code": 429,
   "key": "consumer_name",
   "group": "jack-limit"
   }
   }
   }]])
   -- route A
   t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{
   "uri": "/hello", "plugins": { "key-auth": {} },
   "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": 
"roundrobin" }
   }]])
   -- route B
   t('/apisix/admin/routes/2', ngx.HTTP_PUT, [[{
   "uri": "/hello1", "plugins": { "key-auth": {} },
   "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": 
"roundrobin" }
   }]])
   ngx.say("done")
   }
   }
   --- request
   GET /t
   --- response_body
   done
   
   
   
   === TEST 2: cross-route requests - with group, counter is shared globally
   Consumer has count=1 with group="jack-limit", requests across routes share 
the same counter.
   EXPECTED: [200, 429]
   --- pipelined_requests eval
   ["GET /hello", "GET /hello1"]
   --- more_headers
   apikey: auth-key
   --- error_code eval
   [200, 429]
   
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



[I] bug: limit-req: conf_type/conf_version suffix makes per-consumer rate limits effectively per-route [apisix]

2026-01-27 Thread via GitHub


falvaradorodriguez opened a new issue, #12946:
URL: https://github.com/apache/apisix/issues/12946

   ### Current Behavior
   
   When the limit-req plugin is configured only at the Consumer level, the 
effective rate limit is still scoped per route, not per consumer.
   
   Internally, limit-req always appends ctx.conf_type and ctx.conf_version to 
the generated key. At runtime, ctx.conf_type includes both route and consumer 
(e.g. route&consumer), and conf_version includes the route ID. As a result, a 
separate Redis counter is created for each route, even though the plugin is not 
configured on the routes themselves.
   
   This can be observed in logs such as:
   
   ```
   conf type: route&consumer
   conf version: &
   limit key: route&consumer
   ```
   
   
   Because of this behavior, a consumer configured with N req/sec can 
effectively make N req/sec per route, which bypasses the expected global 
per-consumer rate limit.
   
   There is currently no configuration option in limit-req to prevent the 
conf_type/conf_version suffix from being added, making it impossible to 
implement a true global per-consumer leaky-bucket rate limit using limit-req.
   
   ### Expected Behavior
   
   When the limit-req plugin is configured at the Consumer level, the rate 
limit should apply globally to that consumer, regardless of which route is 
being accessed.
   
   In this scenario, all requests made by the same consumer should share a 
single rate-limit bucket, so that a consumer configured with N req/sec can only 
make N req/sec in total, even when calling multiple routes.
   
   More generally, users should be able to control the scope of the rate-limit 
key (for example, per route vs. per consumer), or at least have a way to 
prevent route-specific information from being implicitly included in the 
rate-limit key when the plugin is defined on a consumer.
   
   This would allow limit-req to be used for true global per-consumer rate 
limiting, without requiring custom plugin overrides or switching to a different 
rate-limiting plugin.
   
   ### Error Logs
   
   The following logs were captured by adding debug prints in limit-req.lua 
while sending requests from the same consumer to different routes.
   
   ```
 key = key .. ctx.conf_type .. ctx.conf_version
 core.log.error("limit key: ", key)
 core.log.error("conf type: ", ctx.conf_type)
 core.log.error("conf version: ", ctx.conf_version)
   ```
   
   Even though limit-req is configured only on the Consumer, the plugin reports 
a combined configuration context (route&consumer), and the generated key 
includes route-specific information:
   
   ```
   2026/01/27 13:11:59 [error] 204#204: *53475 [lua] limit-req.lua:162: 
phase_func(): conf version: 2008&1, client: 192.168.65.1, server: _, request: 
"GET /test HTTP/1.1", host: "localhost:9080"
   
   2026/01/27 13:12:00 [error] 194#194: *53481 [lua] limit-req.lua:160: 
phase_func(): limit key: 192.168.65.1route&consumer2008&1, client: 
192.168.65.1, server: _, request: "GET /test HTTP/1.1", host: "localhost:9080"
   
   2026/01/27 13:12:00 [error] 194#194: *53481 [lua] limit-req.lua:161: 
phase_func(): conf type: route&consumer, client: 192.168.65.1, server: _, 
request: "GET /test HTTP/1.1", host: "localhost:9080"
   ```
   
   
   These logs show that the rate-limit key is effectively namespaced by both 
the route and the consumer, resulting in separate rate-limit counters per route.
   
   ### Steps to Reproduce
   
   1. Start APISIX 3.12 and Redis
   
   Run APISIX 3.12 with Redis enabled (local or via Docker).
   Ensure Redis is reachable from APISIX.
   
   2. Create a Consumer with key-auth and limit-req
   
   Configure limit-req only at the Consumer level:
   
   ```
   curl -X PUT http://127.0.0.1:9180/apisix/admin/consumers/test-consumer \
 -H 'X-API-KEY: ' \
 -H 'Content-Type: application/json' \
 -d '{
   "username": "test-consumer",
   "plugins": {
 "key-auth": {
   "key": "test-api-key"
 },
 "limit-req": {
   "rate": 2,
   "burst": 0,
   "key": "consumer_name",
   "key_type": "var",
   "policy": "redis",
   "redis_host": "redis",
   "redis_port": 6379,
   "redis_database": 0
 }
   }
 }'
   ```
   
   
   3. Create two routes using key-auth
   
   Route A:
   
   ```
   curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
 -H 'X-API-KEY: ' \
 -H 'Content-Type: application/json' \
 -d '{
   "uri": "/route-a",
   "plugins": {
 "key-auth": {}
   },
   "upstream": {
 "type": "roundrobin",
 "nodes": {
   "httpbin.org:80": 1
 }
   }
 }'
   ```
   
   
   Route B:
   
   ```
   curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/2 \
 -H 'X-API-KEY: ' \
 -H 'Content-Type: application/json' \
 -d '{
   "uri": "/route-b",
   "plugins": {
 "key-au