Skip to content

Commit f37c190

Browse files
feat: support configuring variables in limit-conn, limit-count and ai-rate-limiting (#12967)
1 parent 31148aa commit f37c190

File tree

12 files changed

+665
-62
lines changed

12 files changed

+665
-62
lines changed

apisix/plugins/ai-rate-limiting.lua

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,37 @@ local instance_limit_schema = {
2727
type = "object",
2828
properties = {
2929
name = {type = "string"},
30-
limit = {type = "integer", minimum = 1},
31-
time_window = {type = "integer", minimum = 1}
30+
limit = {
31+
oneOf = {
32+
{type = "integer", minimum = 1},
33+
{type = "string"},
34+
},
35+
},
36+
time_window = {
37+
oneOf = {
38+
{type = "integer", minimum = 1},
39+
{type = "string"},
40+
},
41+
}
3242
},
3343
required = {"name", "limit", "time_window"}
3444
}
3545

3646
local schema = {
3747
type = "object",
3848
properties = {
39-
limit = {type = "integer", exclusiveMinimum = 0},
40-
time_window = {type = "integer", exclusiveMinimum = 0},
49+
limit = {
50+
oneOf = {
51+
{type = "integer", exclusiveMinimum = 0},
52+
{type = "string"},
53+
},
54+
},
55+
time_window = {
56+
oneOf = {
57+
{type = "integer", exclusiveMinimum = 0},
58+
{type = "string"},
59+
},
60+
},
4161
show_limit_quota_header = {type = "boolean", default = true},
4262
limit_strategy = {
4363
type = "string",

apisix/plugins/limit-conn.lua

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,18 @@ local workflow = require("apisix.plugins.workflow")
2424
local schema = {
2525
type = "object",
2626
properties = {
27-
conn = {type = "integer", exclusiveMinimum = 0}, -- limit.conn max
28-
burst = {type = "integer", minimum = 0},
27+
conn = {
28+
oneOf = {
29+
{type = "integer", exclusiveMinimum = 0},
30+
{type = "string"},
31+
},
32+
},
33+
burst = {
34+
oneOf = {
35+
{type = "integer", minimum = 0},
36+
{type = "string"},
37+
},
38+
},
2939
default_conn_delay = {type = "number", exclusiveMinimum = 0},
3040
only_use_default_delay = {type = "boolean", default = false},
3141
key = {type = "string"},

apisix/plugins/limit-conn/init.lua

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ local limit_conn_new = require("resty.limit.conn").new
1818
local core = require("apisix.core")
1919
local is_http = ngx.config.subsystem == "http"
2020
local sleep = core.sleep
21+
local tonumber = tonumber
22+
local type = type
23+
local tostring = tostring
2124
local shdict_name = "plugin-limit-conn"
2225
if ngx.config.subsystem == "stream" then
2326
shdict_name = shdict_name .. "-stream"
@@ -34,38 +37,63 @@ do
3437
end
3538

3639

37-
local lrucache = core.lrucache.new({
38-
type = "plugin",
39-
})
4040
local _M = {}
4141

4242

43-
local function create_limit_obj(conf)
43+
local function create_limit_obj(ctx, conf)
4444
core.log.info("create new limit-conn plugin instance")
4545

46+
local conn = conf.conn
47+
if type(conn) == "string" then
48+
local err, _
49+
conn, err, _ = core.utils.resolve_var(conn, ctx.var)
50+
if err then
51+
return nil, "could not resolve vars in conn: " .. err
52+
end
53+
conn = tonumber(conn)
54+
if not conn then
55+
return nil, "resolved conn is not a number: " .. tostring(conn)
56+
end
57+
end
58+
59+
local burst = conf.burst
60+
if type(burst) == "string" then
61+
local err, _
62+
burst, err, _ = core.utils.resolve_var(burst, ctx.var)
63+
if err then
64+
return nil, "could not resolve vars in burst: " .. err
65+
end
66+
burst = tonumber(burst)
67+
if not burst then
68+
return nil, "resolved burst is not a number: " .. tostring(burst)
69+
end
70+
end
71+
72+
core.log.info("limit conn: ", conn, ", burst: ", burst)
73+
4674
if conf.policy == "redis" then
4775
core.log.info("create new limit-conn redis plugin instance")
4876

49-
return redis_single_new("plugin-limit-conn", conf, conf.conn, conf.burst,
77+
return redis_single_new("plugin-limit-conn", conf, conn, burst,
5078
conf.default_conn_delay)
5179

5280
elseif conf.policy == "redis-cluster" then
5381

5482
core.log.info("create new limit-conn redis-cluster plugin instance")
5583

56-
return redis_cluster_new("plugin-limit-conn", conf, conf.conn, conf.burst,
84+
return redis_cluster_new("plugin-limit-conn", conf, conn, burst,
5785
conf.default_conn_delay)
5886
else
5987
core.log.info("create new limit-conn plugin instance")
60-
return limit_conn_new(shdict_name, conf.conn, conf.burst,
88+
return limit_conn_new(shdict_name, conn, burst,
6189
conf.default_conn_delay)
6290
end
6391
end
6492

6593

6694
function _M.increase(conf, ctx)
6795
core.log.info("ver: ", ctx.conf_version)
68-
local lim, err = lrucache(conf, nil, create_limit_obj, conf)
96+
local lim, err = create_limit_obj(ctx, conf)
6997
if not lim then
7098
core.log.error("failed to instantiate a resty.limit.conn object: ", err)
7199
if conf.allow_degradation then

apisix/plugins/limit-count/init.lua

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ local pairs = pairs
2222
local redis_schema = require("apisix.utils.redis-schema")
2323
local policy_to_additional_properties = redis_schema.schema
2424
local get_phase = ngx.get_phase
25+
local tonumber = tonumber
26+
local type = type
27+
local tostring = tostring
2528

2629
local limit_redis_cluster_new
2730
local limit_redis_new
@@ -36,9 +39,6 @@ do
3639
local cluster_src = "apisix.plugins.limit-count.limit-count-redis-cluster"
3740
limit_redis_cluster_new = require(cluster_src).new
3841
end
39-
local lrucache = core.lrucache.new({
40-
type = 'plugin', serial_creating = true,
41-
})
4242
local group_conf_lru = core.lrucache.new({
4343
type = 'plugin',
4444
})
@@ -70,8 +70,18 @@ local metadata_schema = {
7070
local schema = {
7171
type = "object",
7272
properties = {
73-
count = {type = "integer", exclusiveMinimum = 0},
74-
time_window = {type = "integer", exclusiveMinimum = 0},
73+
count = {
74+
oneOf = {
75+
{type = "integer", exclusiveMinimum = 0},
76+
{type = "string"},
77+
},
78+
},
79+
time_window = {
80+
oneOf = {
81+
{type = "integer", exclusiveMinimum = 0},
82+
{type = "string"},
83+
},
84+
},
7585
group = {type = "string"},
7686
key = {type = "string", default = "remote_addr"},
7787
key_type = {type = "string",
@@ -174,22 +184,47 @@ function _M.check_schema(conf, schema_type)
174184
end
175185

176186

177-
local function create_limit_obj(conf, plugin_name)
187+
local function create_limit_obj(conf, ctx, plugin_name)
178188
core.log.info("create new " .. plugin_name .. " plugin instance")
179189

190+
local count = conf.count
191+
if type(count) == "string" then
192+
local err, _
193+
count, err, _ = core.utils.resolve_var(count, ctx.var)
194+
if err then
195+
return nil, "could not resolve vars in count: " .. err
196+
end
197+
count = tonumber(count)
198+
if not count then
199+
return nil, "resolved count is not a number: " .. tostring(count)
200+
end
201+
end
202+
203+
local time_window = conf.time_window
204+
if type(time_window) == "string" then
205+
local err, _
206+
time_window, err, _ = core.utils.resolve_var(time_window, ctx.var)
207+
if err then
208+
return nil, "could not resolve vars in time_window: " .. err
209+
end
210+
time_window = tonumber(time_window)
211+
if not time_window then
212+
return nil, "resolved time_window is not a number: " .. tostring(time_window)
213+
end
214+
end
215+
216+
core.log.info("limit count: ", count, ", time_window: ", time_window)
217+
180218
if not conf.policy or conf.policy == "local" then
181-
return limit_local_new("plugin-" .. plugin_name, conf.count,
182-
conf.time_window)
219+
return limit_local_new("plugin-" .. plugin_name, count, time_window)
183220
end
184221

185222
if conf.policy == "redis" then
186-
return limit_redis_new("plugin-" .. plugin_name,
187-
conf.count, conf.time_window, conf)
223+
return limit_redis_new("plugin-" .. plugin_name, count, time_window, conf)
188224
end
189225

190226
if conf.policy == "redis-cluster" then
191-
return limit_redis_cluster_new("plugin-" .. plugin_name, conf.count,
192-
conf.time_window, conf)
227+
return limit_redis_cluster_new("plugin-" .. plugin_name, count, time_window, conf)
193228
end
194229

195230
return nil
@@ -223,26 +258,11 @@ local function gen_limit_key(conf, ctx, key)
223258
end
224259

225260

226-
local function gen_limit_obj(conf, ctx, plugin_name)
227-
if conf.group then
228-
return lrucache(conf.group, "", create_limit_obj, conf, plugin_name)
229-
end
230-
231-
local extra_key
232-
if conf._vid then
233-
extra_key = conf.policy .. '#' .. conf._vid
234-
else
235-
extra_key = conf.policy
236-
end
237-
238-
return core.lrucache.plugin_ctx(lrucache, ctx, extra_key, create_limit_obj, conf, plugin_name)
239-
end
240-
241261
function _M.rate_limit(conf, ctx, name, cost, dry_run)
242262
core.log.info("ver: ", ctx.conf_version)
243263
core.log.info("conf: ", core.json.delay_encode(conf, true))
244264

245-
local lim, err = gen_limit_obj(conf, ctx, name)
265+
local lim, err = create_limit_obj(conf, ctx, name)
246266

247267
if not lim then
248268
core.log.error("failed to fetch limit.count object: ", err)
@@ -307,7 +327,7 @@ function _M.rate_limit(conf, ctx, name, cost, dry_run)
307327
if err == "rejected" then
308328
-- show count limit header when rejected
309329
if conf.show_limit_quota_header and set_header then
310-
core.response.set_header(set_limit_headers.limit_header, conf.count,
330+
core.response.set_header(set_limit_headers.limit_header, lim.limit,
311331
set_limit_headers.remaining_header, 0,
312332
set_limit_headers.reset_header, reset)
313333
end
@@ -326,7 +346,7 @@ function _M.rate_limit(conf, ctx, name, cost, dry_run)
326346
end
327347

328348
if conf.show_limit_quota_header and set_header then
329-
core.response.set_header(set_limit_headers.limit_header, conf.count,
349+
core.response.set_header(set_limit_headers.limit_header, lim.limit,
330350
set_limit_headers.remaining_header, remaining,
331351
set_limit_headers.reset_header, reset)
332352
end

apisix/plugins/limit-count/limit-count-local.lua

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ function _M.new(plugin_name, limit, window)
5757

5858
local self = {
5959
limit_count = limit_count.new(plugin_name, limit, window),
60-
dict = ngx.shared[plugin_name .. "-reset-header"]
60+
dict = ngx.shared[plugin_name .. "-reset-header"],
61+
limit = limit,
62+
window = window,
6163
}
6264

6365
return setmetatable(self, mt)
@@ -67,8 +69,8 @@ function _M.incoming(self, key, commit, conf, cost)
6769
local delay, remaining = self.limit_count:incoming(key, commit, cost)
6870
local reset
6971

70-
if remaining == conf.count - cost then
71-
reset = set_endtime(self, key, conf.time_window)
72+
if remaining == self.limit - cost then
73+
reset = set_endtime(self, key, self.window)
7274
else
7375
reset = read_reset(self, key)
7476
end

0 commit comments

Comments
 (0)