mirror of
https://gitee.com/iresty/apisix.git
synced 2024-12-02 12:07:35 +08:00
fix(proto): avoid sharing state (#6199)
This commit is contained in:
parent
b57f52302c
commit
14f0889bad
@ -16,6 +16,7 @@
|
||||
--
|
||||
local core = require("apisix.core")
|
||||
local config_util = require("apisix.core.config_util")
|
||||
local pb = require("pb")
|
||||
local protoc = require("protoc")
|
||||
local pcall = pcall
|
||||
local ipairs = ipairs
|
||||
@ -29,6 +30,10 @@ local lrucache_proto = core.lrucache.new({
|
||||
local proto_fake_file = "filename for loaded"
|
||||
|
||||
local function compile_proto(content)
|
||||
-- clear pb state
|
||||
pb.state(nil)
|
||||
|
||||
protoc.reload()
|
||||
local _p = protoc.new()
|
||||
-- the loaded proto won't appears in _p.loaded without a file name after lua-protobuf=0.3.2,
|
||||
-- which means _p.loaded after _p:load(content) is always empty, so we can pass a fake file
|
||||
@ -44,7 +49,23 @@ local function compile_proto(content)
|
||||
return nil, "failed to load proto content"
|
||||
end
|
||||
|
||||
return _p.loaded
|
||||
local compiled = _p.loaded
|
||||
-- fetch pb state
|
||||
compiled.pb_state = pb.state(nil)
|
||||
|
||||
local index = {}
|
||||
for _, s in ipairs(compiled[proto_fake_file].service or {}) do
|
||||
local method_index = {}
|
||||
for _, m in ipairs(s.method) do
|
||||
method_index[m.name] = m
|
||||
end
|
||||
|
||||
index[compiled[proto_fake_file].package .. '.' .. s.name] = method_index
|
||||
end
|
||||
|
||||
compiled[proto_fake_file].index = index
|
||||
|
||||
return compiled
|
||||
end
|
||||
|
||||
|
||||
@ -71,24 +92,7 @@ local function create_proto_obj(proto_id)
|
||||
return nil, "failed to find proto by id: " .. proto_id
|
||||
end
|
||||
|
||||
local compiled, err = compile_proto(content)
|
||||
|
||||
if not compiled then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local index = {}
|
||||
for _, s in ipairs(compiled[proto_fake_file].service or {}) do
|
||||
local method_index = {}
|
||||
for _, m in ipairs(s.method) do
|
||||
method_index[m.name] = m
|
||||
end
|
||||
|
||||
index[compiled[proto_fake_file].package .. '.' .. s.name] = method_index
|
||||
end
|
||||
|
||||
compiled[proto_fake_file].index = index
|
||||
return compiled
|
||||
return compile_proto(content)
|
||||
end
|
||||
|
||||
|
||||
|
@ -37,7 +37,14 @@ function _M.find_method(protos, service, method)
|
||||
return nil
|
||||
end
|
||||
|
||||
return loaded.index[service][method]
|
||||
local res = loaded.index[service][method]
|
||||
if not res then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- restore pb state
|
||||
pb.state(protos.pb_state)
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
|
102
t/plugin/grpc-transcode2.t
vendored
102
t/plugin/grpc-transcode2.t
vendored
@ -128,3 +128,105 @@ POST /grpctest
|
||||
Content-Type: application/json
|
||||
--- response_body chomp
|
||||
{"message":"Hello world, name: Joe"}
|
||||
|
||||
|
||||
|
||||
=== TEST 4: set rule to check if each proto is separate
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local t = require("lib.test_admin").test
|
||||
local etcd = require("apisix.core.etcd")
|
||||
local code, body = t('/apisix/admin/proto/2',
|
||||
ngx.HTTP_PUT,
|
||||
[[{
|
||||
"content" : "syntax = \"proto3\";
|
||||
package helloworld;
|
||||
service Greeter {
|
||||
rpc SayHello (HelloRequest) returns (HelloReply) {}
|
||||
}
|
||||
// same message, different fields. use to pollute the type info
|
||||
message HelloRequest {
|
||||
string name = 1;
|
||||
string person = 2;
|
||||
}
|
||||
message HelloReply {
|
||||
string message = 1;
|
||||
}"
|
||||
}]]
|
||||
)
|
||||
|
||||
if code >= 300 then
|
||||
ngx.status = code
|
||||
ngx.say(body)
|
||||
return
|
||||
end
|
||||
|
||||
local code, body = t('/apisix/admin/routes/2',
|
||||
ngx.HTTP_PUT,
|
||||
[[{
|
||||
"uri": "/fail",
|
||||
"plugins": {
|
||||
"grpc-transcode": {
|
||||
"proto_id": "2",
|
||||
"service": "helloworld.Greeter",
|
||||
"method": "SayHello"
|
||||
}
|
||||
},
|
||||
"upstream": {
|
||||
"scheme": "grpc",
|
||||
"type": "roundrobin",
|
||||
"nodes": {
|
||||
"127.0.0.1:50051": 1
|
||||
}
|
||||
}
|
||||
}]]
|
||||
)
|
||||
|
||||
if code >= 300 then
|
||||
ngx.status = code
|
||||
end
|
||||
ngx.say(body)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
passed
|
||||
|
||||
|
||||
|
||||
=== TEST 5: hit route
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local http = require "resty.http"
|
||||
local uri = "http://127.0.0.1:" .. ngx.var.server_port
|
||||
local body = [[{"name":"world","person":{"name":"John"}}]]
|
||||
local opt = {method = "POST", body = body, headers = {["Content-Type"] = "application/json"}}
|
||||
|
||||
local function access(path)
|
||||
local httpc = http.new()
|
||||
local res, err = httpc:request_uri(uri .. path, opt)
|
||||
if not res then
|
||||
ngx.say(err)
|
||||
return
|
||||
end
|
||||
if res.status > 300 then
|
||||
ngx.say(res.status)
|
||||
else
|
||||
ngx.say(res.body)
|
||||
end
|
||||
end
|
||||
|
||||
access("/fail")
|
||||
access("/grpctest")
|
||||
access("/fail")
|
||||
access("/grpctest")
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
400
|
||||
{"message":"Hello world, name: John"}
|
||||
400
|
||||
{"message":"Hello world, name: John"}
|
||||
--- error_log
|
||||
failed to encode request data to protobuf
|
||||
|
Loading…
Reference in New Issue
Block a user