Skip to content

Commit

Permalink
fix(router) avoid shadowing longer URIs when methods or hosts are def…
Browse files Browse the repository at this point in the history
…ined

Signed-off-by: Thibault Charbonnier <[email protected]>
  • Loading branch information
Leon Zhang authored and thibaultcha committed May 19, 2017
1 parent 2b2ebf2 commit a46a07f
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 16 deletions.
49 changes: 33 additions & 16 deletions kong/core/router.lua
Original file line number Diff line number Diff line change
Expand Up @@ -434,29 +434,46 @@ function _M.new(apis)
end


for category_bit, category in pairs(categories) do
table.sort(category.apis, function(a, b)
if not band(category_bit, MATCH_RULES.URI) then
return
end
local function compare_uris_length(a, b, category_bit)
if not band(category_bit, MATCH_RULES.URI) then
return
end

local max_uri_a = 0
local max_uri_b = 0
local max_uri_a = 0
local max_uri_b = 0

for _, prefix in ipairs(a.uris_prefixes_regexes) do
if #prefix.regex > max_uri_a then
max_uri_a = #prefix.regex
end
for _, prefix in ipairs(a.uris_prefixes_regexes) do
if #prefix.regex > max_uri_a then
max_uri_a = #prefix.regex
end
end

for _, prefix in ipairs(b.uris_prefixes_regexes) do
if #prefix.regex > max_uri_b then
max_uri_b = #prefix.regex
end
for _, prefix in ipairs(b.uris_prefixes_regexes) do
if #prefix.regex > max_uri_b then
max_uri_b = #prefix.regex
end
end

return max_uri_a > max_uri_b
return max_uri_a > max_uri_b
end


for category_bit, category in pairs(categories) do
table.sort(category.apis, function(a, b)
return compare_uris_length(a, b, category_bit)
end)

for _, apis_by_method in pairs(category.apis_by_methods) do
table.sort(apis_by_method, function(a, b)
return compare_uris_length(a, b, category_bit)
end)
end

for _, apis_by_host in pairs(category.apis_by_plain_hosts) do
table.sort(apis_by_host, function(a, b)
return compare_uris_length(a, b, category_bit)
end)
end
end


Expand Down
70 changes: 70 additions & 0 deletions spec/01-unit/11-router_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,76 @@ describe("Router", function()
assert.same(use_case[2], api_t.api)
end)

it("does not superseds another API with a longer [uri] while [methods] are also defined", function()
local use_case = {
{
name = "api-1",
methods = { "POST", "PUT", "GET" },
uris = { "/my-api" },
},
{
name = "api-2",
methods = { "POST", "PUT", "GET" },
uris = { "/my-api/hello" },
}
}

local router = assert(Router.new(use_case))

local api_t = router.select("GET", "/my-api/hello")
assert.truthy(api_t)
assert.same(use_case[2], api_t.api)

api_t = router.select("GET", "/my-api/hello/world")
assert.truthy(api_t)
assert.same(use_case[2], api_t.api)

api_t = router.select("GET", "/my-api")
assert.truthy(api_t)
assert.same(use_case[1], api_t.api)

api_t = router.select("GET", "/my-api/world")
assert.truthy(api_t)
assert.same(use_case[1], api_t.api)
end)

it("does not superseds another API with a longer [uri] while [hosts] are also defined", function()
local use_case = {
{
name = "api-1",
uris = { "/my-api" },
headers = {
["host"] = { "domain.org" },
},
},
{
name = "api-2",
uris = { "/my-api/hello" },
headers = {
["host"] = { "domain.org" },
},
}
}

local router = assert(Router.new(use_case))

local api_t = router.select("GET", "/my-api/hello", "domain.org")
assert.truthy(api_t)
assert.same(use_case[2], api_t.api)

api_t = router.select("GET", "/my-api/hello/world", "domain.org")
assert.truthy(api_t)
assert.same(use_case[2], api_t.api)

api_t = router.select("GET", "/my-api", "domain.org")
assert.truthy(api_t)
assert.same(use_case[1], api_t.api)

api_t = router.select("GET", "/my-api/world", "domain.org")
assert.truthy(api_t)
assert.same(use_case[1], api_t.api)
end)

it("only matches URI as a prefix (anchored mode)", function()
local use_case = {
{
Expand Down
79 changes: 79 additions & 0 deletions spec/02-integration/05-proxy/01-router_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,85 @@ describe("Router", function()
end)
end)

describe("[uris] + [methods]", function()

setup(function()
insert_apis {
{
name = "root-api",
methods = { "GET" },
uris = "/root",
upstream_url = "http://httpbin.org",
},
{
name = "fixture-api",
methods = { "GET" },
uris = "/root/fixture",
upstream_url = "http://httpbin.org",
},
}

assert(helpers.start_kong())
end)

teardown(function()
helpers.stop_kong()
end)

it("prioritizes longer URIs", function()
local res = assert(client:send {
method = "GET",
path = "/root/fixture/get",
headers = {
["kong-debug"] = 1,
}
})

assert.res_status(200, res)
assert.equal("fixture-api", res.headers["kong-api-name"])
end)
end)

describe("[uris] + [hosts]", function()

setup(function()
insert_apis {
{
name = "root-api",
hosts = "api.com",
uris = "/root",
upstream_url = "http://httpbin.org",
},
{
name = "fixture-api",
hosts = "api.com",
uris = "/root/fixture",
upstream_url = "http://httpbin.org",
},
}

assert(helpers.start_kong())
end)

teardown(function()
helpers.stop_kong()
end)

it("prioritizes longer URIs", function()
local res = assert(client:send {
method = "GET",
path = "/root/fixture/get",
headers = {
["Host"] = "api.com",
["kong-debug"] = 1,
}
})

assert.res_status(200, res)
assert.equal("fixture-api", res.headers["kong-api-name"])
end)
end)

describe("trailing slash", function()
local checks = {
-- upstream url uris request path expected path strip uri
Expand Down

0 comments on commit a46a07f

Please sign in to comment.