api7 / lua-resty-radixtree

Adaptive Radix Trees implemented in Lua / LuaJIT
https://api7.ai/
Apache License 2.0
256 stars 61 forks source link

feature: extend extra features to operate the radixtree. #128

Closed ranxuxin001 closed 1 year ago

ranxuxin001 commented 1 year ago

Hi everyone,

This commit extend more features to operate the radixtree. These extra features of the library is used by apache/apisix project in order to increase the performance of modifying a route through administration requests.

refer to #9334

CLAassistant commented 1 year ago

CLA assistant check
All committers have signed the CLA.

leslie-tsang commented 1 year ago

@ranxuxin001 Hello there, need test case to make sure the feat work as expected. :)

ranxuxin001 commented 1 year ago

This lua file could be used as the test case for extended api in radixtree library. To test it, write server block in apisix/cli/ngx_tpl.lua and restart apisix. After that, send requests to test add, update, delete api.

  1. to test add route: only write the test case lua file till step 1. Then send request as below:

curl 'http://10.1.1.1:12000/?name=json&weight=20' -v

response:

metadata /bb metadata /bb name: json other: foo/bar/gloo metadata add route succeed. nil

  1. to test update route: append the test case lua file till step 2. Then send request as below:

curl 'http://10.1.1.1:12000/?name=cinema&weight=20' -v

response:

nil nil name: nil other: nil nil metadata update route succeed.

  1. to test delete route: append the test case lua file till step 3. Then send request as below:

curl 'http://10.1.1.1:12000/?name=cinema&weight=20' -v

response:

nil nil name: nil other: nil nil metadata update route succeed. nil

server {
        listen 12000;

        location / { 
            #return 200 "aaaaaalove";    
            content_by_lua_file /tmp/radixtree_test.lua;
        }    
    }   
local radix = require("resty.radixtree")
local rx = radix.new({
    {
        paths = {"/aa", "/bb*", "/name/:name/*other"},
        hosts = {"*.bar.com", "foo.com"},
        methods = {"GET", "POST", "PUT"},
        remote_addrs = {"127.0.0.1","192.168.0.0/16",
                        "::1", "fe80::/32"},
        vars = {
            {"arg_name", "==", "json"},
            {"arg_weight", ">", 10},
        },
        filter_fun = function(vars, opts)
            return vars["arg_name"] == "json"
        end,

        metadata = "metadata /bb",
    }
})

-- try to match
local opts = {
    host = "foo.com",
    method = "GET",
    remote_addr = "127.0.0.1",
    vars = ngx.var,
}
ngx.say(rx:match("/aa", opts))

-- try to match and store the cached value
local opts = {
    host = "foo.com",
    method = "GET",
    remote_addr = "127.0.0.1",
    vars = ngx.var,
    matched = {}
}
ngx.say(rx:match("/name/json/foo/bar/gloo", opts))
ngx.say("name: ", opts.matched.name, " other: ", opts.matched.other)

--step 1. add route api
local router_opts = {
    no_param_match = true
}

local add_opts = {
    id = "00000000000024216171",
    paths = {"/abc/123*", "/def"},
    hosts = {"*.love.com", "angel.com"},
    methods = {"GET", "POST", "PUT"},
    remote_addrs = {"127.0.0.1","192.168.0.0/16",
                    "::1", "fe80::/32"},
    vars = {
        {"arg_name", "==", "json"},
        {"arg_weight", ">", 10}, 
    },
    filter_fun = function(vars, opts)
        return vars["arg_name"] == "json"
    end,
    metadata = "metadata add route succeed.",
}
rx:add_route(add_opts, router_opts)

local opts = {
    host = "abc.love.com",
    method = "GET",
    remote_addr = "127.0.0.1",
    vars = ngx.var,
}
ngx.say(rx:match("/abc/123456aa", opts))

--step 2. update route api
local update_opts = {
    id = "00000000000024216171",
    paths = {"/nigolas/cage*", "/tom/cruise"},
    hosts = {"*.angel.city.com", "impossible.mission.com"},
    methods = {"GET", "POST", "PUT"},
    remote_addrs = {"127.0.0.1","192.168.0.0/16",
                    "::1", "fe80::/32"},
    vars = {
        {"arg_name", "==", "cinema"},
        {"arg_weight", "<", 60}, 
    },
    filter_fun = function(vars, opts)
        return vars["arg_name"] == "cinema"
    end,
    metadata = "metadata update route succeed.",
}

rx:update_route(add_opts, update_opts, router_opts)

local opts = {
    host = "impossible.mission.com",
    method = "GET",
    remote_addr = "127.0.0.1",
    vars = ngx.var,
}
ngx.say(rx:match("/nigolas/cage/oscars", opts))

--step 3. 
rx:delete_route(update_opts, router_opts)
ngx.say(rx:match("/nigolas/cage/oscars", opts))
ranxuxin001 commented 1 year ago

@kingluo Test cases using Test:Nginx have been committed in ./t directory.