From 6a03e1bd95594716167ccac840ff3e892ed66215 Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Thu, 18 Jul 2019 16:15:22 -0700 Subject: [PATCH] fix(router) ensure reducers respect matching priorities This patch ensures that when reducing categories, we always consider higher-priority categories first. --- kong/router.lua | 12 ++++++++- spec/01-unit/08-router_spec.lua | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/kong/router.lua b/kong/router.lua index 8fbc881e999a..783eed529449 100644 --- a/kong/router.lua +++ b/kong/router.lua @@ -72,6 +72,16 @@ local MATCH_RULES = { DST = 0x00000001, } +local SORTED_MATCH_RULES = {} + +for _, v in pairs(MATCH_RULES) do + insert(SORTED_MATCH_RULES, v) +end + +sort(SORTED_MATCH_RULES, function(a, b) + return a > b +end) + local MATCH_SUBRULES = { HAS_REGEX_URI = 0x01, PLAIN_HOSTS_ONLY = 0x02, @@ -851,7 +861,7 @@ do local reducers_set = {} - for _, bit_match_rule in pairs(MATCH_RULES) do + for _, bit_match_rule in ipairs(SORTED_MATCH_RULES) do if band(bit_category, bit_match_rule) ~= 0 then reducers_set[#reducers_set + 1] = reducers[bit_match_rule] end diff --git a/spec/01-unit/08-router_spec.lua b/spec/01-unit/08-router_spec.lua index a098b7fb6c26..cd9ee90a4bed 100644 --- a/spec/01-unit/08-router_spec.lua +++ b/spec/01-unit/08-router_spec.lua @@ -1088,6 +1088,54 @@ describe("Router", function() assert.truthy(route_t) assert.equal(use_case[2].route, route_t.route) end) + + it("more [headers] has priority over longer [paths]", function() + local use_case = { + { + service = service, + route = { + headers = { + version = { "v1" }, + }, + paths = { "/my-route/hello" }, + }, + }, + { + service = service, + route = { + headers = { + version = { "v1" }, + location = { "us-east" }, + }, + paths = { "/my-route" }, + }, + }, + } + + local router = assert(Router.new(use_case)) + + local match_t = router.select("GET", "/my-route/hello", "domain.org", + nil, nil, nil, nil, nil, { + version = "v1", + location = "us-east", + }) + assert.truthy(match_t) + assert.equal(use_case[2].route, match_t.route) + assert.same("/my-route", match_t.matches.uri) + assert.same({ version = "v1", location = "us-east" }, + match_t.matches.headers) + + local match_t = router.select("GET", "/my-route/hello/world", + "domain.org", nil, nil, nil, nil, nil, { + version = "v1", + location = "us-east", + }) + assert.truthy(match_t) + assert.equal(use_case[2].route, match_t.route) + assert.same("/my-route", match_t.matches.uri) + assert.same({ version = "v1", location = "us-east" }, + match_t.matches.headers) + end) end) describe("misses", function()