Limit request frequency of each URL using openresty

Edit nginx http block

Edit the nginx conf file's http block and declare a lua_shared_dict which is shared by nginx workers. It will be used by lua script later.

Here is an example:

# 10m means 10MB.
lua_shared_dict my_store 10m;

# the following lines are only necessary for very old versions of openresty.
init_by_lua_block {
    require "resty.core"
}

Edit nginx location block

Edit the nginx conf file's location block, and add access_by_lua_block which uses lua script to limit API rate of different URL.

Here is an example:

location /api/ {
  access_by_lua_block {
    local limit_count = require 'resty.limit.count'
    -- define all the urls to be limited here.
    -- {20, 1} means 20 requests in one second
    local urls = {
      ['/api/foo'] =  {20, 1},
      ['/api/bar'] =  {30, 1},
    }

    local key = ngx.var.uri
    local rate = urls[key]
    local cnt, window
    if not rate then
        return
    else
        cnt, window = rate[1], rate[2]
    end

    -- my_store is declared in http block previously
    local lim, err = limit_count.new('my_store', cnt, window)

    local delay, err = lim:incoming(key, true)

    if not delay then
        if err == 'rejected' then
            -- response for requests that are over limit.
            local josnstr = '{"error":"over limit"}'
            ngx.header['Content-Type'] = 'application/json; charset=utf-8'
            return ngx.say(josnstr)
        end
    end
  }
}
Posted on 2022-03-23