You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/07/29 11:24:35 UTC

[incubator-apisix] branch master updated: bugfix: read the request body from the temporary file if it was cached. (#1863)

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

membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 20207c8  bugfix: read the request body from the temporary file if it was cached. (#1863)
20207c8 is described below

commit 20207c8108b85f8481375315ea324153589276ec
Author: YuanSheng Wang <me...@gmail.com>
AuthorDate: Wed Jul 29 19:24:27 2020 +0800

    bugfix: read the request body from the temporary file if it was cached. (#1863)
---
 apisix/admin/init.lua   |  8 ++++--
 apisix/core/request.lua | 53 ++++++++++++++++++++++++++++++++--
 t/admin/routes.t        | 75 ++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 131 insertions(+), 5 deletions(-)

diff --git a/apisix/admin/init.lua b/apisix/admin/init.lua
index 158ba92..71cb25e 100644
--- a/apisix/admin/init.lua
+++ b/apisix/admin/init.lua
@@ -26,6 +26,7 @@ local require = require
 local reload_event = "/apisix/admin/plugins/reload"
 local ipairs = ipairs
 local events
+local MAX_REQ_BODY = 1024 * 1024 * 1.5      -- 1.5 MiB
 
 
 local viewer_methods = {
@@ -117,8 +118,11 @@ local function run()
         core.response.exit(404)
     end
 
-    ngx.req.read_body()
-    local req_body = ngx.req.get_body_data()
+    local req_body, err = core.request.get_body(MAX_REQ_BODY)
+    if err then
+        core.log.error("failed to read request body: ", err)
+        core.response.exit(400, {error_msg = "invalid request body: " .. err})
+    end
 
     if req_body then
         local data, err = core.json.decode(req_body)
diff --git a/apisix/core/request.lua b/apisix/core/request.lua
index 1148234..7fe8cdd 100644
--- a/apisix/core/request.lua
+++ b/apisix/core/request.lua
@@ -14,14 +14,21 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 --
+
+local lfs = require("lfs")
 local ngx = ngx
 local get_headers = ngx.req.get_headers
 local tonumber = tonumber
 local error    = error
 local type     = type
 local str_fmt  = string.format
+local io_open  = io.open
+local req_read_body = ngx.req.read_body
+local req_get_body_data = ngx.req.get_body_data
+local req_get_body_file = ngx.req.get_body_file
+
 
-local _M = {version = 0.1}
+local _M = {}
 
 
 local function _headers(ctx)
@@ -94,7 +101,49 @@ function _M.get_remote_client_port(ctx)
         ctx = ngx.ctx.api_ctx
     end
     return tonumber(ctx.var.remote_port)
-  end
+end
+
+
+local function get_file(file_name)
+    local f, err = io_open(file_name, 'r')
+    if not f then
+        return nil, err
+    end
+
+    local req_body = f:read("*all")
+    f:close()
+    return req_body
+end
+
+
+function _M.get_body(max_size)
+    req_read_body()
+
+    local req_body = req_get_body_data()
+    if req_body then
+        return req_body
+    end
+
+    local file_name = req_get_body_file()
+    if not file_name then
+        return nil
+    end
+
+    if max_size then
+        local size, err = lfs.attributes (file_name, "size")
+        if not size then
+            return nil, err
+        end
+
+        if size > max_size then
+            return nil, "request size " .. size .. " is greater than the "
+                        .. "maximum size " .. max_size .. " allowed"
+        end
+    end
+
+    local req_body, err = get_file(file_name)
+    return req_body, err
+end
 
 
 return _M
diff --git a/t/admin/routes.t b/t/admin/routes.t
index 0e0d198..1ec272d 100644
--- a/t/admin/routes.t
+++ b/t/admin/routes.t
@@ -1882,6 +1882,79 @@ GET /t
         }
     }
 --- request
-GET /t   
+GET /t
 --- response_headers
 Content-Type: application/json
+
+
+
+=== TEST 52: set route with size 36k (temporary file to store request body)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+
+            local core = require("apisix.core")
+            local s = string.rep("a", 1024 * 35)
+            local req_body = [[{
+                "upstream": {
+                    "nodes": {
+                        "]] .. s .. [[": 1
+                    },
+                    "type": "roundrobin"
+                },
+                "uri": "/index.html"
+            }]]
+
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT, req_body)
+
+            if code >= 300 then
+                ngx.status = code
+            end
+
+            ngx.say("req size: ", #req_body)
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+req size: 36066
+passed
+--- error_log
+a client request body is buffered to a temporary file
+
+
+
+=== TEST 53: route size more than 1.5 MiB
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local s = string.rep( "a", 1024 * 1024 * 1.6 )
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:8080": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "desc": "]] .. s .. [[",
+                    "uri": "/index.html"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.print(body)
+        }
+    }
+--- request
+GET /t
+--- error_code: 400
+--- response_body
+{"error_msg":"invalid request body: request size 1678025 is greater than the maximum size 1572864 allowed"}
+--- error_log
+failed to read request body: request size 1678025 is greater than the maximum size 1572864 allowed