2020-06-06 15:07:06 +00:00
|
|
|
local ngx = ngx
|
2019-09-24 01:46:59 +00:00
|
|
|
local string = string
|
|
|
|
local string_len = string.len
|
2019-08-15 15:04:32 +00:00
|
|
|
local string_format = string.format
|
2019-09-24 01:46:59 +00:00
|
|
|
local pairs = pairs
|
2020-05-19 03:51:30 +00:00
|
|
|
local ipairs = ipairs
|
2019-09-24 01:46:59 +00:00
|
|
|
local tonumber = tonumber
|
|
|
|
local getmetatable = getmetatable
|
|
|
|
local type = type
|
|
|
|
local next = next
|
|
|
|
local table = table
|
2020-05-19 03:51:30 +00:00
|
|
|
local re_gmatch = ngx.re.gmatch
|
2018-05-09 15:26:04 +00:00
|
|
|
|
|
|
|
local _M = {}
|
|
|
|
|
2018-05-18 21:36:43 +00:00
|
|
|
function _M.get_nodes(endpoints)
|
|
|
|
local nodes = {}
|
|
|
|
local weight = 1
|
|
|
|
|
|
|
|
for _, endpoint in pairs(endpoints) do
|
|
|
|
local endpoint_string = endpoint.address .. ":" .. endpoint.port
|
|
|
|
nodes[endpoint_string] = weight
|
|
|
|
end
|
|
|
|
|
|
|
|
return nodes
|
|
|
|
end
|
|
|
|
|
2020-05-19 03:51:30 +00:00
|
|
|
-- parse the compound variables, then call generate_var_value function
|
|
|
|
-- to parse into a string value.
|
|
|
|
function _M.parse_complex_value(complex_value)
|
|
|
|
local reg = [[ (\\\$[0-9a-zA-Z_]+) | ]] -- \$var
|
|
|
|
.. [[ \$\{([0-9a-zA-Z_]+)\} | ]] -- ${var}
|
|
|
|
.. [[ \$([0-9a-zA-Z_]+) | ]] -- $var
|
|
|
|
.. [[ (\$|[^$\\]+) ]] -- $ or text value
|
|
|
|
local iterator, err = re_gmatch(complex_value, reg, "jiox")
|
|
|
|
if not iterator then
|
|
|
|
return nil, err
|
|
|
|
end
|
|
|
|
|
|
|
|
local v
|
|
|
|
local t = {}
|
|
|
|
while true do
|
|
|
|
v, err = iterator()
|
|
|
|
if err then
|
|
|
|
return nil, err
|
|
|
|
end
|
|
|
|
|
|
|
|
if not v then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
|
|
|
|
table.insert(t, v)
|
|
|
|
end
|
|
|
|
|
|
|
|
return t
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Parse the return value of function parse_complex_value
|
|
|
|
-- into a string value
|
|
|
|
function _M.generate_var_value(data)
|
|
|
|
if data == nil then
|
|
|
|
return ""
|
|
|
|
end
|
|
|
|
|
|
|
|
local t = {}
|
|
|
|
for _, value in ipairs(data) do
|
|
|
|
local var_name = value[2] or value[3]
|
|
|
|
if var_name then
|
|
|
|
if var_name:match("^%d+$") then
|
|
|
|
var_name = tonumber(var_name)
|
|
|
|
end
|
|
|
|
table.insert(t, ngx.var[var_name])
|
|
|
|
else
|
|
|
|
table.insert(t, value[1] or value[4])
|
|
|
|
end
|
2018-08-21 17:42:21 +00:00
|
|
|
end
|
|
|
|
|
2020-05-19 03:51:30 +00:00
|
|
|
return table.concat(t, "")
|
2018-05-04 21:39:57 +00:00
|
|
|
end
|
2018-03-18 13:13:41 +00:00
|
|
|
|
2019-08-15 15:04:32 +00:00
|
|
|
-- normalize_endpoints takes endpoints as an array of endpoint objects
|
2019-09-24 01:46:59 +00:00
|
|
|
-- and returns a table where keys are string that's
|
|
|
|
-- endpoint.address .. ":" .. endpoint.port and values are all true
|
2019-08-15 15:04:32 +00:00
|
|
|
local function normalize_endpoints(endpoints)
|
|
|
|
local normalized_endpoints = {}
|
|
|
|
|
|
|
|
for _, endpoint in pairs(endpoints) do
|
|
|
|
local endpoint_string = string_format("%s:%s", endpoint.address, endpoint.port)
|
|
|
|
normalized_endpoints[endpoint_string] = true
|
|
|
|
end
|
|
|
|
|
|
|
|
return normalized_endpoints
|
|
|
|
end
|
|
|
|
|
|
|
|
-- diff_endpoints compares old and new
|
|
|
|
-- and as a first argument returns what endpoints are in new
|
|
|
|
-- but are not in old, and as a second argument it returns
|
|
|
|
-- what endpoints are in old but are in new.
|
|
|
|
-- Both return values are normalized (ip:port).
|
|
|
|
function _M.diff_endpoints(old, new)
|
|
|
|
local endpoints_added, endpoints_removed = {}, {}
|
2019-09-24 01:46:59 +00:00
|
|
|
local normalized_old = normalize_endpoints(old)
|
|
|
|
local normalized_new = normalize_endpoints(new)
|
2019-08-15 15:04:32 +00:00
|
|
|
|
|
|
|
for endpoint_string, _ in pairs(normalized_old) do
|
|
|
|
if not normalized_new[endpoint_string] then
|
|
|
|
table.insert(endpoints_removed, endpoint_string)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
for endpoint_string, _ in pairs(normalized_new) do
|
|
|
|
if not normalized_old[endpoint_string] then
|
|
|
|
table.insert(endpoints_added, endpoint_string)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return endpoints_added, endpoints_removed
|
|
|
|
end
|
|
|
|
|
2018-03-18 13:13:41 +00:00
|
|
|
-- this implementation is taken from
|
2020-06-06 15:07:06 +00:00
|
|
|
-- https://web.archive.org/web/20131225070434/http://snippets.
|
|
|
|
-- luacode.org/snippets/Deep_Comparison_of_Two_Values_3
|
2018-03-18 13:13:41 +00:00
|
|
|
-- and modified for use in this project
|
|
|
|
local function deep_compare(t1, t2, ignore_mt)
|
|
|
|
local ty1 = type(t1)
|
|
|
|
local ty2 = type(t2)
|
|
|
|
if ty1 ~= ty2 then return false end
|
|
|
|
-- non-table types can be directly compared
|
|
|
|
if ty1 ~= 'table' and ty2 ~= 'table' then return t1 == t2 end
|
|
|
|
-- as well as tables which have the metamethod __eq
|
|
|
|
local mt = getmetatable(t1)
|
|
|
|
if not ignore_mt and mt and mt.__eq then return t1 == t2 end
|
|
|
|
for k1,v1 in pairs(t1) do
|
|
|
|
local v2 = t2[k1]
|
|
|
|
if v2 == nil or not deep_compare(v1,v2) then return false end
|
|
|
|
end
|
|
|
|
for k2,v2 in pairs(t2) do
|
|
|
|
local v1 = t1[k2]
|
|
|
|
if v1 == nil or not deep_compare(v1,v2) then return false end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
_M.deep_compare = deep_compare
|
|
|
|
|
2018-03-23 15:06:21 +00:00
|
|
|
function _M.is_blank(str)
|
|
|
|
return str == nil or string_len(str) == 0
|
|
|
|
end
|
|
|
|
|
|
|
|
-- this implementation is taken from:
|
|
|
|
-- https://github.com/luafun/luafun/blob/master/fun.lua#L33
|
|
|
|
-- SHA: 04c99f9c393e54a604adde4b25b794f48104e0d0
|
|
|
|
local function deepcopy(orig)
|
|
|
|
local orig_type = type(orig)
|
|
|
|
local copy
|
|
|
|
if orig_type == 'table' then
|
|
|
|
copy = {}
|
|
|
|
for orig_key, orig_value in next, orig, nil do
|
|
|
|
copy[deepcopy(orig_key)] = deepcopy(orig_value)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
copy = orig
|
|
|
|
end
|
|
|
|
return copy
|
|
|
|
end
|
|
|
|
_M.deepcopy = deepcopy
|
|
|
|
|
2018-06-14 02:54:09 +00:00
|
|
|
local function tablelength(T)
|
|
|
|
local count = 0
|
|
|
|
for _ in pairs(T) do
|
|
|
|
count = count + 1
|
|
|
|
end
|
|
|
|
return count
|
|
|
|
end
|
|
|
|
_M.tablelength = tablelength
|
|
|
|
|
2020-07-21 20:02:23 +00:00
|
|
|
-- replaces special character value a with value b for all occurrences in a
|
2019-09-24 01:46:59 +00:00
|
|
|
-- string
|
2018-09-18 18:05:32 +00:00
|
|
|
local function replace_special_char(str, a, b)
|
|
|
|
return string.gsub(str, "%" .. a, b)
|
|
|
|
end
|
|
|
|
_M.replace_special_char = replace_special_char
|
|
|
|
|
2018-03-18 13:13:41 +00:00
|
|
|
return _M
|