You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2022/01/26 01:16:46 UTC
[apisix] branch master updated: fix(proto): avoid sharing state (#6199)
This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 14f0889 fix(proto): avoid sharing state (#6199)
14f0889 is described below
commit 14f0889badc808d8f2fb4a11ca4b4d0d3f026cf4
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Wed Jan 26 09:16:43 2022 +0800
fix(proto): avoid sharing state (#6199)
---
apisix/plugins/grpc-transcode/proto.lua | 42 +++++++------
apisix/plugins/grpc-transcode/util.lua | 9 ++-
t/plugin/grpc-transcode2.t | 102 ++++++++++++++++++++++++++++++++
3 files changed, 133 insertions(+), 20 deletions(-)
diff --git a/apisix/plugins/grpc-transcode/proto.lua b/apisix/plugins/grpc-transcode/proto.lua
index 33d84eb..de19be2 100644
--- a/apisix/plugins/grpc-transcode/proto.lua
+++ b/apisix/plugins/grpc-transcode/proto.lua
@@ -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
diff --git a/apisix/plugins/grpc-transcode/util.lua b/apisix/plugins/grpc-transcode/util.lua
index 8fbe962..18c9f78 100644
--- a/apisix/plugins/grpc-transcode/util.lua
+++ b/apisix/plugins/grpc-transcode/util.lua
@@ -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
diff --git a/t/plugin/grpc-transcode2.t b/t/plugin/grpc-transcode2.t
index 0e7fd2b..7a48077 100644
--- a/t/plugin/grpc-transcode2.t
+++ b/t/plugin/grpc-transcode2.t
@@ -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