Created
January 23, 2018 16:10
-
-
Save jbaiter/18a03170d1a7b4f0802953cfff705ff0 to your computer and use it in GitHub Desktop.
Simple Nginx Rate Limiting with Lua, redis and redis-cell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Requires the `redis-cell` module to be installed in Redis: https://github.com/brandur/redis-cell | |
local redis = require "nginx.redis" | |
local red = redis:new() | |
red:set_timeout(1000) | |
local ok, err = red:connect("127.0.0.1", 6379) | |
if not ok then | |
ngx.log(ngx.ERR, "failed to connect to redis: ", err) | |
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) | |
return | |
end | |
status, err = red["cl.throttle"]( | |
red, -- redis instance | |
ngx.var.remote_addr, -- key | |
15, -- max burst, i.e. after this the client is limited to 1 req/sec | |
30, -- max requests within the full timespan | |
60) -- reset limit to maximum size after this many seconds | |
if not status then | |
ngx.log(ngx.ERR, "failed to update rate limit: ", err) | |
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) | |
return | |
end | |
ok, err = red:set_keepalive(10*1000, 100) | |
if not ok then | |
ngx.log(ngx.ERR, "failed to set keepalive on redis: ", err) | |
end | |
ngx.header["X-RateLimit-Limit"] = status[2] | |
ngx.header["X-RateLimit-Remaining"] = status[3] | |
ngx.header["X-RateLimit-Reset"] = status[5] | |
if status[1] == 1 then | |
ngx.header["Retry-After"] = status[4] | |
ngx.status = ngx.HTTP_TOO_MANY_REQUESTS | |
ngx.header["Content-Type"] = "text/plain" | |
ngx.say("If you need your limits raised, please contact [email protected].") | |
ngx.exit(ngx.HTTP_OK) -- This response code will be ignored | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment