Skip to content

Commit

Permalink
bugfix(radixtree_host_uri): match priority, host > uri. (#817)
Browse files Browse the repository at this point in the history
* bugfix(radixtree_host_uri): match priority, host > uri.

Fix #761.
  • Loading branch information
membphis authored Nov 15, 2019
1 parent 35416e9 commit 77ad662
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 81 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ endif
check:
.travis/openwhisk-utilities/scancode/scanCode.py --config .travis/ASF-Release.cfg ./
luacheck -q lua
./utils/lj-releng lua/*.lua lua/apisix/*.lua \
./utils/lj-releng lua/*.lua \
lua/apisix/*.lua \
lua/apisix/admin/*.lua \
lua/apisix/core/*.lua \
lua/apisix/http/*.lua \
lua/apisix/http/router/*.lua \
lua/apisix/plugins/*.lua \
lua/apisix/plugins/grpc-transcode/*.lua \
lua/apisix/plugins/limit-count/*.lua > \
Expand Down
124 changes: 45 additions & 79 deletions lua/apisix/http/router/radixtree_host_uri.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,22 @@ local plugin = require("apisix.plugin")
local ipairs = ipairs
local type = type
local error = error
local tab_insert = table.insert
local loadstring = loadstring
local pairs = pairs
local user_routes
local cached_version
local only_uri_routes = {}
local host_router
local only_uri_router
local host_uri_routes = {}
local host_uri_router


local _M = {version = 0.1}


local function add_host_uri_routes(path, host, route)
core.log.info("add host+uri route, host: ", host, " path: ", path)
local function push_host_router(route, host_routes, only_uri_routes)
if type(route) ~= "table" then
return
end

local filter_fun, err
if route.value.filter_func then
Expand All @@ -50,98 +52,62 @@ local function add_host_uri_routes(path, host, route)
filter_fun = filter_fun()
end

core.table.insert(host_uri_routes, {
paths = {host .. path},
local hosts = route.value.hosts or {route.value.host}

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


local function push_radixtree_host_router(route)
if type(route) ~= "table" then
return
end

local hosts = route.value.hosts or {route.value.host}
local hosts_wildcard = {}
local uris = route.value.uris or {route.value.uri}

local added_count = 0
for _, host in ipairs(hosts) do
if host:sub(1, 1) == "*" then
core.table.insert(hosts_wildcard, host)
else
for _, uri in ipairs(uris) do
add_host_uri_routes(uri, host, route)
end
added_count = added_count + 1
end
end
}

-- 4 cases:
-- hosts = {}
-- hosts = {"foo.com"}
-- hosts = {"*.foo.com", "bar.com"}
-- hosts = {"*.foo.com", "*.bar.com"}
if added_count > 0 and added_count == #hosts then
if #hosts == 0 then
core.table.insert(only_uri_routes, radixtree_route)
return
end

if #hosts_wildcard == 0 then
hosts_wildcard = nil
end

local filter_fun, err
if route.value.filter_func then
filter_fun, err = loadstring(
"return " .. route.value.filter_func,
"router#" .. route.value.id)
if not filter_fun then
core.log.error("failed to load filter function: ", err,
" route id: ", route.value.id)
return
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}
else
tab_insert(host_routes[host_rev], radixtree_route)
end

filter_fun = filter_fun()
end

core.table.insert(only_uri_routes, {
paths = uris,
method = route.value.methods,
hosts = hosts_wildcard,
remote_addrs = route.value.remote_addrs or route.value.remote_addr,
vars = route.value.vars,
filter_fun = filter_fun,
handler = function (api_ctx)
api_ctx.matched_params = nil
api_ctx.matched_route = route
end,
})

return
end


local function create_radixtree_router(routes)
core.table.clear(host_uri_routes)
core.table.clear(only_uri_routes)
host_uri_router = nil
only_uri_router = nil
local host_routes = {}
local only_uri_routes = {}
host_router = nil

for _, route in ipairs(routes or {}) do
push_radixtree_host_router(route)
push_host_router(route, host_routes, only_uri_routes)
end

-- create router: host_uri_router
if #host_uri_routes > 0 then
host_uri_router = router.new(host_uri_routes)
-- 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, {
paths = host_rev,
filter_fun = function(vars, opts, ...)
return sub_router:dispatch(vars.uri, opts, ...)
end,
handler = function (api_ctx)
end
})
end
if #host_router_routes > 0 then
host_router = router.new(host_router_routes)
end

-- create router: only_uri_router
Expand Down Expand Up @@ -176,9 +142,9 @@ function _M.match(api_ctx)
match_opts.vars = api_ctx.var
match_opts.host = api_ctx.var.host

if host_uri_router then
local host_uri = api_ctx.var.host .. api_ctx.var.uri
local ok = host_uri_router:dispatch(host_uri, match_opts, api_ctx)
if host_router then
local host_uri = api_ctx.var.host
local ok = host_router:dispatch(host_uri:reverse(), match_opts, api_ctx)
if ok then
return true
end
Expand Down
3 changes: 2 additions & 1 deletion lua/apisix/schema_def.lua
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ local upstream_schema = {
description = "the key of chash for dynamic load balancing",
type = "string",
pattern = [[^((uri|server_name|server_addr|request_uri|remote_port]]
.. [[|remote_addr|query_string|host|hostname)|arg_[0-9a-zA-z_-]+)$]],
.. [[|remote_addr|query_string|host|hostname)]]
.. [[|arg_[0-9a-zA-z_-]+)$]],
},
desc = {type = "string", maxLength = 256},
id = id_schema
Expand Down
Loading

0 comments on commit 77ad662

Please sign in to comment.