From b356210c8580256543a1e7b10dbf486f690489f0 Mon Sep 17 00:00:00 2001 From: Yusheng Li Date: Mon, 23 Sep 2024 15:09:44 +0800 Subject: [PATCH] fix(plugins/request-validator): fixed an issue where requests get rejected when defining an object parameter with form style and exploded. (#10052) FTI-6179 --- ...lidator-form-style-explode-true-object.yml | 3 ++ .../plugins/request-validator/handler.lua | 19 ++++++-- .../spec/03-access_draft4_spec.lua | 47 +++++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 changelog/unreleased/kong-ee/plugins-request-validator-form-style-explode-true-object.yml diff --git a/changelog/unreleased/kong-ee/plugins-request-validator-form-style-explode-true-object.yml b/changelog/unreleased/kong-ee/plugins-request-validator-form-style-explode-true-object.yml new file mode 100644 index 000000000000..43ea15016869 --- /dev/null +++ b/changelog/unreleased/kong-ee/plugins-request-validator-form-style-explode-true-object.yml @@ -0,0 +1,3 @@ +message: "**Request-validator**: Fixed an issue where requests get rejected when defining an object parameter with form style and exploded." +type: bugfix +scope: Plugin diff --git a/plugins-ee/request-validator/kong/plugins/request-validator/handler.lua b/plugins-ee/request-validator/kong/plugins/request-validator/handler.lua index b1edeeb4c4f2..83fa323abfa3 100644 --- a/plugins-ee/request-validator/kong/plugins/request-validator/handler.lua +++ b/plugins-ee/request-validator/kong/plugins/request-validator/handler.lua @@ -211,8 +211,16 @@ end -- validates the 'required' property of a schema local function validate_required(location, parameter) - if location == "query" and parameter.style == "deepObject" then - return true + if location == "query" then + if parameter.style == "deepObject" then + return true + end + if parameter.style == "form" and parameter.explode == true then + assert(validator_param_cache[parameter]) + if (parameter.decoded_schema or EMPTY).type == "object" then + return true + end + end end local value = template_environment[location][parameter.name] @@ -253,13 +261,18 @@ local validate_data do return validate_style_deepobject(location, parameter) end + local validator = validator_param_cache[parameter] + if location == "query" and parameter.style == "form" and parameter.explode == true and + (parameter.decoded_schema or EMPTY).type == "object" then + parameter.value = template_environment["query"] + end + -- if param is not required and value is nil or serialization -- information not being set, return valid if not parameter.value or parameter.style == ngx_null then return true end - local validator = validator_param_cache[parameter] if type(parameter.value) ~= "table" or tables_allowed[parameter.decoded_schema.type] then -- if the value is a table, then we can only validate it for non-primitives local result, err = deserialize(parameter.style, parameter.decoded_schema.type, diff --git a/plugins-ee/request-validator/spec/03-access_draft4_spec.lua b/plugins-ee/request-validator/spec/03-access_draft4_spec.lua index a1d2ea0ca155..f20a36287fd6 100644 --- a/plugins-ee/request-validator/spec/03-access_draft4_spec.lua +++ b/plugins-ee/request-validator/spec/03-access_draft4_spec.lua @@ -834,6 +834,53 @@ for _, strategy in strategies() do assert.same({ "a", "e"}, body.data) end) end + + it("location: query, style: form, explode: true schema_type: object", function() + local param_schema = { + { + name = "id", + ["in"] = "query", + required = true, + schema = [[ + { + "type": "object", + "required": ["integer", "string"], + "properties": { + "integer": { + "type": "integer" + }, + "string": { + "type": "string" + } + } + }]], + style = "form", + explode = true, + } + } + + add_plugin(admin_client, { parameter_schema = param_schema, verbose_response = true }, 201) + + local res = assert(proxy_client:send { + method = "GET", + path = "/anything?integer=1&string=str", + headers = { + ["Host"] = "path.test", + } + }) + assert.res_status(200, res) + + local res = assert(proxy_client:send { + method = "GET", + path = "/anything?integer=1", + headers = { + ["Host"] = "path.test", + } + }) + assert.res_status(400, res) + local body = assert.response(res).has.jsonbody() + assert.same("query 'id' validation failed, [error] property string is required", body.message) + end) end) end) end