Skip to content

Commit 399e18b

Browse files
authored
feat: add support for keymatch5 function (#159)
* feat: add KeyMatch5 matcher Fixes #153 * test: add test for KeyMatch5
1 parent eb6c211 commit 399e18b

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

src/model/FunctionMap.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ local FunctionMap = {
2323
["keyMatch4"] = BuiltInFunctions.keyMatch4Func,
2424
["regexMatch"] = BuiltInFunctions.regexMatchFunc,
2525
["IPMatch"] = BuiltInFunctions.IPMatchFunc,
26-
["globMatch"] = BuiltInFunctions.globMatch
26+
["globMatch"] = BuiltInFunctions.globMatch,
27+
["keyMatch5"] = BuiltInFunctions.keyMatch4Func,
2728
}
2829

2930
-- FunctionMap provides a set of built in functions

src/util/BuiltInFunctions.lua

+25-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ local BuiltInFunctions = {}
1919

2020
function BuiltInFunctions.validateVariadicArgs(expectedLen, args)
2121
if #args ~= expectedLen then
22-
return error("Expected"..expectedLen.." arguments, but got "..#args)
22+
return error("Expected "..expectedLen.." arguments, but got "..#args)
2323
end
2424
for i=1,expectedLen do
2525
if type(args[i])~="string" then
@@ -247,6 +247,30 @@ function BuiltInFunctions.globMatch(key1, key2)
247247
end
248248
end
249249

250+
-- Wrapper for keyMatch5
251+
function BuiltInFunctions.keyMatch5Func(args)
252+
BuiltInFunctions.validateVariadicArgs(2, args)
253+
return BuiltInFunctions.keyMatch5(args[1], args[2])
254+
end
255+
256+
-- KeyMatch5 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *
257+
-- For example,
258+
-- - "/foo/bar?status=1&type=2" matches "/foo/bar"
259+
-- - "/parent/child1" and "/parent/child1" matches "/parent/*"
260+
-- - "/parent/child1?status=1" matches "/parent/*"
261+
function BuiltInFunctions.keyMatch5(key1, key2)
262+
local i = string.find(key1, "?", 1, true)
263+
264+
if i then
265+
key1 = string.sub(key1, 1, i - 1)
266+
end
267+
268+
key2 = string.gsub(key2, "/%*", "/.*")
269+
key2 = string.gsub(key2, "%{[^/]+%}", "[^/]+")
270+
271+
return string.match(key1, "^" .. key2 .. "$") ~= nil
272+
end
273+
250274
-- GenerateGFunction is the factory method of the g(_, _) function.
251275
function BuiltInFunctions.generateGFunction(rm)
252276
local function f(args)

tests/util/built_in_functions_spec.lua

+42
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,46 @@ describe("BuiltInFunctions tests", function ()
200200
assert.is.False(BuiltInFunctions.IPMatch("192.168.2.124", "192.168.2.123"))
201201
assert.is.False(BuiltInFunctions.IPMatch("192.166.2.123", "192.168.2.123"))
202202
end)
203+
204+
it("keyMatch5 tests", function ()
205+
assert.has_error(function () BuiltInFunctions.keyMatch5Func({"/foo"}) end, "Expected 2 arguments, but got 1")
206+
assert.has_error(function () BuiltInFunctions.keyMatch5Func({"/foo/create/123", "/foo/*", "/foo/update/123"}) end, "Expected 2 arguments, but got 3")
207+
assert.has_error(function () BuiltInFunctions.keyMatch5Func({"/parent/123", true}) end, "Argument must be a string")
208+
209+
assert.is.True(BuiltInFunctions.keyMatch5("/parent/child?status=1&type=2", "/parent/child"))
210+
assert.is.False(BuiltInFunctions.keyMatch5("/parent?status=1&type=2", "/parent/child"))
211+
212+
assert.is.True(BuiltInFunctions.keyMatch5("/parent/child/?status=1&type=2", "/parent/child/"))
213+
assert.is.False(BuiltInFunctions.keyMatch5("/parent/child/?status=1&type=2", "/parent/child"))
214+
assert.is.False(BuiltInFunctions.keyMatch5("/parent/child?status=1&type=2", "/parent/child/"))
215+
216+
assert.is.True(BuiltInFunctions.keyMatch5("/foo", "/foo"))
217+
assert.is.True(BuiltInFunctions.keyMatch5("/foo", "/foo*"))
218+
assert.is.False(BuiltInFunctions.keyMatch5("/foo", "/foo/*"))
219+
assert.is.False(BuiltInFunctions.keyMatch5("/foo/bar", "/foo"))
220+
assert.is.False(BuiltInFunctions.keyMatch5("/foo/bar", "/foo*"))
221+
assert.is.True(BuiltInFunctions.keyMatch5("/foo/bar", "/foo/*"))
222+
assert.is.False(BuiltInFunctions.keyMatch5("/foobar", "/foo"))
223+
assert.is.False(BuiltInFunctions.keyMatch5("/foobar", "/foo*"))
224+
assert.is.False(BuiltInFunctions.keyMatch5("/foobar", "/foo/*"))
225+
226+
assert.is.False(BuiltInFunctions.keyMatch5("/", "/{resource}"))
227+
assert.is.True(BuiltInFunctions.keyMatch5("/resource1", "/{resource}"))
228+
assert.is.False(BuiltInFunctions.keyMatch5("/myid", "/{id}/using/{resId}"))
229+
assert.is.True(BuiltInFunctions.keyMatch5("/myid/using/myresid", "/{id}/using/{resId}"))
230+
231+
assert.is.False(BuiltInFunctions.keyMatch5("/proxy/myid", "/proxy/{id}/*"))
232+
assert.is.True(BuiltInFunctions.keyMatch5("/proxy/myid/", "/proxy/{id}/*"))
233+
assert.is.True(BuiltInFunctions.keyMatch5("/proxy/myid/res", "/proxy/{id}/*"))
234+
assert.is.True(BuiltInFunctions.keyMatch5("/proxy/myid/res/res2", "/proxy/{id}/*"))
235+
assert.is.True(BuiltInFunctions.keyMatch5("/proxy/myid/res/res2/res3", "/proxy/{id}/*"))
236+
assert.is.False(BuiltInFunctions.keyMatch5("/proxy/", "/proxy/{id}/*"))
237+
238+
assert.is.False(BuiltInFunctions.keyMatch5("/proxy/myid?status=1&type=2", "/proxy/{id}/*"))
239+
assert.is.True(BuiltInFunctions.keyMatch5("/proxy/myid/", "/proxy/{id}/*"))
240+
assert.is.True(BuiltInFunctions.keyMatch5("/proxy/myid/res?status=1&type=2", "/proxy/{id}/*"))
241+
assert.is.True(BuiltInFunctions.keyMatch5("/proxy/myid/res/res2?status=1&type=2", "/proxy/{id}/*"))
242+
assert.is.True(BuiltInFunctions.keyMatch5("/proxy/myid/res/res2/res3?status=1&type=2", "/proxy/{id}/*"))
243+
assert.is.False(BuiltInFunctions.keyMatch5("/proxy/", "/proxy/{id}/*"))
244+
end)
203245
end)

0 commit comments

Comments
 (0)