Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: read the request body from the temporary file if it was cached. #1863

Merged
merged 7 commits into from
Jul 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions apisix/admin/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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)
Expand Down
53 changes: 51 additions & 2 deletions apisix/core/request.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
75 changes: 74 additions & 1 deletion t/admin/routes.t
Original file line number Diff line number Diff line change
Expand Up @@ -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