From dd87111f4886ae0c67c32f964289250334613d59 Mon Sep 17 00:00:00 2001 From: Warnar Boekkooi <88374436+boekkooi-lengoo@users.noreply.github.com> Date: Fri, 29 Dec 2023 02:19:14 +0100 Subject: [PATCH] bug: Trailing slash with argument is not respected (#140) * Fix linting errors Avoid unused loops, trailing whitespaces and hiding global vars. * Trailing Slash not respected with parameter Show the issue where when an argument is specified it's also matching without the trailing slash * Handle the trailing slash As ngx.re.split will `delete empty trailing ones` we need to double check that there is no required `/` at the end of the path. If there is a extra `/` then add it to the pat regex. Also see https://github.com/openresty/lua-resty-core/blob/50f73790b6bb1d83f52cb3b4ec7e4ab7f649ab32/lib/ngx/re.lua#L273 --- lib/resty/radixtree.lua | 29 +++++++++++++++++------------ t/parameter.t | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/lib/resty/radixtree.lua b/lib/resty/radixtree.lua index 5f9bfad..c03cf96 100644 --- a/lib/resty/radixtree.lua +++ b/lib/resty/radixtree.lua @@ -259,9 +259,9 @@ local function modify_route(self, opts) log_err("no route array exists or route array is not a table in hash_path.", path, opts.id) return false end - + update_tab_in_order(route_arr, opts, sort_route) - + return true end @@ -279,7 +279,7 @@ local function modify_route(self, opts) end update_tab_in_order(routes, opts, sort_route) - + return true end @@ -287,7 +287,7 @@ end local function remove_route(self, opts) local path = opts.path opts = clone_tab(opts) - + if not self.disable_path_cache_opt and opts.path_op == '=' then local route_arr = self.hash_path[path] if route_arr == nil or type(route_arr) ~= "table" then @@ -347,7 +347,7 @@ local function remove_route(self, opts) return end end - + log_err("removed route does not exist.", opts.id) return end @@ -506,7 +506,7 @@ end local function pre_update_route(self, path, route, global_opts) - if type(path) ~= "string" then + if type(path) ~= "string" then error("invalid argument path", 2) end @@ -628,9 +628,9 @@ end local tmp = {} -local lru_pat, err = lrucache.new(1000) +local lru_pat, lru_pat_err = lrucache.new(1000) if not lru_pat then - error("failed to generate new lru object: " .. err) + error("failed to generate new lru object: " .. lru_pat_err) end @@ -666,6 +666,11 @@ local function fetch_pat(path) end pat = table.concat(res, [[\/]]) + -- As ngx.re.split will remove empty trailing items check if there is a trailing slash and append it + if path:sub(-1) == '/' then + pat = pat .. [[\/]] + end + lru_pat:set(path, {pat, names}, 60 * 60) return pat, names end @@ -891,7 +896,7 @@ function _M.update_route(self, pre_r, r, opts) end local common = {} - for k,v in pairs(pre_t) do + for k in pairs(pre_t) do if t[k] ~= nil then table.insert(common, k) end @@ -899,16 +904,16 @@ function _M.update_route(self, pre_r, r, opts) for _, p in ipairs(common) do pre_update_route(self, p, r, opts) - + pre_t[p] = nil t[p] = nil end - for k,v in pairs(pre_t) do + for k in pairs(pre_t) do pre_delete_route(self, k, pre_r, opts) end - for k,v in pairs(t) do + for k in pairs(t) do pre_insert_route(self, k, r, opts) end end diff --git a/t/parameter.t b/t/parameter.t index 22ffa71..961779c 100644 --- a/t/parameter.t +++ b/t/parameter.t @@ -392,3 +392,39 @@ GET /t --- response_body match meta: /user/:user match meta: /user/:user/age/:age + + + +=== TEST 12: /name/:name/ (respect trailing slash) +--- config + location /t { + content_by_lua_block { + local json = require("toolkit.json") + local radix = require("resty.radixtree") + local rx = radix.new({ + { + paths = {"/name/:name/"}, + metadata = "metadata /name", + }, + }) + + local opts = {matched = {}} + local meta = rx:match("/name/json/", opts) + ngx.say("match meta: ", meta) + ngx.say("matched: ", json.encode(opts.matched)) + + opts.matched = {} + meta = rx:match("/name/json", opts) + ngx.say("match meta: ", meta) + ngx.say("matched: ", json.encode(opts.matched)) + } + } +--- request +GET /t +--- no_error_log +[error] +--- response_body +match meta: metadata /name +matched: {"_path":"/name/:name/","name":"json"} +match meta: nil +matched: []