Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cfddd8b
increment route update for radixtree host uri, radixtree uri and radi…
ranxuxin001 Jun 19, 2023
455b881
Merge branch 'apache:master' into master
ranxuxin001 Jun 26, 2023
3a18a38
erase unused function and remove useless space
ranxuxin001 Jun 26, 2023
180e2a8
upgrade version of radixtree
ranxuxin001 Jun 26, 2023
2ccd28d
avoid incremental update a route while not base on config_etcd source.
ranxuxin001 Jun 26, 2023
02021f8
be compitable to ai plugin and other config source
ranxuxin001 Jun 27, 2023
6db2b6d
inform ai plugin after init config_etcd object.
ranxuxin001 Jun 27, 2023
345a190
remove redundant even.push()
ranxuxin001 Jun 27, 2023
478ecaf
fix update route from only uri to host uri while host_uri mode
ranxuxin001 Jun 27, 2023
36a7a64
move filter() content to radixtree_uri
ranxuxin001 Jul 3, 2023
bd72921
increment update a route for radixtree host uri
ranxuxin001 Jul 3, 2023
aab6bb1
remove useless file
ranxuxin001 Jul 4, 2023
46069c7
tested host uri done
ranxuxin001 Jul 4, 2023
4e167ca
improve codes for uri, uri_with_parameter
ranxuxin001 Jul 4, 2023
2098b0d
test radixtree uri done.
ranxuxin001 Jul 4, 2023
b3a9621
tested uri with parameter done
ranxuxin001 Jul 4, 2023
2ff51f7
add id in route format
ranxuxin001 Jul 5, 2023
785e7f2
comment
ranxuxin001 Jul 5, 2023
80493bd
comment
ranxuxin001 Jul 5, 2023
aa0360b
fix warnings
ranxuxin001 Jul 5, 2023
4cb466f
improve codes
ranxuxin001 Jul 6, 2023
c7dc966
coding done.
ranxuxin001 Jul 7, 2023
6dad9c9
reuse function
ranxuxin001 Jul 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions apisix/core/config_etcd.lua
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ local function load_full_data(self, dir_res, headers)
item.clean_handlers = {}

if self.filter then
self.filter(item)
self.filter(item, 1, self)
end
end

Expand Down Expand Up @@ -551,7 +551,7 @@ local function load_full_data(self, dir_res, headers)
item.clean_handlers = {}

if self.filter then
self.filter(item)
self.filter(item, #values, self)
end
end

Expand Down Expand Up @@ -695,9 +695,10 @@ local function sync_data(self)
return false
end

local pre_val
local pre_index = self.values_hash[key]
if pre_index then
local pre_val = self.values[pre_index]
pre_val = self.values[pre_index]
if pre_val then
config_util.fire_all_clean_handlers(pre_val)
end
Expand Down Expand Up @@ -755,7 +756,7 @@ local function sync_data(self)
-- /plugins' filter need to known self.values when it is called
-- so the filter should be called after self.values set.
if self.filter then
self.filter(res)
self.filter(res, pre_val, self)
end

self.conf_version = self.conf_version + 1
Expand Down
1 change: 1 addition & 0 deletions apisix/http/route.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ function _M.create_radixtree_uri_router(routes, uri_routes, with_parameter)
core.log.info("insert uri route: ",
core.json.delay_encode(route.value, true))
core.table.insert(uri_routes, {
id = route.value.id,
paths = route.value.uris or route.value.uri,
methods = route.value.methods,
priority = route.value.priority,
Expand Down
267 changes: 209 additions & 58 deletions apisix/http/router/radixtree_host_uri.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,28 @@ local loadstring = loadstring
local pairs = pairs
local cached_router_version
local cached_service_version
local host_router
local only_uri_router
local base = require("resty.core.base")
local clear_tab = base.clear_tab


local _M = {version = 0.1}


local function push_host_router(route, host_routes, only_uri_routes)
local function tab_cpy(t1, t2)
Comment thread
kingluo marked this conversation as resolved.
Outdated
t1 = {}
for k, v in pairs(t2) do
t1[k] = v
end
end


function _M.push_host_router(route, host_routes, only_uri_routes, all_hosts, op, rdx_rt, pre_route, pre_rdx_rt)
if type(route) ~= "table" then
return
end

local filter_fun, err
if route.value.filter_func then
if route.value and route.value.filter_func then
filter_fun, err = loadstring(
"return " .. route.value.filter_func,
"router#" .. route.value.id)
Expand All @@ -53,113 +61,256 @@ local function push_host_router(route, host_routes, only_uri_routes)
filter_fun = filter_fun()
end

local hosts = route.value.hosts
if not hosts then
if route.value.host then
hosts = {route.value.host}
elseif route.value.service_id then
local service = service_fetch(route.value.service_id)
if not service then
core.log.error("failed to fetch service configuration by ",
"id: ", route.value.service_id)
-- we keep the behavior that missing service won't affect the route matching
else
hosts = service.value.hosts
local radixtree_route, pre_radixtree_route = {}, {}
local hosts
if route and route.value then
hosts = route.value.hosts
if not hosts then
if route.value.host then
hosts = {route.value.host}
elseif route.value.service_id then
local service = service_fetch(route.value.service_id)
if not service then
core.log.error("failed to fetch service configuration by ",
"id: ", route.value.service_id)
-- we keep the behavior that missing service won't affect the route matching
else
hosts = service.value.hosts
end
end
end

radixtree_route = {
id = route.value.id,
paths = route.value.uris or route.value.uri,
methods = route.value.methods,
priority = route.value.priority,
remote_addrs = route.value.remote_addrs
or route.value.remote_addr,
vars = route.value.vars,
filter_fun = filter_fun,
handler = function (api_ctx, match_opts)
api_ctx.matched_params = nil
api_ctx.matched_route = route
api_ctx.curr_req_matched = match_opts.matched
api_ctx.real_curr_req_matched_path = match_opts.matched._path
end
}

if rdx_rt ~= nil then
for k, v in pairs(radixtree_route) do
rdx_rt[k] = v
end
end
end

local radixtree_route = {
paths = route.value.uris or route.value.uri,
methods = route.value.methods,
priority = route.value.priority,
remote_addrs = route.value.remote_addrs
or route.value.remote_addr,
vars = route.value.vars,
filter_fun = filter_fun,
handler = function (api_ctx, match_opts)
api_ctx.matched_params = nil
api_ctx.matched_route = route
api_ctx.curr_req_matched = match_opts.matched
api_ctx.real_curr_req_matched_path = match_opts.matched._path
end
}

if hosts == nil then
if hosts == nil and all_hosts == nil then
core.table.insert(only_uri_routes, radixtree_route)
return
end

for i, host in ipairs(hosts) do
local host_rev = host:reverse()
if not host_routes[host_rev] then
host_routes[host_rev] = {radixtree_route}
local pre_hosts
if pre_route and pre_route.value then
pre_hosts = pre_route.value.hosts
if not pre_hosts then
if pre_route.value.host then
pre_hosts = {pre_route.value.host}
elseif pre_route.value.service_id then
local service = service_fetch(pre_route.value.service_id)
if not service then
core.log.error("failed to fetch service configuration by ",
"id: ", pre_route.value.service_id)
-- we keep the behavior that missing service won't affect the route matching
else
pre_hosts = service.value.hosts
end
end
end

pre_radixtree_route = {
id = pre_route.value.id,
paths = pre_route.value.uris or pre_route.value.uri,
methods = pre_route.value.methods,
priority = pre_route.value.priority,
remote_addrs = pre_route.value.remote_addrs
or pre_route.value.remote_addr,
vars = pre_route.value.vars,
filter_fun = filter_fun,
handler = function (api_ctx, match_opts)
api_ctx.matched_params = nil
api_ctx.matched_route = pre_route
api_ctx.curr_req_matched = match_opts.matched
api_ctx.real_curr_req_matched_path = match_opts.matched._path
end
}

if pre_rdx_rt ~= nil then
for k, v in pairs(pre_radixtree_route) do
pre_rdx_rt[k] = v
end
end
end

if all_hosts ~= nil then
all_hosts["host"] = hosts
all_hosts["pre_host"] = pre_hosts
end

local pre_t = {}
if pre_hosts then
for i, h in ipairs(pre_hosts) do
local rev_h = h:reverse()
pre_t[rev_h] = 1
end
end

local t = {}
if hosts then
for i, h in ipairs(hosts) do
local rev_h = h:reverse()
t[rev_h] = 1
end
end

local comm = {}
for k, v in pairs(pre_t) do
if t[k] ~= nil then
tab_insert(comm, k)
pre_t[k] = nil
t[k] = nil
end
end

for _, j in ipairs(comm) do
local routes = host_routes[j]
if routes == nil then
core.log.error("no routes array for reverse host in the map.", j)
return
end

local found = false
for i, r in ipairs(routes) do
if r.id == radixtree_route.id then
routes[i] = radixtree_route
found = true
if op then
table.insert(op["upd"], j)
end
break
end
end

if not found then
core.log.error("cannot find the route in common host's table.", j, radixtree_route.id)
return
end
end

for k, v in pairs(pre_t) do
local routes = host_routes[k]
if routes == nil then
core.log.error("no routes array for reverse host in the map.", k)
return
end

local found = false
for i, r in ipairs(routes) do
if r.id == pre_radixtree_route.id then
table.remove(routes, i)
found = true
break
end
end

if not found then
core.log.error("cannot find the route in previous host's table.", k, pre_radixtree_route.id)
return
end

if #routes == 0 then
host_routes[k] = nil
if op then
table.insert(op["del"], k)
end
else
if op then
table.insert(op["upd"], k)
end
end
end

for k, v in pairs(t) do
local routes = host_routes[k]
if routes == nil then
host_routes[k] = {radixtree_route}
if op then
table.insert(op["add"], k)
end
else
tab_insert(host_routes[host_rev], radixtree_route)
table.insert(routes, radixtree_route)
if op then
table.insert(op["upd"], k)
end
end
end
end


local function create_radixtree_router(routes)
function _M.create_radixtree_router(routes)
local host_routes = {}
local only_uri_routes = {}
host_router = nil
routes = routes or {}

for _, route in ipairs(routes) do
local status = core.table.try_read_attr(route, "value", "status")
-- check the status
if not status or status == 1 then
push_host_router(route, host_routes, only_uri_routes)
end
end
_M.push_host_router(route, host_routes, only_uri_routes)
end
Comment thread
kingluo marked this conversation as resolved.
Outdated
Comment thread
kingluo marked this conversation as resolved.
Outdated
end

-- create router: host_router
local host_router_routes = {}
for host_rev, routes in pairs(host_routes) do
local sub_router = router.new(routes)

core.table.insert(host_router_routes, {
id = 1,
paths = host_rev,
filter_fun = function(vars, opts, ...)
return sub_router:dispatch(vars.uri, opts, ...)
end,
handler = function (api_ctx, match_opts)
api_ctx.real_curr_req_matched_host = match_opts.matched._path
end
})
end
end
})
end

_M.host_routes = host_routes

event.push(event.CONST.BUILD_ROUTER, routes)

if #host_router_routes > 0 then
host_router = router.new(host_router_routes)
_M.host_router = router.new(host_router_routes)
end

-- create router: only_uri_router
only_uri_router = router.new(only_uri_routes)
_M.only_uri_router = router.new(only_uri_routes)

return true
end


local match_opts = {}
function _M.match(api_ctx)
local user_routes = _M.user_routes
local _, service_version = get_services()
if not cached_router_version or cached_router_version ~= user_routes.conf_version
or not cached_service_version or cached_service_version ~= service_version
then
create_radixtree_router(user_routes.values)
cached_router_version = user_routes.conf_version
cached_service_version = service_version
end

return _M.matching(api_ctx)
end


function _M.matching(api_ctx)
local host_router = _M.host_router
local only_uri_router = _M.only_uri_router

core.log.info("route match mode: radixtree_host_uri")

core.table.clear(match_opts)
Expand Down
Loading