From 5cab556adc6b0c74c11b83baeb2b81010881e8dc Mon Sep 17 00:00:00 2001 From: Yufu Zhao Date: Thu, 31 Oct 2024 14:38:58 +0800 Subject: [PATCH] fix(admin-api): nested parameters can be parsed correctly when using form-urlencoded requests (#13668) When using curl to send a form-urlencoded request with nested parameters, such as $ curl -X POST http://localhost:8001/parsed_params \ --data 'items[1]=foo' \ --data 'items[2]=bar' the expected response is {"items":["foo","bar"]}, but instead, it returns {"items":{}}. This is actually an EE issue, but I see that there is a risk of this in CE even though it doesn't currently occur. So I initiated that fix on CE. The cause of the problem is due to the fact that nested parameters are lost when the decode_args method is called twice, without this fix. FTI-6165 --- .../kong/fix-parse-nested-parameters.yml | 3 +++ kong/tools/http.lua | 4 +++- .../04-admin_api/13-plugin-endpoints_spec.lua | 16 +++++++++++++++- .../kong/plugins/admin-api-method/api.lua | 10 ++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 changelog/unreleased/kong/fix-parse-nested-parameters.yml diff --git a/changelog/unreleased/kong/fix-parse-nested-parameters.yml b/changelog/unreleased/kong/fix-parse-nested-parameters.yml new file mode 100644 index 000000000000..e1cdd3fd21e9 --- /dev/null +++ b/changelog/unreleased/kong/fix-parse-nested-parameters.yml @@ -0,0 +1,3 @@ +message: Fixed an issue where nested parameters can not be parsed correctly when using form-urlencoded requests. +type: bugfix +scope: Admin API diff --git a/kong/tools/http.lua b/kong/tools/http.lua index 58e5bb908b5e..344c2a6f3f21 100644 --- a/kong/tools/http.lua +++ b/kong/tools/http.lua @@ -141,6 +141,8 @@ do end + -- { ["1"] = "a", ["2"] = "b" } becomes {"a", "b"} + -- { "a", "b" } becomes { "a", "b" } local function decode_array(t) local keys = {} local len = 0 @@ -160,7 +162,7 @@ do if keys[i] ~= i then return nil end - new_t[i] = t[tostring(i)] + new_t[i] = t[tostring(i)] or t[i] end return new_t diff --git a/spec/02-integration/04-admin_api/13-plugin-endpoints_spec.lua b/spec/02-integration/04-admin_api/13-plugin-endpoints_spec.lua index 24a4c7af8dd1..bdd637ffde4c 100644 --- a/spec/02-integration/04-admin_api/13-plugin-endpoints_spec.lua +++ b/spec/02-integration/04-admin_api/13-plugin-endpoints_spec.lua @@ -38,9 +38,23 @@ describe("Admin API endpoints added via plugins #" .. strategy, function() path = "/method_without_exit", headers = { ["Content-Type"] = "application/json" } }) - local body = assert.res_status(201 , res) + local body = assert.res_status(201, res) assert.same("hello", body) end) + + it("nested parameters can be parsed correctly when using form-urlencoded requests", function() + local res = assert(client:send{ + method = "POST", + path = "/parsed_params", + body = ngx.encode_args{ + ["items[1]"] = "foo", + ["items[2]"] = "bar", + }, + headers = { ["Content-Type"] = "application/x-www-form-urlencoded" } + }) + local body = assert.res_status(200, res) + assert.same('{"items":["foo","bar"]}', body) + end) end) end diff --git a/spec/fixtures/custom_plugins/kong/plugins/admin-api-method/api.lua b/spec/fixtures/custom_plugins/kong/plugins/admin-api-method/api.lua index 73c42b11cf9c..cec0e17eb297 100644 --- a/spec/fixtures/custom_plugins/kong/plugins/admin-api-method/api.lua +++ b/spec/fixtures/custom_plugins/kong/plugins/admin-api-method/api.lua @@ -6,4 +6,14 @@ return { ngx.print("hello") end, }, + ["/parsed_params"] = { + -- The purpose of the dummy filter is to let `parse_params` + -- of api/api_helpers.lua to be called twice. + before = function(self, db, helpers, parent) + end, + + POST = function(self, db, helpers, parent) + kong.response.exit(200, self.params) + end, + }, }