From 8d223deb4aa156b2483338c7f226aeebc00adb06 Mon Sep 17 00:00:00 2001 From: spacewander Date: Fri, 20 Aug 2021 11:50:34 +0800 Subject: [PATCH] fix(grpc-transcode): support converting nested message Signed-off-by: spacewander --- apisix/plugins/grpc-transcode/util.lua | 21 ++-- ci/common.sh | 2 +- t/plugin/grpc-transcode2.t | 130 +++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 t/plugin/grpc-transcode2.t diff --git a/apisix/plugins/grpc-transcode/util.lua b/apisix/plugins/grpc-transcode/util.lua index faffecc7a4df..102e50d4171d 100644 --- a/apisix/plugins/grpc-transcode/util.lua +++ b/apisix/plugins/grpc-transcode/util.lua @@ -91,25 +91,34 @@ local function get_from_request(request_table, name, kind) end -function _M.map_message(field, default_values) +function _M.map_message(field, default_values, request_table) if not pb.type(field) then return nil, "Field " .. field .. " is not defined" end local request = {} local sub, err - local request_table = get_request_table() + if not request_table then + request_table = get_request_table() + end + for name, _, field_type in pb.fields(field) do local _, _, ty = pb.type(field_type) if ty ~= "enum" and field_type:sub(1, 1) == "." then - sub, err = _M.map_message(field_type, default_values) - if err then - return nil, err + if request_table[name] == nil then + sub = default_values and default_values[name] + else + sub, err = _M.map_message(field_type, default_values and default_values[name], + request_table[name]) + if err then + return nil, err + end end + request[name] = sub else request[name] = get_from_request(request_table, name, field_type) - or default_values[name] or nil + or (default_values and default_values[name]) end end return request diff --git a/ci/common.sh b/ci/common.sh index 56f2d33dec10..bf06c49f1bd8 100644 --- a/ci/common.sh +++ b/ci/common.sh @@ -31,4 +31,4 @@ create_lua_deps() { # luarocks install luacov-coveralls --tree=deps --local > build.log 2>&1 || (cat build.log && exit 1) } -GRPC_SERVER_EXAMPLE_VER=20210730 +GRPC_SERVER_EXAMPLE_VER=20210819 diff --git a/t/plugin/grpc-transcode2.t b/t/plugin/grpc-transcode2.t new file mode 100644 index 000000000000..0e7fd2b58a2c --- /dev/null +++ b/t/plugin/grpc-transcode2.t @@ -0,0 +1,130 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +use t::APISIX 'no_plan'; + +no_long_string(); +no_shuffle(); +no_root_location(); + +add_block_preprocessor(sub { + my ($block) = @_; + + if (!$block->request) { + $block->set_value("request", "GET /t"); + } + + if ((!defined $block->error_log) && (!defined $block->no_error_log)) { + $block->set_value("no_error_log", "[error]"); + } +}); + +run_tests; + +__DATA__ + +=== TEST 1: set rule +--- 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/1', + ngx.HTTP_PUT, + [[{ + "content" : "syntax = \"proto3\"; + package helloworld; + service Greeter { + rpc SayHello (HelloRequest) returns (HelloReply) {} + } + enum Gender { + GENDER_UNKNOWN = 0; + GENDER_MALE = 1; + GENDER_FEMALE = 2; + } + message Person { + string name = 1; + int32 age = 2; + } + message HelloRequest { + string name = 1; + repeated string items = 2; + Gender gender = 3; + Person person = 4; + } + message HelloReply { + string message = 1; + }" + }]] + ) + + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "uri": "/grpctest", + "plugins": { + "grpc-transcode": { + "proto_id": "1", + "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 2: hit route +--- request +POST /grpctest +{"name":"world","person":{"name":"Joe","age":1}} +--- more_headers +Content-Type: application/json +--- response_body chomp +{"message":"Hello world, name: Joe, age: 1"} + + + +=== TEST 3: hit route, missing some fields +--- request +POST /grpctest +{"name":"world","person":{"name":"Joe"}} +--- more_headers +Content-Type: application/json +--- response_body chomp +{"message":"Hello world, name: Joe"}