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