This is an automated email from the ASF dual-hosted git repository.
shreemaanabhishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 945e077e7 feat(limit-count): make rate-limit response headers
configurable (#11831)
945e077e7 is described below
commit 945e077e7164789af0292eb7df90271c37470392
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Wed Dec 18 16:48:36 2024 +0545
feat(limit-count): make rate-limit response headers configurable (#11831)
---
apisix/plugins/limit-count.lua | 5 +--
apisix/plugins/limit-count/init.lua | 54 +++++++++++++++++++++++++-----
docs/en/latest/plugins/limit-count.md | 59 ++++++++++++++++++++++++++++++++
t/plugin/limit-count5.t | 63 +++++++++++++++++++++++++++++++++++
4 files changed, 171 insertions(+), 10 deletions(-)
diff --git a/apisix/plugins/limit-count.lua b/apisix/plugins/limit-count.lua
index ab7c532a5..1472a6db1 100644
--- a/apisix/plugins/limit-count.lua
+++ b/apisix/plugins/limit-count.lua
@@ -24,11 +24,12 @@ local _M = {
priority = 1002,
name = plugin_name,
schema = limit_count.schema,
+ metadata_schema = limit_count.metadata_schema,
}
-function _M.check_schema(conf)
- return limit_count.check_schema(conf)
+function _M.check_schema(conf, schema_type)
+ return limit_count.check_schema(conf, schema_type)
end
diff --git a/apisix/plugins/limit-count/init.lua
b/apisix/plugins/limit-count/init.lua
index e7d03028e..08a4c9763 100644
--- a/apisix/plugins/limit-count/init.lua
+++ b/apisix/plugins/limit-count/init.lua
@@ -42,6 +42,30 @@ local group_conf_lru = core.lrucache.new({
type = 'plugin',
})
+local metadata_defaults = {
+ limit_header = "X-RateLimit-Limit",
+ remaining_header = "X-RateLimit-Remaining",
+ reset_header = "X-RateLimit-Reset",
+}
+
+local metadata_schema = {
+ type = "object",
+ properties = {
+ limit_header = {
+ type = "string",
+ default = metadata_defaults.limit_header,
+ },
+ remaining_header = {
+ type = "string",
+ default = metadata_defaults.remaining_header,
+ },
+ reset_header = {
+ type = "string",
+ default = metadata_defaults.reset_header,
+ },
+ },
+}
+
local schema = {
type = "object",
properties = {
@@ -91,7 +115,8 @@ local schema = {
local schema_copy = core.table.deepcopy(schema)
local _M = {
- schema = schema
+ schema = schema,
+ metadata_schema = metadata_schema,
}
@@ -100,7 +125,12 @@ local function group_conf(conf)
end
-function _M.check_schema(conf)
+
+function _M.check_schema(conf, schema_type)
+ if schema_type == core.schema.TYPE_METADATA then
+ return core.schema.check(metadata_schema, conf)
+ end
+
local ok, err = core.schema.check(schema, conf)
if not ok then
return false, err
@@ -250,14 +280,22 @@ function _M.rate_limit(conf, ctx, name, cost)
delay, remaining, reset = lim:incoming(key, cost)
end
+ local metadata = apisix_plugin.plugin_metadata("limit-count")
+ if metadata then
+ metadata = metadata.value
+ else
+ metadata = metadata_defaults
+ end
+ core.log.info("limit-count plugin-metadata: ",
core.json.delay_encode(metadata))
+
if not delay then
local err = remaining
if err == "rejected" then
-- show count limit header when rejected
if conf.show_limit_quota_header then
- core.response.set_header("X-RateLimit-Limit", conf.count,
- "X-RateLimit-Remaining", 0,
- "X-RateLimit-Reset", reset)
+ core.response.set_header(metadata.limit_header, conf.count,
+ metadata.remaining_header, 0,
+ metadata.reset_header, reset)
end
if conf.rejected_msg then
@@ -274,9 +312,9 @@ function _M.rate_limit(conf, ctx, name, cost)
end
if conf.show_limit_quota_header then
- core.response.set_header("X-RateLimit-Limit", conf.count,
- "X-RateLimit-Remaining", remaining,
- "X-RateLimit-Reset", reset)
+ core.response.set_header(metadata.limit_header, conf.count,
+ metadata.remaining_header, remaining,
+ metadata.reset_header, reset)
end
end
diff --git a/docs/en/latest/plugins/limit-count.md
b/docs/en/latest/plugins/limit-count.md
index 4c019332a..c5c225017 100644
--- a/docs/en/latest/plugins/limit-count.md
+++ b/docs/en/latest/plugins/limit-count.md
@@ -344,6 +344,65 @@ Server: APISIX web server
{"error_msg":"Requests are too frequent, please try again later."}
```
+### Customize Rate Limiting Headers
+
+The following example demonstrates how you can use plugin metadata to
customize the rate limiting response header names, which are by default
`X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset`.
+
+Configure the plugin metadata for this plugin and update the headers:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/limit-count" -X PUT
-d '
+{
+ "log_format": {
+ "limit_header": "X-Custom-RateLimit-Limit",
+ "remaining_header": "X-Custom-RateLimit-Remaining",
+ "reset_header": "X-Custom-RateLimit-Reset"
+ }
+}'
+```
+
+Create a route with `limit-count` plugin that allows for a quota of 1 within a
30-second window per remote address:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${ADMIN_API_KEY}" \
+ -d '{
+ "id": "limit-count-route",
+ "uri": "/get",
+ "plugins": {
+ "limit-count": {
+ "count": 1,
+ "time_window": 30,
+ "rejected_code": 429,
+ "key_type": "var",
+ "key": "remote_addr",
+ "window_type": "sliding"
+ }
+ # highlight-end
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+ }'
+```
+
+Send a request to verify:
+
+```shell
+curl -i "http://127.0.0.1:9080/get"
+```
+
+You should receive an `HTTP/1.1 200 OK` response and see the following headers:
+
+```text
+X-Custom-RateLimit-Limit: 1
+X-Custom-RateLimit-Remaining: 0
+X-Custom-RateLimit-Reset: 28
+```
+
## Delete Plugin
To remove the `limit-count` Plugin, you can delete the corresponding JSON
configuration from the Plugin configuration. APISIX will automatically reload
and you do not have to restart for this to take effect.
diff --git a/t/plugin/limit-count5.t b/t/plugin/limit-count5.t
index cb4615990..4227b4f10 100644
--- a/t/plugin/limit-count5.t
+++ b/t/plugin/limit-count5.t
@@ -137,3 +137,66 @@ passed
["GET /hello", "GET /hello", "GET /hello", "GET /hello"]
--- error_code eval
[200, 200, 503, 503]
+
+
+
+=== TEST 4: customize rate limit headers by plugin metadata
+--- 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,
+ [[{
+ "methods": ["GET"],
+ "plugins": {
+ "limit-count": {
+ "count": 10,
+ "time_window": 60,
+ "rejected_code": 503,
+ "key_type": "var",
+ "key": "remote_addr"
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ ngx.say("fail")
+ return
+ end
+ local code, meta_body =
t('/apisix/admin/plugin_metadata/limit-count',
+ ngx.HTTP_PUT,
+ [[{
+ "limit_header":"APISIX-RATELIMIT-QUOTA",
+ "remaining_header":"APISIX-RATELIMIT-REMAINING",
+ "reset_header":"APISIX-RATELIMIT-RESET"
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ ngx.say("fail")
+ return
+ end
+ ngx.say("passed")
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 5: check rate limit headers
+--- request
+GET /hello
+--- response_headers_like
+APISIX-RATELIMIT-QUOTA: 10
+APISIX-RATELIMIT-REMAINING: 9
+APISIX-RATELIMIT-RESET: \d+