openresty / lua-resty-limit-traffic

Lua library for limiting and controlling traffic in OpenResty/ngx_lua
819 stars 150 forks source link

Rate limit status headers #65

Open heatherKoo07 opened 3 years ago

heatherKoo07 commented 3 years ago

hello @agentzh, I have a question about how to add information about the rate limits and their current status. I know many services such as GitHub, Twitter, and Discord return response headers containing the information. For example, there exists "X-RateLimt-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset", and "Retry-After". (reference: https://jameslao.com/post/gcra-rate-limit-status/) I see resty.limit.count module has the first two headers and I wonder how to do the same thing in resty.limit.req (leaky bucket method)

Here's how I tried with rate=0.5req/s and burst=5.

http {
    lua_shared_dict my_limit_req_store 100m;

    server {
        location / {
            access_by_lua_block {
                local limit_req = require "resty.limit.req"
                local rate, burst = 0.5, 5
                local lim, err = limit_req.new("my_limit_req_store", rate, burst)
                if not lim then
                    ngx.log(ngx.ERR,
                            "failed to instantiate a resty.limit.req object: ", err)
                    return ngx.exit(500)
                end

                local key = ngx.var.binary_remote_addr
                local delay, err = lim:incoming(key, true)
                if not delay then
                    if err == "rejected" then
                        ngx.header["X-RateLimit-Limit"] = burst
                        ngx.header["X-RateLimit-Remaining"] = 0
                        ngx.header["Retry-After"] = 1/rate
                        return ngx.exit(503)
                    end
                    ngx.log(ngx.ERR, "failed to limit req: ", err)
                    return ngx.exit(500)
                end

                if delay >= 0.001 then
                    local excess = err
                    ngx.sleep(delay)
                end

                local remaining = burst - err

                ngx.header["X-RateLimit-Limit"] = burst
                ngx.header["X-RateLimit-Remaining"] = remaining
            }

        }
    }
}

"X-RateLimt-Limit" and "X-RateLimit-Remaining" seem to be working but I'm not sure how to implement "X-RateLimit-Reset", and "Retry-After". Could you help with this?

Thanks