Files
kong--kong/spec/02-integration/05-proxy/21-grpc_plugins_triggering_spec.lua
2026-07-13 12:32:21 +08:00

231 lines
5.7 KiB
Lua

local helpers = require "spec.helpers"
local pl_file = require "pl.file"
local TEST_CONF = helpers.test_conf
local function reload_router(flavor)
helpers = require("spec.internal.module").reload_helpers(flavor)
end
-- TODO: remove it when we confirm it is not needed
local function gen_route(flavor, r)
return r
end
local function find_in_file(pat, cnt)
local f = assert(io.open(TEST_CONF.prefix .. "/" .. TEST_CONF.proxy_error_log, "r"))
local line = f:read("*l")
local count = 0
while line do
if line:match(pat) then
count = count + 1
end
line = f:read("*l")
end
return cnt == -1 and count >= 1 or count == cnt
end
local function wait()
-- wait for the second log phase to finish, otherwise it might not appear
-- in the logs when executing this
helpers.wait_until(function()
local logs = pl_file.read(TEST_CONF.prefix .. "/" .. TEST_CONF.proxy_error_log)
local _, count = logs:gsub("%[logger%] log phase", "")
return count >= 1
end, 10)
end
-- Phrases and counters for unary grpc requests **without reflection**,
-- Phrases with a -1 count are checked to have at least one occurrence
local phrases = {
["%[logger%] init_worker phase"] = 1,
["%[logger%] configure phase"] = 1,
["%[logger%] rewrite phase"] = 1,
["%[logger%] access phase"] = 1,
["%[logger%] header_filter phase"] = 1,
["%[logger%] body_filter phase"] = -1,
["%[logger%] log phase"] = 1,
}
local phrases_ssl = {
["%[logger%] init_worker phase"] = 1,
["%[logger%] configure phase"] = 1,
["%[logger%] certificate phase"] = 1,
["%[logger%] rewrite phase"] = 1,
["%[logger%] access phase"] = 1,
["%[logger%] header_filter phase"] = 1,
["%[logger%] body_filter phase"] = -1,
["%[logger%] log phase"] = 1,
}
-- Phrases and counters for unary grpc requests **with reflection**,
-- Phrases with a -1 count are checked to have at least one occurrence
--
-- "Reflection" is a gRPC server extension to assist clients without prior
-- prior knowledge of the server's services methods and messages formats.
--
-- A request sent to method `/hello.HelloService/SayHello` without a protobuf
-- file will result in two requests, resembling the following:
-- /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo
-- (obtain methods and data formats)
-- /hello.HelloService/SayHello
-- (perform actual intended request)
local phrases_reflection = {
["%[logger%] init_worker phase"] = 1,
["%[logger%] configure phase"] = 1,
["%[logger%] rewrite phase"] = 2,
["%[logger%] access phase"] = 2,
["%[logger%] header_filter phase"] = 2,
["%[logger%] body_filter phase"] = -1,
["%[logger%] log phase"] = 2,
}
local phrases_ssl_reflection = {
["%[logger%] init_worker phase"] = 1,
["%[logger%] configure phase"] = 1,
["%[logger%] certificate phase"] = 1,
["%[logger%] rewrite phase"] = 2,
["%[logger%] access phase"] = 2,
["%[logger%] header_filter phase"] = 2,
["%[logger%] body_filter phase"] = -1,
["%[logger%] log phase"] = 2,
}
local function assert_phases(phrases)
for phase, count in pairs(phrases) do
assert(find_in_file(phase, count))
end
end
for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" }) do
for _, strategy in helpers.each_strategy() do
describe("gRPC Proxying [#" .. strategy .. ", flavor = " .. flavor .. "]", function()
local grpc_client
local grpcs_client
local bp
reload_router(flavor)
before_each(function()
bp = helpers.get_db_utils(strategy, {
"routes",
"services",
"plugins",
}, {
"logger",
})
local service1 = assert(bp.services:insert {
name = "grpc",
url = helpers.grpcbin_url,
})
local service2 = assert(bp.services:insert {
name = "grpcs",
url = helpers.grpcbin_ssl_url,
})
assert(bp.routes:insert(gen_route(flavor, {
protocols = { "grpc" },
hosts = { "grpc" },
service = service1,
})))
assert(bp.routes:insert(gen_route(flavor, {
protocols = { "grpcs" },
hosts = { "grpcs" },
service = service2,
})))
assert(bp.plugins:insert {
name = "logger",
})
assert(helpers.start_kong {
router_flavor = flavor,
database = strategy,
plugins = "logger",
})
grpc_client = assert(helpers.proxy_client_grpc())
grpcs_client = assert(helpers.proxy_client_grpcs())
end)
after_each(function()
helpers.stop_kong()
end)
it("grpc", function()
local ok, resp = grpc_client({
service = "hello.HelloService.SayHello",
opts = {
["-authority"] = "grpc",
},
})
assert.truthy(ok)
assert.truthy(resp)
wait()
assert_phases(phrases)
end)
it("grpcs", function()
local ok, resp = grpcs_client({
service = "hello.HelloService.SayHello",
opts = {
["-authority"] = "grpcs",
},
})
assert(ok)
assert.truthy(resp)
wait()
assert_phases(phrases_ssl)
end)
it("grpc - with reflection", function()
local ok, resp = grpc_client({
service = "hello.HelloService.SayHello",
opts = {
["-authority"] = "grpc",
["-proto"] = false,
},
})
assert(ok)
assert.truthy(resp)
wait()
assert_phases(phrases_reflection)
end)
it("grpcs - with reflection", function()
local ok, resp = grpcs_client({
service = "hello.HelloService.SayHello",
opts = {
["-authority"] = "grpcs",
["-proto"] = false,
},
})
assert.truthy(ok)
assert.truthy(resp)
wait()
assert_phases(phrases_ssl_reflection)
end)
end)
end
end -- flavor