in kong/kong/pdk/response.lua [1129:1215]
function _RESPONSE.error(status, message, headers)
if self.worker_events and ngx.get_phase() == "content" then
self.worker_events.poll()
end
check_phase(rewrite_access_header)
if ngx.headers_sent then
error("headers have already been sent", 2)
end
if type(status) ~= "number" then
error("code must be a number", 2)
elseif status < MIN_ERR_STATUS_CODE or status > MAX_STATUS_CODE then
error(fmt("code must be a number between %u and %u", MIN_ERR_STATUS_CODE,
MAX_STATUS_CODE), 2)
end
if message ~= nil then
if type(message) == "table" then
local err
message, err = cjson.encode(message)
if err then
error("could not JSON encode the error message: " .. err, 2)
end
end
if type(message) ~= "string" then
error("message must be a nil, a string or a table", 2)
end
end
if headers ~= nil and type(headers) ~= "table" then
error("headers must be a nil or table", 2)
end
if headers ~= nil then
validate_headers(headers)
else
headers = {}
end
local content_type_header = headers[CONTENT_TYPE_NAME]
local content_type = content_type_header and content_type_header[1]
or content_type_header
if content_type_header == nil then
if is_grpc_request() then
content_type = CONTENT_TYPE_GRPC
else
content_type_header = ngx.req.get_headers()[ACCEPT_NAME]
if type(content_type_header) == "table" then
content_type_header = content_type_header[1]
end
content_type = get_response_type(content_type_header)
end
end
headers[CONTENT_TYPE_NAME] = content_type
local body
if content_type ~= CONTENT_TYPE_GRPC then
local actual_message = message or
HTTP_MESSAGES["s" .. status] or
fmt(HTTP_MESSAGES.default, status)
body = fmt(utils.get_error_template(content_type), actual_message)
end
local ctx = ngx.ctx
ctx.KONG_EXITED = true
if ctx.delay_response and not ctx.delayed_response then
ctx.delayed_response = {
status_code = status,
content = body,
headers = headers,
}
ctx.delayed_response_callback = flush
coroutine.yield()
else
return send(status, body, headers)
end
end