This is an automated email from the ASF dual-hosted git repository.

shreemaan-abhishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 779948893 fix(graphql-proxy-cache): clear all Vary variants on PURGE 
(#13523)
779948893 is described below

commit 779948893dd6cb2a64e8ad005bc4c68364d42a31
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Fri Jun 12 16:45:38 2026 +0800

    fix(graphql-proxy-cache): clear all Vary variants on PURGE (#13523)
---
 apisix/plugins/graphql-proxy-cache.lua        |   6 +-
 apisix/plugins/proxy-cache/memory_handler.lua |   6 ++
 t/plugin/graphql-proxy-cache/memory.t         | 104 ++++++++++++++++++++++++++
 3 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/apisix/plugins/graphql-proxy-cache.lua 
b/apisix/plugins/graphql-proxy-cache.lua
index 2926471ec..3fb38311d 100644
--- a/apisix/plugins/graphql-proxy-cache.lua
+++ b/apisix/plugins/graphql-proxy-cache.lua
@@ -395,8 +395,10 @@ local function purge_hander()
         end
         os.remove(filename)
     else
-        local memory_handler = memory_strategy({shdict_name = conf.cache_zone})
-        memory_handler:purge(ngx_var.upstream_cache_key)
+        local memory = memory_strategy({shdict_name = conf.cache_zone})
+        -- Walk the Vary index and purge every variant, not just the legacy
+        -- base-key entry, so PURGE clears all cached responses for the key.
+        memory_handler.purge_all_variants(memory, ngx_var.upstream_cache_key)
     end
 
     return core.response.exit(200)
diff --git a/apisix/plugins/proxy-cache/memory_handler.lua 
b/apisix/plugins/proxy-cache/memory_handler.lua
index a106d8e09..cba8febef 100644
--- a/apisix/plugins/proxy-cache/memory_handler.lua
+++ b/apisix/plugins/proxy-cache/memory_handler.lua
@@ -571,4 +571,10 @@ function _M.body_filter(conf, ctx)
 end
 
 
+-- Expose the variant-aware purge so callers reusing this strategy (e.g.
+-- graphql-proxy-cache's PURGE handler) can clear the index and every Vary
+-- variant instead of only the legacy base-key entry.
+_M.purge_all_variants = purge_all_variants
+
+
 return _M
diff --git a/t/plugin/graphql-proxy-cache/memory.t 
b/t/plugin/graphql-proxy-cache/memory.t
index 5545cef0c..bdda20f0a 100644
--- a/t/plugin/graphql-proxy-cache/memory.t
+++ b/t/plugin/graphql-proxy-cache/memory.t
@@ -553,3 +553,107 @@ a_1=MISS
 a_2=HIT
 b_1=MISS
 b_2=HIT
+
+
+
+=== TEST 16: PURGE clears every Vary variant, not just the base key
+--- extra_yaml_config
+plugins:
+    - graphql-proxy-cache
+    - public-api
+--- http_config
+    lua_shared_dict memory_cache 50m;
+
+    server {
+        listen 1986;
+        server_tokens off;
+
+        location = /graphql {
+            content_by_lua_block {
+                ngx.header["Vary"] = "X-Variant"
+                ngx.say('{"data":{"variant":"', ngx.var.http_x_variant or 
"none", '"}}')
+            }
+        }
+    }
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local http = require("resty.http")
+
+            local code, res_body = t('/apisix/admin/routes/gql-vary-purge', 
ngx.HTTP_PUT, [[{
+                "uri": "/graphql",
+                "plugins": {
+                    "graphql-proxy-cache": {
+                        "cache_zone": "memory_cache",
+                        "cache_strategy": "memory",
+                        "cache_ttl": 300
+                    }
+                },
+                "upstream": {
+                    "nodes": {"127.0.0.1:1986": 1},
+                    "type": "roundrobin"
+                }
+            }]])
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(res_body)
+                return
+            end
+
+            local code = t('/apisix/admin/routes/graphql-purge', ngx.HTTP_PUT, 
[[{
+                "uri": "/apisix/plugin/graphql-proxy-cache/*",
+                "plugins": {"public-api": {}}
+            }]])
+            if code >= 300 then
+                ngx.status = code
+                ngx.say("failed to set purge route")
+                return
+            end
+
+            local uri = "http://127.0.0.1:"; .. ngx.var.server_port .. 
"/graphql"
+            local body = '{"query":"query{persons{id}}"}'
+
+            local function fetch(variant)
+                local res, err = http.new():request_uri(uri, {
+                    method = "POST",
+                    body = body,
+                    headers = {
+                        ["X-Variant"] = variant,
+                        ["Content-Type"] = "application/json",
+                    },
+                })
+                if not res then
+                    return nil, err
+                end
+                return res.headers["Apisix-Cache-Status"], 
res.headers["APISIX-Cache-Key"]
+            end
+
+            -- Populate two distinct variants under the same base key.
+            local a1 = fetch("a")
+            local _, cache_key = fetch("a")
+            local b1 = fetch("b")
+            local b2 = fetch("b")
+            ngx.say("a_miss=", a1)
+            ngx.say("b_miss=", b1)
+            ngx.say("b_hit=", b2)
+
+            -- PURGE the base key once; the fix must clear both variants.
+            local purge_code = 
t('/apisix/plugin/graphql-proxy-cache/memory/gql-vary-purge/'
+                                 .. cache_key, "PURGE")
+            ngx.say("purge=", purge_code)
+
+            -- Both variants must MISS again now that the index + variants are 
gone.
+            ngx.say("a_after=", (fetch("a")))
+            ngx.say("b_after=", (fetch("b")))
+        }
+    }
+--- request
+GET /t
+--- response_body
+a_miss=MISS
+b_miss=MISS
+b_hit=HIT
+purge=200
+a_after=MISS
+b_after=MISS

Reply via email to