Skip to content
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
44 changes: 37 additions & 7 deletions apisix/core/request_json.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ local config_local = require("apisix.core.config_local")
local core_json = require("apisix.core.json")
local qjson = require("qjson")
local simdjson = require("resty.simdjson")
local pcall = pcall
local tostring = tostring


local simdjson_parser, simdjson_err = simdjson.new()
Expand All @@ -28,6 +30,39 @@ local configured_name
local _M = {}


local function qjson_decode(str)
local ok, decoded, err = pcall(qjson.decode, str)
if not ok then
return nil, tostring(decoded)
end

if decoded == nil then
return nil, err
end

ok, decoded, err = pcall(qjson.materialize, decoded)
if not ok then
return nil, tostring(decoded)
end

if decoded == nil then
return nil, err
end

return decoded
end


local function qjson_encode(data)
local ok, encoded, err = pcall(qjson.encode, data)
if not ok then
return nil, tostring(encoded)
end

return encoded, err
end


function _M.decode(str)
if not configured_name then
configured_name = config_local.local_conf().apisix.request_body_json_lib
Expand All @@ -42,12 +77,7 @@ function _M.decode(str)
return simdjson_parser:decode(str)
end

local decoded, err = qjson.decode(str)
if not decoded then
return nil, err
end

return qjson.materialize(decoded)
return qjson_decode(str)
end


Expand All @@ -57,7 +87,7 @@ function _M.encode(data)
end

if configured_name == "qjson" then
return qjson.encode(data)
return qjson_encode(data)
end

-- simdjson encode is slower than cjson, so simdjson mode only uses it for decode.
Expand Down
47 changes: 45 additions & 2 deletions t/core/request.t
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,50 @@ cjson encode: {"lib":"body"}



=== TEST 19: simdjson preserves empty arrays for cjson encoding
=== TEST 19: qjson decode and encode errors are returned
--- yaml_config
apisix:
request_body_json_lib: qjson
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local request_json = require("apisix.core.request_json")

ngx.ctx.api_ctx = {}

local body, body_err = core.request.get_json_request_body_table()
ngx.say("body nil: ", body == nil)
ngx.say("body error: ", body_err and body_err.message and
body_err.message:find("could not parse JSON request body:", 1, true) == 1)

local decoded, decode_err = request_json.decode("{")
ngx.say("decode nil: ", decoded == nil)
ngx.say("decode error: ", type(decode_err) == "string" and #decode_err > 0)

local encoded, encode_err = request_json.encode({bad = function() end})
ngx.say("encode nil: ", encoded == nil)
ngx.say("encode error: ", type(encode_err) == "string" and #encode_err > 0)
}
}
--- request
POST /t
{
--- more_headers
Content-Type: application/json
--- response_body
body nil: true
body error: true
decode nil: true
decode error: true
encode nil: true
encode error: true
--- no_error_log
[error]



=== TEST 20: simdjson preserves empty arrays for cjson encoding
--- yaml_config
apisix:
request_body_json_lib: simdjson
Expand All @@ -653,7 +696,7 @@ tags array: true



=== TEST 20: ai transport encoders use request_json
=== TEST 21: ai transport encoders use request_json
--- config
location /t {
content_by_lua_block {
Expand Down
Loading