Skip to content

Instantly share code, notes, and snippets.

@jamesbjackson
Forked from jbaiter/rate-limit.lua
Created July 31, 2019 11:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamesbjackson/eabd46769eeaec790a78ee3d82ea7f7d to your computer and use it in GitHub Desktop.
Save jamesbjackson/eabd46769eeaec790a78ee3d82ea7f7d to your computer and use it in GitHub Desktop.
Simple Nginx Rate Limiting with Lua, redis and redis-cell
-- 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 admin@example.com.")
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