From a8740bf0ee31d8baeca4b9bcb4c410e0c6cefac2 Mon Sep 17 00:00:00 2001 From: ms2008 Date: Thu, 28 Dec 2023 23:04:58 +0800 Subject: [PATCH] feat(cjson): ensure `cjson.new` encode number with a precision of 16 decimals --- kong/db/strategies/postgres/init.lua | 2 - kong/globalpatches.lua | 21 +++++++ kong/pdk/response.lua | 1 - kong/plugins/zipkin/reporter.lua | 1 - .../05-proxy/34-max_safe_integer_spec.lua | 60 +++++++++++++++++++ t/01-pdk/08-response/11-exit.t | 1 + 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 spec/02-integration/05-proxy/34-max_safe_integer_spec.lua diff --git a/kong/db/strategies/postgres/init.lua b/kong/db/strategies/postgres/init.lua index e76af557e293..8f8c70ff12bc 100644 --- a/kong/db/strategies/postgres/init.lua +++ b/kong/db/strategies/postgres/init.lua @@ -6,8 +6,6 @@ local utils = require "kong.tools.utils" local new_tab = require "table.new" local clear_tab = require "table.clear" -cjson.encode_number_precision(16) -cjson_safe.encode_number_precision(16) local kong = kong local ngx = ngx diff --git a/kong/globalpatches.lua b/kong/globalpatches.lua index c3782f0c8a0f..876c8234603f 100644 --- a/kong/globalpatches.lua +++ b/kong/globalpatches.lua @@ -14,6 +14,27 @@ return function(options) options = options or {} local meta = require "kong.meta" + do -- make cjson encode numbers with a precision of up to 16 decimals + local cjson = require "cjson" + local cjson_safe = require "cjson.safe" + local native_cjson_new = cjson.new + local native_cjson_safe_new = cjson_safe.new + + cjson.encode_number_precision(16) + cjson_safe.encode_number_precision(16) + + cjson.new = function() + local json = native_cjson_new() + json.encode_number_precision(16) + return json + end + + cjson_safe.new = function() + local json = native_cjson_safe_new() + json.encode_number_precision(16) + return json + end + end local cjson = require("cjson.safe") cjson.encode_sparse_array(nil, nil, 2^15) diff --git a/kong/pdk/response.lua b/kong/pdk/response.lua index e196067cd311..37a0c67d11f4 100644 --- a/kong/pdk/response.lua +++ b/kong/pdk/response.lua @@ -20,7 +20,6 @@ local utils = require "kong.tools.utils" local request_id = require "kong.tracing.request_id" local constants = require "kong.constants" -cjson.encode_number_precision(16) local ngx = ngx local arg = ngx.arg diff --git a/kong/plugins/zipkin/reporter.lua b/kong/plugins/zipkin/reporter.lua index 73c1111a81de..d01c3d605bc6 100644 --- a/kong/plugins/zipkin/reporter.lua +++ b/kong/plugins/zipkin/reporter.lua @@ -3,7 +3,6 @@ local to_hex = require "resty.string".to_hex local cjson = require "cjson".new() local Queue = require "kong.tools.queue" -cjson.encode_number_precision(16) local zipkin_reporter_methods = {} local zipkin_reporter_mt = { diff --git a/spec/02-integration/05-proxy/34-max_safe_integer_spec.lua b/spec/02-integration/05-proxy/34-max_safe_integer_spec.lua new file mode 100644 index 000000000000..ed216c8bfc5b --- /dev/null +++ b/spec/02-integration/05-proxy/34-max_safe_integer_spec.lua @@ -0,0 +1,60 @@ +local helpers = require "spec.helpers" + +for _, strategy in helpers.each_strategy() do + describe("cjson.new encode number with a precision of 16 decimals [#" .. strategy .. "]", function() + local proxy_client + + lazy_setup(function() + local bp = helpers.get_db_utils(strategy, { + "routes", + "services", + "plugins", + }, { "pre-function" }) + + local route = bp.routes:insert({ + paths = { "/route_with_max_safe_integer_priority"}, + }) + + bp.plugins:insert { + route = { id = route.id }, + name = "pre-function", + config = { + access = { + [[ + local cjson = require("cjson").new() + ngx.say(cjson.encode({ n = 9007199254740992 })) + ]] + }, + } + } + + assert(helpers.start_kong({ + database = strategy, + untrusted_lua = "on", + plugins = "bundled", + nginx_conf = "spec/fixtures/custom_nginx.template", + nginx_worker_processes = 1 + })) + + proxy_client = helpers.proxy_client() + end) + + lazy_teardown(function() + if proxy_client then + proxy_client:close() + end + + helpers.stop_kong() + end) + + it("the maximum safe integer can be accurately represented as a decimal number", function() + local res = assert(proxy_client:send { + method = "GET", + path = "/route_with_max_safe_integer_priority" + }) + + assert.res_status(200, res) + assert.match_re(res:read_body(), "9007199254740992") + end) + end) +end diff --git a/t/01-pdk/08-response/11-exit.t b/t/01-pdk/08-response/11-exit.t index 8048b91cdbe7..4a6f7a624c92 100644 --- a/t/01-pdk/08-response/11-exit.t +++ b/t/01-pdk/08-response/11-exit.t @@ -1162,6 +1162,7 @@ manually setting Transfer-Encoding. Ignored. location = /t { default_type 'text/test'; access_by_lua_block { + require("kong.globalpatches")() local PDK = require "kong.pdk" local pdk = PDK.new()