From 8d7f5019f785f3f6ef338ee1afae0527ee493dae Mon Sep 17 00:00:00 2001 From: kurt Date: Tue, 13 Aug 2024 10:13:01 +0800 Subject: [PATCH] fix(degraphql): handle multiple parameter types when converting query parameters (#9911) After the query parameters of the graphql are parsed into AST, there are three types: listType, nonNullType, and namedType. Are their structures different, so the way of obtaining variable types from the structure is also different. This PR is compatible with different structures for obtaining variable types. Fix FTI-6153 --- ...plugins-degraphql-handle-variable-type.yml | 3 ++ kong/plugins/degraphql/handler.lua | 17 ++++++- .../20-degraphql/02-access_spec.lua | 46 +++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 changelog/unreleased/kong-ee/plugins-degraphql-handle-variable-type.yml diff --git a/changelog/unreleased/kong-ee/plugins-degraphql-handle-variable-type.yml b/changelog/unreleased/kong-ee/plugins-degraphql-handle-variable-type.yml new file mode 100644 index 00000000000..d9b0e3c30d8 --- /dev/null +++ b/changelog/unreleased/kong-ee/plugins-degraphql-handle-variable-type.yml @@ -0,0 +1,3 @@ +message: "**degraphql**: Fixed an issue where multiple parameter types were not handled correctly when converting query parameters." +type: bugfix +scope: Plugin diff --git a/kong/plugins/degraphql/handler.lua b/kong/plugins/degraphql/handler.lua index 97143c02e7b..1ea53a7c423 100644 --- a/kong/plugins/degraphql/handler.lua +++ b/kong/plugins/degraphql/handler.lua @@ -17,7 +17,6 @@ local workspaces = require "kong.workspaces" local type = type local ipairs = ipairs -local fmt = string.format local FORCE = true @@ -109,8 +108,22 @@ local function coerce_query_variable(query_str, args) if variable_definition and type(variable_definition) == "table" then for _, variable in ipairs(variable_definition) do + local var_kind = variable.type.kind + local var_type + if var_kind == "listType" or var_kind == "nonNullType" then + var_type = variable.type.type.name.value + end + + if var_kind == "namedType" then + var_type = variable.type.name.value + end + + if not var_type then + kong.log.err("unsupported variable type: ", var_kind) + return + end + local var_name = variable.variable.name.value - local var_type = variable.type.type.name.value local var_value = args[var_name] if var_value then diff --git a/spec-ee/03-plugins/20-degraphql/02-access_spec.lua b/spec-ee/03-plugins/20-degraphql/02-access_spec.lua index 9f958133f03..cc1853c828f 100644 --- a/spec-ee/03-plugins/20-degraphql/02-access_spec.lua +++ b/spec-ee/03-plugins/20-degraphql/02-access_spec.lua @@ -56,6 +56,27 @@ local graphql_mock_query = { } } ]], + + query_with_mixed_param_type = [[ + query($repoCount: [Int], $rating: Float!, $isActive: Boolean) { + user { + id + name + isActive @include(if: $isActive) + repositories(last: $repoCount) { + nodes { + id + name + languages: stars(rating: $rating) + } + } + friends: following { + name + isActive + } + } + } + ]], } for _, strategy in helpers.each_strategy() do @@ -122,6 +143,12 @@ for _, strategy in helpers.each_strategy() do query = graphql_mock_query.fetch_recent_repos, }) + assert(db.degraphql_routes:insert { + service = { id = service.id }, + uri = "/query_with_mixed_param_type", + query = graphql_mock_query.query_with_mixed_param_type, + }) + helpers.start_kong({ database = strategy, plugins = "bundled,degraphql", @@ -197,6 +224,25 @@ for _, strategy in helpers.each_strategy() do assert.response(res).has.status(200) local json = assert.response(res).has.jsonbody() assert.same(ori_graph_query, json.data.variables) + + local ori_graph_query_with_mixed_param_type = { + repoCount = 3, -- A signed 32‐bit integer + rating = 4.5, -- A signed double-precision floating-point value. + isActive = true, -- true or false. + } + + local res = assert(proxy_client:send { + method = "GET", + path = "/query_with_mixed_param_type", + query = ori_graph_query_with_mixed_param_type, + headers = { + ["Host"] = "graphql.test" + } + }) + + assert.response(res).has.status(200) + local json = assert.response(res).has.jsonbody() + assert.same(ori_graph_query_with_mixed_param_type, json.data.variables) end) it("can update graphql router when creating new graphql_route entity", function ()