kong--kong
152 行
3.5 KiB
Lua
152 行
3.5 KiB
Lua
local bit = require "bit"
|
|
|
|
|
|
local band = bit.band
|
|
local fmt = string.format
|
|
local ngx_get_phase = ngx.get_phase
|
|
|
|
|
|
local PHASES = {
|
|
--init = 0x00000001,
|
|
init_worker = 0x00000001,
|
|
certificate = 0x00000002,
|
|
client_hello = 0x00000008,
|
|
--set = 0x00000004,
|
|
rewrite = 0x00000010,
|
|
access = 0x00000020,
|
|
balancer = 0x00000040,
|
|
response = 0x00000080,
|
|
--content = 0x00000100,
|
|
header_filter = 0x00000200,
|
|
body_filter = 0x00000400,
|
|
--timer = 0x00001000,
|
|
log = 0x00002000,
|
|
preread = 0x00004000,
|
|
error = 0x01000000,
|
|
admin_api = 0x10000000,
|
|
cluster_listener = 0x00000100,
|
|
}
|
|
|
|
|
|
do
|
|
local t = {}
|
|
for k, v in pairs(PHASES) do
|
|
t[k] = v
|
|
end
|
|
|
|
for k, v in pairs(t) do
|
|
PHASES[v] = k
|
|
end
|
|
|
|
-- max lshift limit, 2^30 = 0x40000000
|
|
PHASES.n = 30
|
|
end
|
|
|
|
|
|
local function new_phase(...)
|
|
return bit.bor(...)
|
|
end
|
|
|
|
|
|
local function get_phases_names(phases)
|
|
local names = {}
|
|
local n = 1
|
|
|
|
for _ = 1, PHASES.n do
|
|
if band(phases, n) ~= 0 and PHASES[n] then
|
|
table.insert(names, PHASES[n])
|
|
end
|
|
|
|
n = bit.lshift(n, 1)
|
|
end
|
|
|
|
return names
|
|
end
|
|
|
|
|
|
local function check_phase(accepted_phases)
|
|
if not kong or not kong.ctx then
|
|
-- no _G.kong, we are likely in tests
|
|
return
|
|
end
|
|
|
|
local current_phase = ngx.ctx.KONG_PHASE
|
|
if not current_phase then
|
|
if ngx_get_phase() == "content" then
|
|
-- treat custom content blocks as the Admin API
|
|
current_phase = PHASES.admin_api
|
|
else
|
|
error(fmt("no phase in ngx.ctx.KONG_PHASE, (need one of %s)",
|
|
table.concat(get_phases_names(accepted_phases), ", ")), 3)
|
|
end
|
|
end
|
|
|
|
if band(current_phase, accepted_phases) ~= 0 then
|
|
return
|
|
end
|
|
|
|
local current_phase_name = PHASES[current_phase] or "'unknown phase'"
|
|
local accepted_phases_names = get_phases_names(accepted_phases)
|
|
|
|
error(fmt("function cannot be called in %s phase (only in: %s)",
|
|
current_phase_name,
|
|
table.concat(accepted_phases_names, ", ")), 3)
|
|
end
|
|
|
|
|
|
local function check_not_phase(rejected_phases)
|
|
if not kong or not kong.ctx then
|
|
-- no _G.kong, we are likely in tests
|
|
return
|
|
end
|
|
|
|
local current_phase = ngx.ctx.KONG_PHASE
|
|
if not current_phase then
|
|
error("no phase in ngx.ctx.KONG_PHASE", 3)
|
|
end
|
|
|
|
if band(current_phase, rejected_phases) == 0 then
|
|
return
|
|
end
|
|
|
|
local current_phase_name = PHASES[current_phase] or "'unknown phase'"
|
|
local rejected_phases_names = get_phases_names(rejected_phases)
|
|
|
|
error(fmt("function cannot be called in %s phase (can be called in any " ..
|
|
"phases except: %s)",
|
|
current_phase_name,
|
|
table.concat(rejected_phases_names, ", ")), 3)
|
|
end
|
|
|
|
|
|
-- Exact phases + convenience aliases
|
|
local public_phases = setmetatable({
|
|
request = new_phase(PHASES.rewrite,
|
|
PHASES.access,
|
|
PHASES.balancer,
|
|
PHASES.response,
|
|
PHASES.header_filter,
|
|
PHASES.body_filter,
|
|
PHASES.log,
|
|
PHASES.error,
|
|
PHASES.admin_api,
|
|
PHASES.cluster_listener),
|
|
}, {
|
|
__index = function(t, k)
|
|
error("unknown phase or phase alias: " .. k)
|
|
end
|
|
})
|
|
|
|
|
|
for k, v in pairs(PHASES) do
|
|
public_phases[k] = v
|
|
end
|
|
|
|
|
|
return {
|
|
new = new_phase,
|
|
check = check_phase,
|
|
check_not = check_not_phase,
|
|
phases = public_phases,
|
|
}
|