514 lines
14 KiB
Lua
514 lines
14 KiB
Lua
local helpers = require "spec.helpers"
|
|
local cjson = require "cjson"
|
|
|
|
local mock_fn_one = [[
|
|
ngx.status = 503
|
|
ngx.exit(ngx.status)
|
|
]]
|
|
|
|
local mock_fn_two = [[
|
|
ngx.status = 404
|
|
ngx.say("Not Found")
|
|
ngx.exit(ngx.status)
|
|
]]
|
|
|
|
local mock_fn_three = [[
|
|
return kong.response.exit(406, { message = "Invalid" })
|
|
]]
|
|
|
|
local mock_fn_four = [[
|
|
ngx.status = 400
|
|
]]
|
|
|
|
local mock_fn_five = [[
|
|
ngx.exit(ngx.status)
|
|
]]
|
|
|
|
local mock_fn_six = [[
|
|
local count = 0
|
|
ngx.log(ngx.ERR, "mock_fn_six: initialization ran")
|
|
return function()
|
|
ngx.log(ngx.ERR, "mock_fn_six: function ran")
|
|
count = count + 1
|
|
ngx.status = 200
|
|
ngx.say(ngx.worker.pid() * 1000 + count)
|
|
ngx.exit(ngx.status)
|
|
end
|
|
]]
|
|
|
|
local mock_fn_seven = [[
|
|
ngx.req.read_body()
|
|
|
|
local count = tonumber(ngx.req.get_body_data())
|
|
count = count + 1
|
|
|
|
ngx.status = 200
|
|
ngx.say(count)
|
|
ngx.exit(ngx.status)
|
|
]]
|
|
|
|
-- same as 7, but with upvalue format
|
|
local mock_fn_eight = "return function() \n" .. mock_fn_seven .. "\n end"
|
|
|
|
local mock_fn_nine = [[
|
|
error("this should stop the request with a 500")
|
|
]]
|
|
|
|
local mock_fn_ten = [[
|
|
ngx.var.args = nil
|
|
]]
|
|
|
|
-- cache is accessible
|
|
local mock_fn_eleven = [[
|
|
local ok, err = kong.cache:get("foo", nil, function() return "val" end)
|
|
if err then
|
|
ngx.exit(500)
|
|
end
|
|
local v = kong.cache:get("foo")
|
|
ngx.status = 200
|
|
ngx.say(v)
|
|
ngx.exit(ngx.status)
|
|
]]
|
|
|
|
-- cache does not allow access to gateway information
|
|
local mock_fn_twelve = [[
|
|
ngx.status = 200
|
|
ngx.say(tostring(kong.cache.cluster_events))
|
|
ngx.exit(ngx.status)
|
|
]]
|
|
|
|
-- configuration is accessible
|
|
local mock_fn_thirteen = [[
|
|
ngx.status = 200
|
|
ngx.say(kong.configuration.plugins[1])
|
|
ngx.exit(ngx.status)
|
|
]]
|
|
|
|
-- configuration restricts access to properties
|
|
local mock_fn_fourteen = [[
|
|
ngx.status = 200
|
|
ngx.say(kong.configuration.pg_password)
|
|
ngx.exit(ngx.status)
|
|
]]
|
|
|
|
|
|
describe("Plugin: serverless-functions", function()
|
|
it("priority of plugins", function()
|
|
local pre = require "kong.plugins.pre-function.handler"
|
|
local post = require "kong.plugins.post-function.handler"
|
|
assert(pre.PRIORITY > post.PRIORITY, "expected the priority of PRE (" ..
|
|
tostring(pre.PRIORITY) .. ") to be higher than POST (" ..
|
|
tostring(post.PRIORITY)..")")
|
|
end)
|
|
end)
|
|
|
|
|
|
|
|
for _, plugin_name in ipairs({ "pre-function", "post-function" }) do
|
|
|
|
for _, method in ipairs({ "phase=functions" }) do
|
|
local function get_conf(functions)
|
|
return { access = functions }
|
|
end
|
|
|
|
describe("Plugin: " .. plugin_name .. string.format(" (by %s)", method) .. " access", function()
|
|
local client, admin_client
|
|
|
|
setup(function()
|
|
local bp, db = helpers.get_db_utils()
|
|
|
|
assert(db:truncate())
|
|
|
|
local service = bp.services:insert {
|
|
name = "service-1",
|
|
host = helpers.mock_upstream_host,
|
|
port = helpers.mock_upstream_port,
|
|
}
|
|
|
|
local route1 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "one." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route2 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "two." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route3 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "three." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route4 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "four." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route6 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "six." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route7 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "seven." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route8 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "eight." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route9 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "nine." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route10 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "ten." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route11 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "eleven." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route12 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "twelve." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route13 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "thirteen." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
local route14 = bp.routes:insert {
|
|
service = { id = service.id },
|
|
hosts = { "fourteen." .. plugin_name .. ".test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route1.id },
|
|
config = get_conf { mock_fn_one },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route2.id },
|
|
config = get_conf { mock_fn_two },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route3.id },
|
|
config = get_conf { mock_fn_three },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route4.id },
|
|
config = get_conf { mock_fn_four, mock_fn_five },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route6.id },
|
|
config = get_conf { mock_fn_six },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route7.id },
|
|
config = get_conf { mock_fn_seven },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route8.id },
|
|
config = get_conf { mock_fn_eight },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route9.id },
|
|
config = get_conf { mock_fn_nine },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route10.id },
|
|
config = get_conf { mock_fn_ten },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route11.id },
|
|
config = get_conf { mock_fn_eleven },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route12.id },
|
|
config = get_conf { mock_fn_twelve },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route13.id },
|
|
config = get_conf { mock_fn_thirteen },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = plugin_name,
|
|
route = { id = route14.id },
|
|
config = get_conf { mock_fn_fourteen },
|
|
}
|
|
|
|
assert(helpers.start_kong({
|
|
nginx_conf = "spec/fixtures/custom_nginx.template",
|
|
}))
|
|
end)
|
|
|
|
teardown(function()
|
|
helpers.stop_kong()
|
|
end)
|
|
|
|
before_each(function()
|
|
client = helpers.proxy_client()
|
|
admin_client = helpers.admin_client()
|
|
end)
|
|
|
|
after_each(function()
|
|
if client and admin_client then
|
|
client:close()
|
|
admin_client:close()
|
|
end
|
|
end)
|
|
|
|
|
|
describe("request termination", function()
|
|
it("using ngx.exit()", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "one." .. plugin_name .. ".test"
|
|
}
|
|
})
|
|
|
|
assert.res_status(503, res)
|
|
end)
|
|
|
|
it("with upvalues", function()
|
|
local results = {}
|
|
for i = 1, 50 do
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "six." .. plugin_name .. ".test"
|
|
}
|
|
})
|
|
|
|
local body = assert.res_status(200, res)
|
|
assert.is_string(body)
|
|
--print(i, ": ", body)
|
|
assert.is_nil(results[body])
|
|
results[body] = true
|
|
end
|
|
end)
|
|
|
|
it("using ngx.status and exit", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "two." .. plugin_name .. ".test"
|
|
}
|
|
})
|
|
local body = assert.res_status(404, res)
|
|
assert.same("Not Found", body)
|
|
end)
|
|
|
|
it("import response utility and send message", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "three." .. plugin_name .. ".test"
|
|
}
|
|
})
|
|
local body = assert.res_status(406, res)
|
|
local json = cjson.decode(body)
|
|
assert.not_nil(json)
|
|
assert.matches("Invalid", json.message)
|
|
end)
|
|
|
|
it("cascading functions for a 400 and exit", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "four." .. plugin_name .. ".test"
|
|
}
|
|
})
|
|
local body = assert.res_status(400, res)
|
|
assert.matches("Bad request", body)
|
|
end)
|
|
|
|
it("runtime error aborts with a 500", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "nine." .. plugin_name .. ".test"
|
|
}
|
|
})
|
|
local body = assert.res_status(500, res)
|
|
local json = cjson.decode(body)
|
|
assert.not_nil(json)
|
|
assert.matches("An unexpected error occurred", json.message)
|
|
end)
|
|
end)
|
|
|
|
describe("invocation count", function()
|
|
it("once on initialization", function()
|
|
local count = 0
|
|
local res = assert(client:send {
|
|
method = "POST",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "seven." .. plugin_name .. ".test",
|
|
["Content-Length"] = #tostring(count),
|
|
},
|
|
body = count,
|
|
})
|
|
assert.equal(1, tonumber(res:read_body()))
|
|
end)
|
|
|
|
it("on repeated calls", function()
|
|
local count = 0
|
|
|
|
for i = 1, 10 do
|
|
local res = assert(client:send {
|
|
method = "POST",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "seven." .. plugin_name .. ".test",
|
|
["Content-Length"] = #tostring(count),
|
|
},
|
|
body = count,
|
|
})
|
|
count = tonumber(res:read_body())
|
|
end
|
|
|
|
assert.equal(10, count)
|
|
end)
|
|
|
|
it("once on initialization, with upvalues", function()
|
|
local count = 0
|
|
local res = assert(client:send {
|
|
method = "POST",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "eight." .. plugin_name .. ".test",
|
|
["Content-Length"] = #tostring(count),
|
|
},
|
|
body = count,
|
|
})
|
|
assert.equal(1, tonumber(res:read_body()))
|
|
end)
|
|
|
|
it("on repeated calls, with upvalues", function()
|
|
local count = 0
|
|
for i = 1, 10 do
|
|
local res = assert(client:send {
|
|
method = "POST",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "eight." .. plugin_name .. ".test",
|
|
["Content-Length"] = #tostring(count),
|
|
},
|
|
body = count,
|
|
})
|
|
count = tonumber(res:read_body())
|
|
end
|
|
|
|
assert.equal(10, count)
|
|
end)
|
|
end)
|
|
|
|
describe("sandbox access", function()
|
|
it("can access cache", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "eleven." .. plugin_name .. ".test",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
assert.is_not_nil(body)
|
|
assert.equal("val", body)
|
|
end)
|
|
|
|
it("cannot access gateway information through the cache", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "twelve." .. plugin_name .. ".test",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
assert.is_not_nil(body)
|
|
assert.equal("nil", body)
|
|
end)
|
|
|
|
it("can access kong.configuration fields", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "thirteen." .. plugin_name .. ".test",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
assert.is_not_nil(body)
|
|
assert.equal("bundled", body)
|
|
end)
|
|
|
|
it("redacts sensitive configuration fields", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "fourteen." .. plugin_name .. ".test",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
assert.is_not_nil(body)
|
|
assert.match("%*+", body)
|
|
end)
|
|
end)
|
|
|
|
describe("issues", function()
|
|
it("does not crash even when query is cleared, #9246", function()
|
|
local res = client:get("/status/200?a=b", {
|
|
headers = {
|
|
["Host"] = "ten." .. plugin_name .. ".test"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.same({}, json.uri_args)
|
|
end)
|
|
end)
|
|
end)
|
|
end
|
|
end
|