This is an automated email from the ASF dual-hosted git repository.

spacewander pushed a commit to branch release/2.13
in repository https://gitbox.apache.org/repos/asf/apisix.git

commit 314d13cff555fe0b8110ad0053f6f44bba99d129
Author: 余茂林 <1090568...@qq.com>
AuthorDate: Fri Jun 17 11:07:33 2022 +0800

    fix: grpc-transcode request support object array  (#7231)
    
    Co-authored-by: jon.yu <jon...@ambergroup.io>
---
 apisix/plugins/grpc-transcode/util.lua            |  16 ++
 t/grpc_server_example/main.go                     |  25 ++
 t/grpc_server_example/proto/helloworld.pb.go      | 321 +++++++++++++++++-----
 t/grpc_server_example/proto/helloworld.proto      |  15 +
 t/grpc_server_example/proto/helloworld_grpc.pb.go |  40 +++
 t/grpc_server_example/proto/import.pb.go          |  21 +-
 t/grpc_server_example/proto/src.pb.go             |  21 +-
 t/grpc_server_example/proto/src_grpc.pb.go        |   4 +
 t/plugin/grpc-transcode3.t                        | 124 +++++++++
 9 files changed, 518 insertions(+), 69 deletions(-)

diff --git a/apisix/plugins/grpc-transcode/util.lua 
b/apisix/plugins/grpc-transcode/util.lua
index 2a7bfb648..68d300203 100644
--- a/apisix/plugins/grpc-transcode/util.lua
+++ b/apisix/plugins/grpc-transcode/util.lua
@@ -110,6 +110,22 @@ function _M.map_message(field, default_values, 
request_table)
         if ty ~= "enum" and field_type:sub(1, 1) == "." then
             if request_table[name] == nil then
                 sub = default_values and default_values[name]
+            elseif core.table.isarray(request_table[name]) then
+                local sub_array = core.table.new(#request_table[name], 0)
+                for i, value in ipairs(request_table[name]) do
+                    local sub_array_obj
+                    if type(value) == "table" then
+                        sub_array_obj, err = _M.map_message(field_type,
+                                default_values and default_values[name], value)
+                        if err then
+                            return nil, err
+                        end
+                    else
+                        sub_array_obj = value
+                    end
+                    sub_array[i] = sub_array_obj
+                end
+                sub = sub_array
             else
                 sub, err = _M.map_message(field_type, default_values and 
default_values[name],
                                           request_table[name])
diff --git a/t/grpc_server_example/main.go b/t/grpc_server_example/main.go
index 18bda0536..1b533582c 100644
--- a/t/grpc_server_example/main.go
+++ b/t/grpc_server_example/main.go
@@ -172,6 +172,31 @@ func (s *server) SayHelloBidirectionalStream(stream 
pb.Greeter_SayHelloBidirecti
        }
 }
 
+// SayMultipleHello implements helloworld.GreeterServer
+func (s *server) SayMultipleHello(ctx context.Context, in 
*pb.MultipleHelloRequest) (*pb.MultipleHelloReply, error) {
+       log.Printf("Received: %v", in.Name)
+       log.Printf("Enum Gender: %v", in.GetGenders())
+       msg := "Hello " + in.Name
+
+       persons := in.GetPersons()
+       if persons != nil {
+               for _, person := range persons {
+                       if person.GetName() != "" {
+                               msg += fmt.Sprintf(", name: %v", 
person.GetName())
+                       }
+                       if person.GetAge() != 0 {
+                               msg += fmt.Sprintf(", age: %v", person.GetAge())
+                       }
+               }
+       }
+
+       return &pb.MultipleHelloReply{
+               Message: msg,
+               Items:   in.GetItems(),
+               Genders: in.GetGenders(),
+       }, nil
+}
+
 func (s *server) Run(ctx context.Context, in *pb.Request) (*pb.Response, 
error) {
        return &pb.Response{Body: in.User.Name + " " + in.Body}, nil
 }
diff --git a/t/grpc_server_example/proto/helloworld.pb.go 
b/t/grpc_server_example/proto/helloworld.pb.go
index 9cb209566..71b16a345 100644
--- a/t/grpc_server_example/proto/helloworld.pb.go
+++ b/t/grpc_server_example/proto/helloworld.pb.go
@@ -1,8 +1,10 @@
-// Copyright 2015 gRPC authors.
 //
-// Licensed 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
+// 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
 //
@@ -11,11 +13,12 @@
 // 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.
+//
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-//     protoc-gen-go v1.27.1
-//     protoc        v3.6.1
+//     protoc-gen-go v1.25.0-devel
+//     protoc        v3.12.4
 // source: proto/helloworld.proto
 
 package proto
@@ -374,6 +377,140 @@ func (x *PlusReply) GetResult() int64 {
        return 0
 }
 
+type MultipleHelloRequest struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string    `protobuf:"bytes,1,opt,name=name,proto3" 
json:"name,omitempty"`
+       Items   []string  `protobuf:"bytes,2,rep,name=items,proto3" 
json:"items,omitempty"`
+       Genders []Gender  
`protobuf:"varint,3,rep,packed,name=genders,proto3,enum=helloworld.Gender" 
json:"genders,omitempty"`
+       Persons []*Person `protobuf:"bytes,4,rep,name=persons,proto3" 
json:"persons,omitempty"`
+}
+
+func (x *MultipleHelloRequest) Reset() {
+       *x = MultipleHelloRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_helloworld_proto_msgTypes[5]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *MultipleHelloRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MultipleHelloRequest) ProtoMessage() {}
+
+func (x *MultipleHelloRequest) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_helloworld_proto_msgTypes[5]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use MultipleHelloRequest.ProtoReflect.Descriptor instead.
+func (*MultipleHelloRequest) Descriptor() ([]byte, []int) {
+       return file_proto_helloworld_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *MultipleHelloRequest) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *MultipleHelloRequest) GetItems() []string {
+       if x != nil {
+               return x.Items
+       }
+       return nil
+}
+
+func (x *MultipleHelloRequest) GetGenders() []Gender {
+       if x != nil {
+               return x.Genders
+       }
+       return nil
+}
+
+func (x *MultipleHelloRequest) GetPersons() []*Person {
+       if x != nil {
+               return x.Persons
+       }
+       return nil
+}
+
+type MultipleHelloReply struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Message string   `protobuf:"bytes,1,opt,name=message,proto3" 
json:"message,omitempty"`
+       Items   []string `protobuf:"bytes,2,rep,name=items,proto3" 
json:"items,omitempty"`
+       Genders []Gender 
`protobuf:"varint,3,rep,packed,name=genders,proto3,enum=helloworld.Gender" 
json:"genders,omitempty"`
+}
+
+func (x *MultipleHelloReply) Reset() {
+       *x = MultipleHelloReply{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_helloworld_proto_msgTypes[6]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *MultipleHelloReply) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MultipleHelloReply) ProtoMessage() {}
+
+func (x *MultipleHelloReply) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_helloworld_proto_msgTypes[6]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use MultipleHelloReply.ProtoReflect.Descriptor instead.
+func (*MultipleHelloReply) Descriptor() ([]byte, []int) {
+       return file_proto_helloworld_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *MultipleHelloReply) GetMessage() string {
+       if x != nil {
+               return x.Message
+       }
+       return ""
+}
+
+func (x *MultipleHelloReply) GetItems() []string {
+       if x != nil {
+               return x.Items
+       }
+       return nil
+}
+
+func (x *MultipleHelloReply) GetGenders() []Gender {
+       if x != nil {
+               return x.Genders
+       }
+       return nil
+}
+
 var File_proto_helloworld_proto protoreflect.FileDescriptor
 
 var file_proto_helloworld_proto_rawDesc = []byte{
@@ -403,40 +540,63 @@ var file_proto_helloworld_proto_rawDesc = []byte{
        0x0a, 0x01, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x01, 0x62, 
0x22, 0x23, 0x0a, 0x09,
        0x50, 0x6c, 0x75, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x16, 0x0a, 
0x06, 0x72, 0x65, 0x73,
        0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x72, 
0x65, 0x73, 0x75, 0x6c,
-       0x74, 0x2a, 0x40, 0x0a, 0x06, 0x47, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 
0x12, 0x0a, 0x0e, 0x47,
-       0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 
0x4e, 0x10, 0x00, 0x12,
-       0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x4d, 0x41, 
0x4c, 0x45, 0x10, 0x01,
-       0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x46, 
0x45, 0x4d, 0x41, 0x4c,
-       0x45, 0x10, 0x02, 0x32, 0xc0, 0x03, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, 
0x74, 0x65, 0x72, 0x12,
-       0x3e, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 
0x18, 0x2e, 0x68, 0x65,
-       0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 
0x6c, 0x6f, 0x52, 0x65,
-       0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 
0x6f, 0x77, 0x6f, 0x72,
-       0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 
0x79, 0x22, 0x00, 0x12,
-       0x38, 0x0a, 0x04, 0x50, 0x6c, 0x75, 0x73, 0x12, 0x17, 0x2e, 0x68, 0x65, 
0x6c, 0x6c, 0x6f, 0x77,
-       0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x50, 0x6c, 0x75, 0x73, 0x52, 0x65, 0x71, 
0x75, 0x65, 0x73, 0x74,
-       0x1a, 0x15, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 
0x64, 0x2e, 0x50, 0x6c,
-       0x75, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x48, 0x0a, 
0x12, 0x53, 0x61, 0x79,
-       0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x41, 0x66, 0x74, 0x65, 0x72, 0x44, 0x65, 
0x6c, 0x61, 0x79, 0x12,
-       0x18, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 
0x2e, 0x48, 0x65, 0x6c,
-       0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 
0x68, 0x65, 0x6c, 0x6c,
-       0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 
0x52, 0x65, 0x70, 0x6c,
-       0x79, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x14, 0x53, 0x61, 0x79, 0x48, 0x65, 
0x6c, 0x6c, 0x6f, 0x53,
-       0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 
0x18, 0x2e, 0x68, 0x65,
-       0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 
0x6c, 0x6f, 0x52, 0x65,
-       0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 
0x6f, 0x77, 0x6f, 0x72,
-       0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 
0x79, 0x22, 0x00, 0x30,
-       0x01, 0x12, 0x4c, 0x0a, 0x14, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 
0x6f, 0x43, 0x6c, 0x69,
-       0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 
0x68, 0x65, 0x6c, 0x6c,
-       0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 
0x52, 0x65, 0x71, 0x75,
-       0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 
0x6f, 0x72, 0x6c, 0x64,
-       0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 
0x00, 0x28, 0x01, 0x12,
-       0x55, 0x0a, 0x1b, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x42, 
0x69, 0x64, 0x69, 0x72,
-       0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, 0x65, 
0x61, 0x6d, 0x12, 0x18,
+       0x74, 0x22, 0x9c, 0x01, 0x0a, 0x14, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 
0x6c, 0x65, 0x48, 0x65,
+       0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 
0x0a, 0x04, 0x6e, 0x61,
+       0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 
0x6d, 0x65, 0x12, 0x14,
+       0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 
0x09, 0x52, 0x05, 0x69,
+       0x74, 0x65, 0x6d, 0x73, 0x12, 0x2c, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x64, 
0x65, 0x72, 0x73, 0x18,
+       0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 
0x6f, 0x77, 0x6f, 0x72,
+       0x6c, 0x64, 0x2e, 0x47, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x07, 0x67, 
0x65, 0x6e, 0x64, 0x65,
+       0x72, 0x73, 0x12, 0x2c, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 
0x73, 0x18, 0x04, 0x20,
+       0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 
0x6f, 0x72, 0x6c, 0x64,
+       0x2e, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x52, 0x07, 0x70, 0x65, 0x72, 
0x73, 0x6f, 0x6e, 0x73,
+       0x22, 0x72, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 
0x48, 0x65, 0x6c, 0x6c,
+       0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 
0x73, 0x73, 0x61, 0x67,
+       0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 
0x73, 0x61, 0x67, 0x65,
+       0x12, 0x14, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 
0x03, 0x28, 0x09, 0x52,
+       0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x2c, 0x0a, 0x07, 0x67, 0x65, 
0x6e, 0x64, 0x65, 0x72,
+       0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x68, 0x65, 
0x6c, 0x6c, 0x6f, 0x77,
+       0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x47, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 
0x07, 0x67, 0x65, 0x6e,
+       0x64, 0x65, 0x72, 0x73, 0x2a, 0x40, 0x0a, 0x06, 0x47, 0x65, 0x6e, 0x64, 
0x65, 0x72, 0x12, 0x12,
+       0x0a, 0x0e, 0x47, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 
0x4e, 0x4f, 0x57, 0x4e,
+       0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x44, 0x45, 0x52, 
0x5f, 0x4d, 0x41, 0x4c,
+       0x45, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x44, 0x45, 
0x52, 0x5f, 0x46, 0x45,
+       0x4d, 0x41, 0x4c, 0x45, 0x10, 0x02, 0x32, 0x98, 0x04, 0x0a, 0x07, 0x47, 
0x72, 0x65, 0x65, 0x74,
+       0x65, 0x72, 0x12, 0x3e, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 
0x6c, 0x6f, 0x12, 0x18,
        0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 
0x48, 0x65, 0x6c, 0x6c,
        0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 
0x65, 0x6c, 0x6c, 0x6f,
        0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 
0x65, 0x70, 0x6c, 0x79,
-       0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 
0x70, 0x72, 0x6f, 0x74,
-       0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+       0x22, 0x00, 0x12, 0x38, 0x0a, 0x04, 0x50, 0x6c, 0x75, 0x73, 0x12, 0x17, 
0x2e, 0x68, 0x65, 0x6c,
+       0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x50, 0x6c, 0x75, 0x73, 
0x52, 0x65, 0x71, 0x75,
+       0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 
0x6f, 0x72, 0x6c, 0x64,
+       0x2e, 0x50, 0x6c, 0x75, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 
0x12, 0x48, 0x0a, 0x12,
+       0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x41, 0x66, 0x74, 0x65, 
0x72, 0x44, 0x65, 0x6c,
+       0x61, 0x79, 0x12, 0x18, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 
0x72, 0x6c, 0x64, 0x2e,
+       0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 
0x1a, 0x16, 0x2e, 0x68,
+       0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 
0x6c, 0x6c, 0x6f, 0x52,
+       0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x10, 0x53, 0x61, 
0x79, 0x4d, 0x75, 0x6c,
+       0x74, 0x69, 0x70, 0x6c, 0x65, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x20, 
0x2e, 0x68, 0x65, 0x6c,
+       0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 
0x69, 0x70, 0x6c, 0x65,
+       0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 
0x1a, 0x1e, 0x2e, 0x68,
+       0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x4d, 0x75, 
0x6c, 0x74, 0x69, 0x70,
+       0x6c, 0x65, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 
0x22, 0x00, 0x12, 0x4c,
+       0x0a, 0x14, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x53, 0x65, 
0x72, 0x76, 0x65, 0x72,
+       0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x68, 0x65, 0x6c, 
0x6c, 0x6f, 0x77, 0x6f,
+       0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 
0x75, 0x65, 0x73, 0x74,
+       0x1a, 0x16, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 
0x64, 0x2e, 0x48, 0x65,
+       0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 
0x12, 0x4c, 0x0a, 0x14,
+       0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x43, 0x6c, 0x69, 0x65, 
0x6e, 0x74, 0x53, 0x74,
+       0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 
0x77, 0x6f, 0x72, 0x6c,
+       0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 
0x73, 0x74, 0x1a, 0x16,
+       0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 
0x48, 0x65, 0x6c, 0x6c,
+       0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x55, 
0x0a, 0x1b, 0x53, 0x61,
+       0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x42, 0x69, 0x64, 0x69, 0x72, 0x65, 
0x63, 0x74, 0x69, 0x6f,
+       0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 
0x68, 0x65, 0x6c, 0x6c,
+       0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 
0x52, 0x65, 0x71, 0x75,
+       0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 
0x6f, 0x72, 0x6c, 0x64,
+       0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 
0x00, 0x28, 0x01, 0x30,
+       0x01, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 
0x62, 0x06, 0x70, 0x72,
+       0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -452,36 +612,43 @@ func file_proto_helloworld_proto_rawDescGZIP() []byte {
 }
 
 var file_proto_helloworld_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_proto_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
+var file_proto_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
 var file_proto_helloworld_proto_goTypes = []interface{}{
-       (Gender)(0),          // 0: helloworld.Gender
-       (*Person)(nil),       // 1: helloworld.Person
-       (*HelloRequest)(nil), // 2: helloworld.HelloRequest
-       (*HelloReply)(nil),   // 3: helloworld.HelloReply
-       (*PlusRequest)(nil),  // 4: helloworld.PlusRequest
-       (*PlusReply)(nil),    // 5: helloworld.PlusReply
+       (Gender)(0),                  // 0: helloworld.Gender
+       (*Person)(nil),               // 1: helloworld.Person
+       (*HelloRequest)(nil),         // 2: helloworld.HelloRequest
+       (*HelloReply)(nil),           // 3: helloworld.HelloReply
+       (*PlusRequest)(nil),          // 4: helloworld.PlusRequest
+       (*PlusReply)(nil),            // 5: helloworld.PlusReply
+       (*MultipleHelloRequest)(nil), // 6: helloworld.MultipleHelloRequest
+       (*MultipleHelloReply)(nil),   // 7: helloworld.MultipleHelloReply
 }
 var file_proto_helloworld_proto_depIdxs = []int32{
-       0, // 0: helloworld.HelloRequest.gender:type_name -> helloworld.Gender
-       1, // 1: helloworld.HelloRequest.person:type_name -> helloworld.Person
-       0, // 2: helloworld.HelloReply.gender:type_name -> helloworld.Gender
-       2, // 3: helloworld.Greeter.SayHello:input_type -> 
helloworld.HelloRequest
-       4, // 4: helloworld.Greeter.Plus:input_type -> helloworld.PlusRequest
-       2, // 5: helloworld.Greeter.SayHelloAfterDelay:input_type -> 
helloworld.HelloRequest
-       2, // 6: helloworld.Greeter.SayHelloServerStream:input_type -> 
helloworld.HelloRequest
-       2, // 7: helloworld.Greeter.SayHelloClientStream:input_type -> 
helloworld.HelloRequest
-       2, // 8: helloworld.Greeter.SayHelloBidirectionalStream:input_type -> 
helloworld.HelloRequest
-       3, // 9: helloworld.Greeter.SayHello:output_type -> 
helloworld.HelloReply
-       5, // 10: helloworld.Greeter.Plus:output_type -> helloworld.PlusReply
-       3, // 11: helloworld.Greeter.SayHelloAfterDelay:output_type -> 
helloworld.HelloReply
-       3, // 12: helloworld.Greeter.SayHelloServerStream:output_type -> 
helloworld.HelloReply
-       3, // 13: helloworld.Greeter.SayHelloClientStream:output_type -> 
helloworld.HelloReply
-       3, // 14: helloworld.Greeter.SayHelloBidirectionalStream:output_type -> 
helloworld.HelloReply
-       9, // [9:15] is the sub-list for method output_type
-       3, // [3:9] is the sub-list for method input_type
-       3, // [3:3] is the sub-list for extension type_name
-       3, // [3:3] is the sub-list for extension extendee
-       0, // [0:3] is the sub-list for field type_name
+       0,  // 0: helloworld.HelloRequest.gender:type_name -> helloworld.Gender
+       1,  // 1: helloworld.HelloRequest.person:type_name -> helloworld.Person
+       0,  // 2: helloworld.HelloReply.gender:type_name -> helloworld.Gender
+       0,  // 3: helloworld.MultipleHelloRequest.genders:type_name -> 
helloworld.Gender
+       1,  // 4: helloworld.MultipleHelloRequest.persons:type_name -> 
helloworld.Person
+       0,  // 5: helloworld.MultipleHelloReply.genders:type_name -> 
helloworld.Gender
+       2,  // 6: helloworld.Greeter.SayHello:input_type -> 
helloworld.HelloRequest
+       4,  // 7: helloworld.Greeter.Plus:input_type -> helloworld.PlusRequest
+       2,  // 8: helloworld.Greeter.SayHelloAfterDelay:input_type -> 
helloworld.HelloRequest
+       6,  // 9: helloworld.Greeter.SayMultipleHello:input_type -> 
helloworld.MultipleHelloRequest
+       2,  // 10: helloworld.Greeter.SayHelloServerStream:input_type -> 
helloworld.HelloRequest
+       2,  // 11: helloworld.Greeter.SayHelloClientStream:input_type -> 
helloworld.HelloRequest
+       2,  // 12: helloworld.Greeter.SayHelloBidirectionalStream:input_type -> 
helloworld.HelloRequest
+       3,  // 13: helloworld.Greeter.SayHello:output_type -> 
helloworld.HelloReply
+       5,  // 14: helloworld.Greeter.Plus:output_type -> helloworld.PlusReply
+       3,  // 15: helloworld.Greeter.SayHelloAfterDelay:output_type -> 
helloworld.HelloReply
+       7,  // 16: helloworld.Greeter.SayMultipleHello:output_type -> 
helloworld.MultipleHelloReply
+       3,  // 17: helloworld.Greeter.SayHelloServerStream:output_type -> 
helloworld.HelloReply
+       3,  // 18: helloworld.Greeter.SayHelloClientStream:output_type -> 
helloworld.HelloReply
+       3,  // 19: helloworld.Greeter.SayHelloBidirectionalStream:output_type 
-> helloworld.HelloReply
+       13, // [13:20] is the sub-list for method output_type
+       6,  // [6:13] is the sub-list for method input_type
+       6,  // [6:6] is the sub-list for extension type_name
+       6,  // [6:6] is the sub-list for extension extendee
+       0,  // [0:6] is the sub-list for field type_name
 }
 
 func init() { file_proto_helloworld_proto_init() }
@@ -550,6 +717,30 @@ func file_proto_helloworld_proto_init() {
                                return nil
                        }
                }
+               file_proto_helloworld_proto_msgTypes[5].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*MultipleHelloRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_helloworld_proto_msgTypes[6].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*MultipleHelloReply); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
        }
        type x struct{}
        out := protoimpl.TypeBuilder{
@@ -557,7 +748,7 @@ func file_proto_helloworld_proto_init() {
                        GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
                        RawDescriptor: file_proto_helloworld_proto_rawDesc,
                        NumEnums:      1,
-                       NumMessages:   5,
+                       NumMessages:   7,
                        NumExtensions: 0,
                        NumServices:   1,
                },
diff --git a/t/grpc_server_example/proto/helloworld.proto 
b/t/grpc_server_example/proto/helloworld.proto
index 2e18a467c..db056fade 100644
--- a/t/grpc_server_example/proto/helloworld.proto
+++ b/t/grpc_server_example/proto/helloworld.proto
@@ -25,6 +25,7 @@ service Greeter {
   rpc SayHello (HelloRequest) returns (HelloReply) {}
   rpc Plus (PlusRequest) returns (PlusReply) {}
   rpc SayHelloAfterDelay (HelloRequest) returns (HelloReply) {}
+  rpc SayMultipleHello(MultipleHelloRequest) returns (MultipleHelloReply) {}
 
   // Server side streaming.
   rpc SayHelloServerStream (HelloRequest) returns (stream HelloReply) {}
@@ -34,6 +35,7 @@ service Greeter {
 
   // Bidirectional streaming.
   rpc SayHelloBidirectionalStream (stream HelloRequest) returns (stream 
HelloReply) {}
+
 }
 
 enum Gender {
@@ -68,3 +70,16 @@ message PlusRequest {
 message PlusReply {
   int64 result = 1;
 }
+
+message MultipleHelloRequest {
+  string name = 1;
+  repeated string items = 2;
+  repeated Gender genders = 3;
+  repeated Person persons = 4;
+}
+
+message MultipleHelloReply{
+  string message = 1;
+  repeated string items = 2;
+  repeated Gender genders = 3;
+}
diff --git a/t/grpc_server_example/proto/helloworld_grpc.pb.go 
b/t/grpc_server_example/proto/helloworld_grpc.pb.go
index 7d6d8ef8b..c0527d754 100644
--- a/t/grpc_server_example/proto/helloworld_grpc.pb.go
+++ b/t/grpc_server_example/proto/helloworld_grpc.pb.go
@@ -1,4 +1,8 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc             v3.12.4
+// source: proto/helloworld.proto
 
 package proto
 
@@ -22,6 +26,7 @@ type GreeterClient interface {
        SayHello(ctx context.Context, in *HelloRequest, opts 
...grpc.CallOption) (*HelloReply, error)
        Plus(ctx context.Context, in *PlusRequest, opts ...grpc.CallOption) 
(*PlusReply, error)
        SayHelloAfterDelay(ctx context.Context, in *HelloRequest, opts 
...grpc.CallOption) (*HelloReply, error)
+       SayMultipleHello(ctx context.Context, in *MultipleHelloRequest, opts 
...grpc.CallOption) (*MultipleHelloReply, error)
        // Server side streaming.
        SayHelloServerStream(ctx context.Context, in *HelloRequest, opts 
...grpc.CallOption) (Greeter_SayHelloServerStreamClient, error)
        // Client side streaming.
@@ -65,6 +70,15 @@ func (c *greeterClient) SayHelloAfterDelay(ctx 
context.Context, in *HelloRequest
        return out, nil
 }
 
+func (c *greeterClient) SayMultipleHello(ctx context.Context, in 
*MultipleHelloRequest, opts ...grpc.CallOption) (*MultipleHelloReply, error) {
+       out := new(MultipleHelloReply)
+       err := c.cc.Invoke(ctx, "/helloworld.Greeter/SayMultipleHello", in, 
out, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
 func (c *greeterClient) SayHelloServerStream(ctx context.Context, in 
*HelloRequest, opts ...grpc.CallOption) (Greeter_SayHelloServerStreamClient, 
error) {
        stream, err := c.cc.NewStream(ctx, &Greeter_ServiceDesc.Streams[0], 
"/helloworld.Greeter/SayHelloServerStream", opts...)
        if err != nil {
@@ -170,6 +184,7 @@ type GreeterServer interface {
        SayHello(context.Context, *HelloRequest) (*HelloReply, error)
        Plus(context.Context, *PlusRequest) (*PlusReply, error)
        SayHelloAfterDelay(context.Context, *HelloRequest) (*HelloReply, error)
+       SayMultipleHello(context.Context, *MultipleHelloRequest) 
(*MultipleHelloReply, error)
        // Server side streaming.
        SayHelloServerStream(*HelloRequest, Greeter_SayHelloServerStreamServer) 
error
        // Client side streaming.
@@ -192,6 +207,9 @@ func (UnimplementedGreeterServer) Plus(context.Context, 
*PlusRequest) (*PlusRepl
 func (UnimplementedGreeterServer) SayHelloAfterDelay(context.Context, 
*HelloRequest) (*HelloReply, error) {
        return nil, status.Errorf(codes.Unimplemented, "method 
SayHelloAfterDelay not implemented")
 }
+func (UnimplementedGreeterServer) SayMultipleHello(context.Context, 
*MultipleHelloRequest) (*MultipleHelloReply, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method SayMultipleHello 
not implemented")
+}
 func (UnimplementedGreeterServer) SayHelloServerStream(*HelloRequest, 
Greeter_SayHelloServerStreamServer) error {
        return status.Errorf(codes.Unimplemented, "method SayHelloServerStream 
not implemented")
 }
@@ -268,6 +286,24 @@ func _Greeter_SayHelloAfterDelay_Handler(srv interface{}, 
ctx context.Context, d
        return interceptor(ctx, in, info, handler)
 }
 
+func _Greeter_SayMultipleHello_Handler(srv interface{}, ctx context.Context, 
dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) 
(interface{}, error) {
+       in := new(MultipleHelloRequest)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(GreeterServer).SayMultipleHello(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: "/helloworld.Greeter/SayMultipleHello",
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(GreeterServer).SayMultipleHello(ctx, 
req.(*MultipleHelloRequest))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
 func _Greeter_SayHelloServerStream_Handler(srv interface{}, stream 
grpc.ServerStream) error {
        m := new(HelloRequest)
        if err := stream.RecvMsg(m); err != nil {
@@ -360,6 +396,10 @@ var Greeter_ServiceDesc = grpc.ServiceDesc{
                        MethodName: "SayHelloAfterDelay",
                        Handler:    _Greeter_SayHelloAfterDelay_Handler,
                },
+               {
+                       MethodName: "SayMultipleHello",
+                       Handler:    _Greeter_SayMultipleHello_Handler,
+               },
        },
        Streams: []grpc.StreamDesc{
                {
diff --git a/t/grpc_server_example/proto/import.pb.go 
b/t/grpc_server_example/proto/import.pb.go
index 28fabf3f3..a5575fdbd 100644
--- a/t/grpc_server_example/proto/import.pb.go
+++ b/t/grpc_server_example/proto/import.pb.go
@@ -1,7 +1,24 @@
+//
+// 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.
+//
+
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-//     protoc-gen-go v1.27.1
-//     protoc        v3.6.1
+//     protoc-gen-go v1.25.0-devel
+//     protoc        v3.12.4
 // source: proto/import.proto
 
 package proto
diff --git a/t/grpc_server_example/proto/src.pb.go 
b/t/grpc_server_example/proto/src.pb.go
index 8e6a32ae3..74fa884d1 100644
--- a/t/grpc_server_example/proto/src.pb.go
+++ b/t/grpc_server_example/proto/src.pb.go
@@ -1,7 +1,24 @@
+//
+// 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.
+//
+
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-//     protoc-gen-go v1.27.1
-//     protoc        v3.6.1
+//     protoc-gen-go v1.25.0-devel
+//     protoc        v3.12.4
 // source: proto/src.proto
 
 package proto
diff --git a/t/grpc_server_example/proto/src_grpc.pb.go 
b/t/grpc_server_example/proto/src_grpc.pb.go
index 01fe1502d..d4015ed99 100644
--- a/t/grpc_server_example/proto/src_grpc.pb.go
+++ b/t/grpc_server_example/proto/src_grpc.pb.go
@@ -1,4 +1,8 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc             v3.12.4
+// source: proto/src.proto
 
 package proto
 
diff --git a/t/plugin/grpc-transcode3.t b/t/plugin/grpc-transcode3.t
new file mode 100644
index 000000000..a027a84bd
--- /dev/null
+++ b/t/plugin/grpc-transcode3.t
@@ -0,0 +1,124 @@
+#
+# 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 http = require "resty.http"
+          local t = require("lib.test_admin").test
+          local code, body = t('/apisix/admin/proto/1',
+                ngx.HTTP_PUT,
+                [[{
+                   "content" : "syntax = \"proto3\";
+                    package helloworld;
+                    service Greeter {
+                         rpc SayMultipleHello(MultipleHelloRequest) returns 
(MultipleHelloReply) {}
+                     }
+
+                     enum Gender {
+                           GENDER_UNKNOWN = 0;
+                           GENDER_MALE = 1;
+                           GENDER_FEMALE = 2;
+                      }
+
+                       message Person {
+                           string name = 1;
+                           int32 age = 2;
+                       }
+
+                      message MultipleHelloRequest {
+                          string name = 1;
+                          repeated string items = 2;
+                          repeated Gender genders = 3;
+                          repeated Person persons = 4;
+                    }
+
+                    message MultipleHelloReply{
+                          string message = 1;
+                    }"
+                }]]
+              )
+
+             if code >= 300 then
+                 ngx.say(body)
+                 return
+              end
+
+             local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                   "methods": ["POST"],
+                    "uri": "/grpctest",
+                    "plugins": {
+                        "grpc-transcode": {
+                            "proto_id": "1",
+                            "service": "helloworld.Greeter",
+                            "method": "SayMultipleHello"
+                       }
+                    },
+                    "upstream": {
+                        "scheme": "grpc",
+                            "type": "roundrobin",
+                            "nodes": {
+                            "127.0.0.1:50051": 1
+                        }
+                    }
+                }]]
+             )
+
+            if code >= 300 then
+                ngx.say(body)
+                return
+            end
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 2: hit route
+--- request
+POST /grpctest
+{"name":"world","persons":[{"name":"Joe","age":1},{"name":"Jake","age":2}]}
+--- more_headers
+Content-Type: application/json
+--- response_body chomp
+{"message":"Hello world, name: Joe, age: 1, name: Jake, age: 2"}

Reply via email to