Hi, Lang, Apache APISIX was designed with this in mind. The `key` supports all nginx variables, including http_ *, cookie_ *, args_ *, etc.
However, in order to prevent misuse by users, this restriction is not relaxed at the code level. Developers need to manually add a key here[1] to unlock this feature. This is not described in the documentation, welcome to submit PR to improve the documentation, thank you [1] https://github.com/apache/incubator-apisix/blob/master/lua/apisix/plugins/limit-req.lua#L29 Thanks, Ming Wen, Apache APISIX Twitter: _WenMing Lang Wang <[email protected]> 于2020年2月25日周二 下午5:05写道: > Hello all, > > > We used to use this code below [1] to deal with limit-* case (for example: > ratelimit for sending sms verifycode): > > mobile stands for users' mobile phone no. from http post body. > But for other people maybe use `cookie`, `arg` or `mobile_phone` from body > instead. > So how can we avoid hard coding this key in the lua code? > > > 1. lua code like: > > location /verifycode { > default_type 'application/json'; > > #so you can to use set_by_lua from $mobile > set $mobile ''; > > access_by_lua_block { > local request_method = ngx.var.request_method > local args = nil > if "GET" == request_method then > local arg = ngx.req.get_uri_args()["mobile"] or 0 > ngx.var.mobile = arg > elseif "POST" == request_method then > cjson = require "cjson" > local body = ngx.req.get_body_data() > if body then > -- parsing json body for {mobile : 123, address: .... } > local body = cjson.decode(body) > local arg = body.mobile or 0 > ngx.var.mobile = arg > end > end > > local ratelimit = require "resty.redis.ratelimit" > local lim, err = ratelimit.new("verifycode", "1r/m", 0, 0) > > if not lim then > ngx.log(ngx.ERR, > "failed to instantiate a resty.redis.ratelimit > object: ", err) > return ngx.exit(500) > end > > local red = { host = "", port = 6379, timeout = 1, pass = "" } > > local key = ngx.var.mobile > local delay, err = lim:incoming(key, red) > if not delay then > if err == "rejected" then > return ngx.exit(429) > -- cjson = require "cjson" > -- ngx.say(cjson.encode({ code=1603, message = "Too > Many Requests", successful = true })) > end > ngx.log(ngx.ERR, "failed to limit req: ", err) > return ngx.exit(500) > end > > if delay >= 0.001 then > -- the 2nd return value holds the number of excess requests > -- per second for the specified key. > local excess = err > > ngx.sleep(delay) > end > } > } > > > > > Thanks. >
