From aa7741f8b86365f8251ac99472857e16fee8276a Mon Sep 17 00:00:00 2001 From: bytelazy <82265836+bytelazy@users.noreply.github.com> Date: Sat, 4 Oct 2025 17:28:12 +0800 Subject: [PATCH 1/2] test: cover grpc-transcode empty array responses --- apisix/plugins/grpc-transcode/response.lua | 45 +++++++++++++++++++ t/plugin/grpc-transcode.t | 51 ++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/apisix/plugins/grpc-transcode/response.lua b/apisix/plugins/grpc-transcode/response.lua index 9dd6780f049d..2487409a5e96 100644 --- a/apisix/plugins/grpc-transcode/response.lua +++ b/apisix/plugins/grpc-transcode/response.lua @@ -23,6 +23,48 @@ local string = string local ngx_decode_base64 = ngx.decode_base64 local ipairs = ipairs local pcall = pcall +local type = type +local pairs = pairs +local setmetatable = setmetatable + +pb.option "decode_default_array" +-- Protobuf repeated field label value +local PROTOBUF_REPEATED_LABEL = 3 +local repeated_label = PROTOBUF_REPEATED_LABEL + +local function fetch_proto_array_names(proto_obj) + local names = {} + if type(proto_obj) == "table" then + for k,v in pairs(proto_obj) do + if type(v) == "table" then + local sub_names = fetch_proto_array_names(v) + for sub_name,_ in pairs(sub_names) do + names[sub_name] = 1 + end + end + end + if proto_obj["label"] == repeated_label then + if proto_obj["name"] then + names[proto_obj["name"]] = 1 + end + end + end + return names +end + +local function set_default_array(tab, array_names) + if type(tab) ~= "table" then + return + end + for k, v in pairs(tab) do + if type(v) == "table" then + if array_names[k] == 1 then + setmetatable(v, core.json.array_mt) + end + set_default_array(v, array_names) + end + end +end local function handle_error_response(status_detail_type, proto) @@ -132,6 +174,9 @@ return function(ctx, proto, service, method, pb_option, show_status_in_body, sta return err_msg end + local array_names = fetch_proto_array_names(proto) + set_default_array(decoded, array_names) + local response, err = core.json.encode(decoded) if not response then err_msg = "failed to json_encode response body" diff --git a/t/plugin/grpc-transcode.t b/t/plugin/grpc-transcode.t index e261bf7bd554..c7c4d0d71ef6 100644 --- a/t/plugin/grpc-transcode.t +++ b/t/plugin/grpc-transcode.t @@ -761,3 +761,54 @@ POST /grpctest Content-Type: application/json --- response_body eval qr/"gender":2/ + + + +=== TEST 30: set route (return empty array from grpc server) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "methods": ["GET", "POST"], + "uri": "/grpctest", + "plugins": { + "grpc-transcode": { + "proto_id": "1", + "service": "helloworld.Greeter", + "method": "SayHello" + } + }, + "upstream": { + "scheme": "grpc", + "type": "roundrobin", + "nodes": { + "127.0.0.1:10051": 1 + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 31: hit route, response keeps empty array +--- request +POST /grpctest +{"name":"world","items":[]} +--- more_headers +Content-Type: application/json +--- response_body eval +qr/"items":\[\]/ From 6aac6c57a79a528ca2acf59317c966e54169ce50 Mon Sep 17 00:00:00 2001 From: bytelazy <82265836+bytelazy@users.noreply.github.com> Date: Sun, 12 Oct 2025 16:04:14 +0000 Subject: [PATCH 2/2] remove option: decode_default_array --- apisix/plugins/grpc-transcode/response.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/apisix/plugins/grpc-transcode/response.lua b/apisix/plugins/grpc-transcode/response.lua index 2487409a5e96..ae3f7a6ddacf 100644 --- a/apisix/plugins/grpc-transcode/response.lua +++ b/apisix/plugins/grpc-transcode/response.lua @@ -27,7 +27,6 @@ local type = type local pairs = pairs local setmetatable = setmetatable -pb.option "decode_default_array" -- Protobuf repeated field label value local PROTOBUF_REPEATED_LABEL = 3 local repeated_label = PROTOBUF_REPEATED_LABEL