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 2021/10/08 03:34:12 UTC

[apisix] branch master updated: refactor: introduce hold_body_chunk to dismiss repeated code (#5167)

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 178d18a  refactor: introduce hold_body_chunk to dismiss repeated code (#5167)
178d18a is described below

commit 178d18aa3550c6d536f2fbd4cbaa560ee4753c76
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Fri Oct 8 11:34:07 2021 +0800

    refactor: introduce hold_body_chunk to dismiss repeated code (#5167)
---
 apisix/core/response.lua                   | 47 +++++++++++++++++++++++
 apisix/plugins/grpc-transcode.lua          |  2 +-
 apisix/plugins/grpc-transcode/response.lua | 60 ++++++++++++------------------
 3 files changed, 72 insertions(+), 37 deletions(-)

diff --git a/apisix/core/response.lua b/apisix/core/response.lua
index 92cd069..7b1128d 100644
--- a/apisix/core/response.lua
+++ b/apisix/core/response.lua
@@ -16,6 +16,7 @@
 --
 local encode_json = require("cjson.safe").encode
 local ngx = ngx
+local arg = ngx.arg
 local ngx_print = ngx.print
 local ngx_header = ngx.header
 local ngx_add_header
@@ -151,4 +152,50 @@ function _M.clear_header_as_body_modified()
 end
 
 
+-- Hold body chunks and return the final body once all chunks have been read.
+-- Usage:
+-- function _M.body_filter(conf, ctx)
+--  local final_body = core.response.hold_body_chunk(ctx)
+--  if not final_body then
+--      return
+--  end
+--  final_body = transform(final_body)
+--  ngx.arg[1] = final_body
+--  ...
+--
+-- Inspired by kong.response.get_raw_body()
+function _M.hold_body_chunk(ctx)
+    local body_buffer
+    local chunk, eof = arg[1], arg[2]
+    if eof then
+        body_buffer = ctx._body_buffer
+        if not body_buffer then
+            return chunk
+        end
+
+        body_buffer = concat_tab(body_buffer, "", 1, body_buffer.n)
+        ctx._body_buffer = nil
+        return body_buffer
+    end
+
+    if type(chunk) == "string" and chunk ~= "" then
+        body_buffer = ctx._body_buffer
+        if not body_buffer then
+            body_buffer = {
+                chunk,
+                n = 1
+            }
+            ctx._body_buffer = body_buffer
+        else
+            local n = body_buffer.n + 1
+            body_buffer.n = n
+            body_buffer[n] = chunk
+        end
+    end
+
+    arg[1] = nil
+    return nil
+end
+
+
 return _M
diff --git a/apisix/plugins/grpc-transcode.lua b/apisix/plugins/grpc-transcode.lua
index b9ed7ab..2f396df 100644
--- a/apisix/plugins/grpc-transcode.lua
+++ b/apisix/plugins/grpc-transcode.lua
@@ -163,7 +163,7 @@ function _M.body_filter(conf, ctx)
         return
     end
 
-    local err = response(proto_obj, conf.service, conf.method, conf.pb_option)
+    local err = response(ctx, proto_obj, conf.service, conf.method, conf.pb_option)
     if err then
         core.log.error("transform response error: ", err)
         return
diff --git a/apisix/plugins/grpc-transcode/response.lua b/apisix/plugins/grpc-transcode/response.lua
index b2ce1dc..e342b9a 100644
--- a/apisix/plugins/grpc-transcode/response.lua
+++ b/apisix/plugins/grpc-transcode/response.lua
@@ -19,55 +19,43 @@ local core   = require("apisix.core")
 local pb     = require("pb")
 local ngx    = ngx
 local string = string
-local table  = table
 local ipairs = ipairs
 
-return function(proto, service, method, pb_option)
+return function(ctx, proto, service, method, pb_option)
+    local buffer = core.response.hold_body_chunk(ctx)
+    if not buffer then
+        return nil
+    end
+
     local m = util.find_method(proto, service, method)
     if not m then
         return false, "2.Undefined service method: " .. service .. "/" .. method
                       .. " end."
     end
 
-    local chunk, eof = ngx.arg[1], ngx.arg[2]
-    local buffered = ngx.ctx.buffered
-    if not buffered then
-        buffered = {}
-        ngx.ctx.buffered = buffered
-    end
-
-    if chunk ~= "" then
-        core.table.insert(buffered, chunk)
-        ngx.arg[1] = nil
+    if not ngx.req.get_headers()["X-Grpc-Web"] then
+        buffer = string.sub(buffer, 6)
     end
 
-
-    if eof then
-        ngx.ctx.buffered = nil
-        local buffer = table.concat(buffered)
-        if not ngx.req.get_headers()["X-Grpc-Web"] then
-            buffer = string.sub(buffer, 6)
-        end
-
-        if pb_option then
-            for _, opt in ipairs(pb_option) do
-                pb.option(opt)
-            end
-        end
-
-        local decoded = pb.decode(m.output_type, buffer)
-        if not decoded then
-            ngx.arg[1] = "failed to decode response data by protobuf"
-            return "failed to decode response data by protobuf"
+    if pb_option then
+        for _, opt in ipairs(pb_option) do
+            pb.option(opt)
         end
+    end
 
-        local response, err = core.json.encode(decoded)
-        if not response then
-            core.log.error("failed to call json_encode data: ", err)
-            response = "failed to json_encode response body"
-        end
+    local decoded = pb.decode(m.output_type, buffer)
+    if not decoded then
+        ngx.arg[1] = "failed to decode response data by protobuf"
+        return "failed to decode response data by protobuf"
+    end
 
-        ngx.arg[1] = response
+    local response, err = core.json.encode(decoded)
+    if not response then
+        core.log.error("failed to call json_encode data: ", err)
+        response = "failed to json_encode response body"
+        return response
     end
 
+    ngx.arg[1] = response
+    return nil
 end