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

guoqqqi 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 f416c4332 fix(router): respect explicit URI overrides during servlet 
normalization (#14163)
f416c4332 is described below

commit f416c4332d55beaabb0cb67ab4d1444101622e49
Author: ruanweihong-aaa <[email protected]>
AuthorDate: Mon Nov 9 18:16:42 2026 +0800

    fix(router): respect explicit URI overrides during servlet normalization 
(#14163)
---
 apisix/core/ctx.lua                      |   6 +
 apisix/init.lua                          |  23 ++-
 apisix/plugins/data-mask.lua             |  26 ++-
 apisix/plugins/proxy-mirror.lua          |  11 +-
 t/plugin/data-mask.t                     | 105 ++++++++++++
 t/router/servlet-upstream-uri-override.t | 281 +++++++++++++++++++++++++++++++
 t/router/servlet-upstream-uri.t          | 216 +++++++++++++++++++++++-
 7 files changed, 656 insertions(+), 12 deletions(-)

diff --git a/apisix/core/ctx.lua b/apisix/core/ctx.lua
index 12cdadc7d..06d4d0b26 100644
--- a/apisix/core/ctx.lua
+++ b/apisix/core/ctx.lua
@@ -401,6 +401,12 @@ do
                 ngx_var[key] = val
             end
 
+            -- A same-path assignment can intentionally remove the query 
string.
+            -- Track writes rather than comparing the resulting URI with its 
seed.
+            if key == "upstream_uri" and t._ctx and 
t._ctx.servlet_upstream_uri then
+                t._ctx.servlet_upstream_uri_overridden = true
+            end
+
             -- log.info("key: ", key, " new val: ", val)
             t._cache[key] = val
         end,
diff --git a/apisix/init.lua b/apisix/init.lua
index adf21a3cd..451a95108 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -627,13 +627,14 @@ end
 -- Forward the original path so servlet upstreams can consume params after ';'.
 -- URI-encode it before proxying to keep delimiters as path data.
 --
--- Setting $upstream_uri at all turns off the "empty proxy_pass URI" 
passthrough
--- that otherwise hands the client's request line -- query string included -- 
to
--- the upstream unchanged, so the query string has to be re-appended here.
+-- We set api_ctx.var.upstream_uri early so early plugins (like ext-plugin,
+-- graphql-limit-count) observe the servlet path parameters.
+-- Query arguments are appended after rewrite and access plugin phases 
complete.
 local function set_servlet_upstream_uri(api_ctx, uri)
-    api_ctx.var.upstream_uri = core.utils.uri_safe_encode(uri)
-                               .. (api_ctx.var.is_args or "")
-                               .. (api_ctx.var.args or "")
+    local servlet_uri = core.utils.uri_safe_encode(uri)
+    api_ctx.var.upstream_uri = servlet_uri
+    api_ctx.servlet_upstream_uri = servlet_uri
+    api_ctx.servlet_upstream_uri_overridden = false
 end
 
 
@@ -1106,6 +1107,16 @@ function _M.http_access_phase()
     end
     span:finish(ngx_ctx)
 
+    if api_ctx.servlet_upstream_uri then
+        if (not api_ctx.servlet_upstream_uri_overridden and
+            api_ctx.var.upstream_uri == api_ctx.servlet_upstream_uri) or
+           not api_ctx.var.upstream_uri or api_ctx.var.upstream_uri == "" then
+            api_ctx.var.upstream_uri = api_ctx.servlet_upstream_uri
+                                       .. (api_ctx.var.is_args or "")
+                                       .. (api_ctx.var.args or "")
+        end
+    end
+
     _M.handle_upstream(api_ctx, route, enable_websocket)
 end
 
diff --git a/apisix/plugins/data-mask.lua b/apisix/plugins/data-mask.lua
index 3f49fee98..fad35ca13 100644
--- a/apisix/plugins/data-mask.lua
+++ b/apisix/plugins/data-mask.lua
@@ -22,6 +22,8 @@ local t_remove  = table.remove
 local re_sub    = ngx.re.sub
 local str_lower = string.lower
 local str_gsub  = string.gsub
+local str_find  = string.find
+local str_sub   = string.sub
 local core      = require("apisix.core")
 local jp        = require("jsonpath")
 
@@ -232,12 +234,27 @@ function _M.log(conf, ctx)
     local body_masked = false
     local masked_headers
 
+    local upstream_args
+    local upstream_path
+    if ctx.var.upstream_uri and ctx.var.upstream_uri ~= "" then
+        local idx = str_find(ctx.var.upstream_uri, "?", 1, true)
+        if idx then
+            upstream_path = str_sub(ctx.var.upstream_uri, 1, idx - 1)
+            local raw_query = str_sub(ctx.var.upstream_uri, idx + 1)
+            upstream_args = core.string.decode_args(raw_query)
+        end
+    end
+    local upstream_query_masked = false
+
     if conf.request then
         for _, item in ipairs(conf.request) do
             if item.type == "query" then
                 if mask_table(args, item) then
                     query_masked = true
                 end
+                if upstream_args and mask_table(upstream_args, item) then
+                    upstream_query_masked = true
+                end
             end
 
             if item.type == "header" then
@@ -327,7 +344,14 @@ function _M.log(conf, ctx)
         -- for access log
         ctx.var.request_line = core.request.get_method() .. " " .. 
ctx.var.request_uri
                                     .. " HTTP/" .. 
core.request.get_http_version()
-        -- TODO: handle upstream_uri in access log when enable proxy-rewrite
+    end
+
+    if upstream_query_masked then
+        if next(upstream_args) then
+            ctx.var.upstream_uri = upstream_path .. "?" .. 
core.string.encode_args(upstream_args)
+        else
+            ctx.var.upstream_uri = upstream_path
+        end
     end
 
     if post_args_masked then
diff --git a/apisix/plugins/proxy-mirror.lua b/apisix/plugins/proxy-mirror.lua
index 8ffb534ec..a5e0d1fe4 100644
--- a/apisix/plugins/proxy-mirror.lua
+++ b/apisix/plugins/proxy-mirror.lua
@@ -91,8 +91,15 @@ end
 
 local function enable_mirror(ctx, conf)
     local uri = (ctx.var.upstream_uri and ctx.var.upstream_uri ~= "") and
-                ctx.var.upstream_uri or
-                ctx.var.uri .. ctx.var.is_args .. (ctx.var.args or '')
+                (ctx.servlet_upstream_uri and not 
ctx.servlet_upstream_uri_overridden and
+                    ctx.var.upstream_uri == ctx.servlet_upstream_uri and
+                    (ctx.servlet_upstream_uri .. (ctx.var.is_args or "")
+                     .. (ctx.var.args or "")) or
+                    ctx.var.upstream_uri) or
+                (ctx.servlet_upstream_uri and
+                    (ctx.servlet_upstream_uri .. (ctx.var.is_args or "")
+                     .. (ctx.var.args or "")) or
+                    (ctx.var.uri .. ctx.var.is_args .. (ctx.var.args or "")))
 
     if conf.path then
         if conf.path_concat_mode == "prefix" then
diff --git a/t/plugin/data-mask.t b/t/plugin/data-mask.t
index 21d471015..65a33a198 100644
--- a/t/plugin/data-mask.t
+++ b/t/plugin/data-mask.t
@@ -1489,3 +1489,108 @@ success
     }
 --- response_body
 success
+
+
+
+=== TEST 35: data-mask with proxy-rewrite preserves unrelated upstream 
parameters and repeated values in upstream_uri
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/1',
+                 ngx.HTTP_PUT,
+                 [[{
+                        "plugins": {
+                            "proxy-rewrite": {
+                                "uri": "/echo?fixed=1"
+                            },
+                            "data-mask": {
+                                "request": [
+                                    {
+                                        "action": "remove",
+                                        "name": "password",
+                                        "type": "query"
+                                    }
+                                ]
+                            },
+                            "file-logger": {
+                                "path": "mask-proxy-rewrite-upstream.log",
+                                "log_format": {
+                                    "upstream_uri": "$upstream_uri"
+                                }
+                            }
+                        },
+                        "upstream": {
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            },
+                            "type": "roundrobin"
+                        },
+                        "uri": "/hello"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+
+
+
+=== TEST 36: verify upstream_uri preserves unrelated upstream parameters and 
repeated values
+--- config
+    location /t {
+        content_by_lua_block {
+            local core = require("apisix.core")
+            local t = require("lib.test_admin").test
+
+            t("/hello?password=secret&foo=1&tag=a&tag=b", ngx.HTTP_GET)
+            ngx.sleep(0.5)
+
+            local fd, err = io.open("mask-proxy-rewrite-upstream.log", "r")
+            if not fd then
+                core.log.error("failed to open file: ", err)
+                return
+            end
+            local line = fd:read()
+            fd:close()
+            os.remove("mask-proxy-rewrite-upstream.log")
+
+            local log = core.json.decode(line)
+            local idx = string.find(log.upstream_uri, "?", 1, true)
+            if not idx then
+                ngx.say("missing query in upstream_uri: ", log.upstream_uri)
+                return
+            end
+
+            local path = string.sub(log.upstream_uri, 1, idx - 1)
+            if path ~= "/echo" then
+                ngx.say("unexpected path in upstream_uri: ", path)
+                return
+            end
+
+            local args = core.string.decode_args(string.sub(log.upstream_uri, 
idx + 1))
+            if args.password then
+                ngx.say("password was not masked in upstream_uri: ", 
log.upstream_uri)
+                return
+            end
+            if args.fixed ~= "1" then
+                ngx.say("fixed param missing in upstream_uri: ", 
log.upstream_uri)
+                return
+            end
+            if args.foo ~= "1" then
+                ngx.say("foo param missing in upstream_uri: ", 
log.upstream_uri)
+                return
+            end
+            if type(args.tag) ~= "table" or args.tag[1] ~= "a" or args.tag[2] 
~= "b" then
+                ngx.say("repeated tag param missing or corrupt in 
upstream_uri: ", log.upstream_uri)
+                return
+            end
+
+            ngx.say("success")
+        }
+    }
+--- response_body
+success
diff --git a/t/router/servlet-upstream-uri-override.t 
b/t/router/servlet-upstream-uri-override.t
new file mode 100644
index 000000000..3f74c464f
--- /dev/null
+++ b/t/router/servlet-upstream-uri-override.t
@@ -0,0 +1,281 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+
+repeat_each(1);
+no_shuffle();
+no_root_location();
+log_level('info');
+
+add_block_preprocessor(sub {
+    my ($block) = @_;
+    $block->set_value("yaml_config", <<'_EOC_');
+apisix:
+    node_listen: 1984
+    normalize_uri_like_servlet: true
+_EOC_
+    $block->set_value("upstream_server_config", <<'_EOC_');
+    location ~ ^/(anything|other) {
+        content_by_lua_block {
+            ngx.say(ngx.var.request_uri)
+        }
+    }
+_EOC_
+    $block->set_value("http_config", <<'_EOC_');
+    server {
+        listen 1987;
+        location / {
+            content_by_lua_block {
+                ngx.log(ngx.WARN, "mirror-uri[", ngx.var.request_uri, "]")
+                ngx.say("mirrored")
+            }
+        }
+    }
+_EOC_
+});
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: configure URI overrides and query-only changes
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local function rewrite(uri, priority)
+                return {
+                    use_real_request_uri_unsafe = true,
+                    regex_uri = {"^.*$", uri},
+                    _meta = {priority = priority or 1100},
+                }
+            end
+            local function access(code)
+                return {
+                    phase = "access",
+                    functions = {"return function(conf, ctx) " .. code .. " 
end"},
+                }
+            end
+            local mirror = {host = "http://127.0.0.1:1987";, sample_ratio = 1}
+            local path = "/anything;jsessionid=x"
+            local cases = {
+                same = {["proxy-rewrite"] = rewrite(path)},
+                different = {["proxy-rewrite"] = rewrite("/other?fixed=2")},
+                mirror = {["proxy-rewrite"] = rewrite(path), ["proxy-mirror"] 
= mirror},
+                default_order = {
+                    ["proxy-rewrite"] = rewrite(path, 1008), ["proxy-mirror"] 
= mirror,
+                },
+                args = {["serverless-post-function"] = access(
+                    "require('apisix.core').request.set_uri_args(ctx, 
'foo=2')")},
+                override = {["serverless-post-function"] = access(
+                    "ctx.var.upstream_uri = '/anything;jsessionid=x'")},
+                later_args = {
+                    ["proxy-rewrite"] = rewrite(path),
+                    ["serverless-post-function"] = 
access("ngx.req.set_uri_args('foo=2')"),
+                },
+                clear = {
+                    ["proxy-rewrite"] = rewrite("/other"),
+                    ["serverless-post-function"] = access(
+                        "ctx.var.upstream_uri = ''; 
ngx.req.set_uri_args('foo=2')"),
+                },
+                untouched = {},
+                native = {
+                    ["serverless-pre-function"] = {
+                        phase = "rewrite",
+                        functions = {[[return function(conf, ctx)
+                            ngx.var.upstream_uri = '/other?fixed=2'
+                            ctx.var._cache.upstream_uri = nil
+                        end]]},
+                    },
+                    ["proxy-mirror"] = mirror,
+                },
+            }
+            for name, plugins in pairs(cases) do
+                local code, body = t("/apisix/admin/routes/servlet-override-" 
.. name,
+                    ngx.HTTP_PUT, {
+                        uri = "/anything",
+                        host = name .. ".test",
+                        plugins = plugins,
+                        upstream = {
+                            type = "roundrobin",
+                            nodes = {["127.0.0.1:1980"] = 1},
+                        },
+                    })
+                if code >= 300 then
+                    ngx.status = code
+                    ngx.say(body)
+                    return
+                end
+            end
+            ngx.say("passed")
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 2: same-path rewrite removes the query
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: same.test
+--- response_body
+/anything;jsessionid=x
+
+
+
+=== TEST 3: explicit URI retains its own query
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: different.test
+--- response_body
+/other?fixed=2
+
+
+
+=== TEST 4: mirror after rewrite preserves the explicit same-path URI
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: mirror.test
+--- response_body
+/anything;jsessionid=x
+--- error_log
+mirror-uri[/anything;jsessionid=x]
+--- no_error_log
+[error]
+mirror-uri[/anything;jsessionid=x?foo=1]
+
+
+
+=== TEST 5: mirror before rewrite still observes the original query
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: default_order.test
+--- response_body
+/anything;jsessionid=x
+--- error_log
+mirror-uri[/anything;jsessionid=x?foo=1]
+--- no_error_log
+[error]
+
+
+
+=== TEST 6: query-only access changes are appended to the servlet path
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: args.test
+--- response_body
+/anything;jsessionid=x?foo=2
+
+
+
+=== TEST 7: an access plugin can explicitly remove the query
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: override.test
+--- response_body
+/anything;jsessionid=x
+
+
+
+=== TEST 8: later query changes do not replace an explicit upstream URI
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: later_args.test
+--- response_body
+/anything;jsessionid=x
+
+
+
+=== TEST 9: clearing an override restores servlet path and live query fallback
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: clear.test
+--- response_body
+/anything;jsessionid=x?foo=2
+
+
+
+=== TEST 10: override state does not leak to the next request
+--- config
+    location /t {
+        content_by_lua_block {
+            local httpc = require("resty.http").new()
+            for _, host in ipairs({"same.test", "untouched.test"}) do
+                local res = assert(httpc:request_uri(
+                    "http://127.0.0.1:1984/anything;jsessionid=x?foo=1";, {
+                        headers = {Host = host},
+                    }))
+                assert(res.status == 200)
+                ngx.print(res.body)
+            end
+        }
+    }
+--- request
+GET /t
+--- response_body
+/anything;jsessionid=x
+/anything;jsessionid=x?foo=1
+
+
+
+=== TEST 11: preserve a different URI even if its assignment bypasses ctx.var
+--- request
+GET /anything;jsessionid=x?foo=1
+--- more_headers
+Host: native.test
+--- response_body
+/other?fixed=2
+--- error_log
+mirror-uri[/other?fixed=2]
+--- no_error_log
+[error]
+
+
+
+=== TEST 12: delete routes
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            for _, name in ipairs({"same", "different", "mirror", 
"default_order", "args",
+                                   "override", "later_args", "clear", 
"untouched", "native"}) do
+                local code, body = t("/apisix/admin/routes/servlet-override-" 
.. name,
+                    ngx.HTTP_DELETE)
+                if code >= 300 then
+                    ngx.status = code
+                    ngx.say(body)
+                    return
+                end
+            end
+            ngx.say("passed")
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
diff --git a/t/router/servlet-upstream-uri.t b/t/router/servlet-upstream-uri.t
index 0a5b3efe0..7b0766490 100644
--- a/t/router/servlet-upstream-uri.t
+++ b/t/router/servlet-upstream-uri.t
@@ -43,6 +43,7 @@ add_block_preprocessor(sub {
             content_by_lua_block {
                 ngx.say("protected-handler")
                 ngx.say("route-marker=", ngx.var.http_x_route_marker or "")
+                ngx.say("request-uri=", ngx.var.request_uri)
             }
         }
 
@@ -53,6 +54,20 @@ add_block_preprocessor(sub {
                 ngx.say("request-uri=", ngx.var.request_uri)
             }
         }
+
+        location /early-plugin {
+            content_by_lua_block {
+                ngx.say("observed-upstream-uri=", 
ngx.var.http_x_observed_upstream_uri or "")
+                ngx.say("request-uri=", ngx.var.request_uri)
+            }
+        }
+
+        location /data-mask {
+            content_by_lua_block {
+                ngx.say("data-mask-handler")
+                ngx.say("request-uri=", ngx.var.request_uri)
+            }
+        }
 _EOC_
     }
 });
@@ -66,6 +81,23 @@ __DATA__
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
+            local code, body = t("/apisix/admin/consumers",
+                ngx.HTTP_PUT,
+                {
+                    username = "jack",
+                    plugins = {
+                        ["key-auth"] = {
+                            key = "secret-key",
+                        },
+                    },
+                }
+            )
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
             local routes = {
                 {
                     id = "protected-exact-path",
@@ -73,7 +105,9 @@ __DATA__
                     priority = 100000,
                     uri = "/anything",
                     plugins = {
-                        ["key-auth"] = {},
+                        ["key-auth"] = {
+                            hide_credentials = true,
+                        },
                     },
                 },
                 {
@@ -93,6 +127,44 @@ __DATA__
                         },
                     },
                 },
+                {
+                    id = "early-plugin-test",
+                    host = "servlet-uri.test",
+                    priority = 100001,
+                    uri = "/early-plugin/*",
+                    plugins = {
+                        ["serverless-pre-function"] = {
+                            phase = "rewrite",
+                            functions = {
+                                "return function(conf, ctx) 
ngx.req.set_header('X-Observed-Upstream-Uri', ctx.var.upstream_uri or '') end",
+                            },
+                        },
+                    },
+                },
+                {
+                    id = "data-mask-test",
+                    host = "servlet-uri.test",
+                    priority = 100002,
+                    uri = "/data-mask",
+                    plugins = {
+                        ["data-mask"] = {
+                            request = {
+                                {
+                                    action = "remove",
+                                    name = "password",
+                                    type = "query",
+                                },
+                            },
+                        },
+                        ["file-logger"] = {
+                            path = "mask-servlet-upstream.log",
+                            log_format = {
+                                request_line = "$request_line",
+                                upstream_uri = "$upstream_uri",
+                            },
+                        },
+                    },
+                },
             }
 
             for _, route in ipairs(routes) do
@@ -101,7 +173,7 @@ __DATA__
                     type = "roundrobin",
                 }
 
-                local code, body = t("/apisix/admin/routes/" .. route.id,
+                code, body = t("/apisix/admin/routes/" .. route.id,
                     ngx.HTTP_PUT, route)
                 if code >= 300 then
                     ngx.status = code
@@ -155,7 +227,135 @@ 
qr/^path-handler\nroute-marker=[a-f]{6}\nrequest-uri=\/anything\/sub;jsessionid=
 
 
 
-=== TEST 5: delete routes
+=== TEST 5: query modifications (key-auth hide_credentials) are preserved 
during servlet normalization
+--- request
+GET /anything;jsessionid=x?apikey=secret-key&foo=1
+--- more_headers
+Host: servlet-uri.test
+--- response_body eval
+"path-handler\nroute-marker=\nrequest-uri=/anything;jsessionid=x?foo=1\n"
+--- no_error_log
+[error]
+
+
+
+=== TEST 6: when all query args are stripped by hide_credentials, no trailing 
question mark is sent upstream
+--- request
+GET /anything;jsessionid=x?apikey=secret-key
+--- more_headers
+Host: servlet-uri.test
+--- response_body eval
+"path-handler\nroute-marker=\nrequest-uri=/anything;jsessionid=x\n"
+--- no_error_log
+[error]
+
+
+
+=== TEST 7: early plugins (rewrite/access phase) observe servlet path 
parameters in upstream_uri
+--- request
+GET /early-plugin/test;jsessionid=x?foo=1
+--- more_headers
+Host: servlet-uri.test
+--- response_body eval
+"observed-upstream-uri=/early-plugin/test;jsessionid=x\nrequest-uri=/early-plugin/test;jsessionid=x?foo=1\n"
+--- no_error_log
+[error]
+
+
+
+=== TEST 8: data-mask sanitizes upstream_uri and request_line when servlet 
normalization is on
+--- request
+GET /data-mask;jsessionid=x?password=secret
+--- more_headers
+Host: servlet-uri.test
+--- response_body eval
+"data-mask-handler\nrequest-uri=/data-mask;jsessionid=x?password=secret\n"
+--- no_error_log
+[error]
+
+
+
+=== TEST 9: verify log contains masked request_line and sanitized upstream_uri
+--- config
+    location /t {
+        content_by_lua_block {
+            local core = require("apisix.core")
+            local fd, err = io.open("mask-servlet-upstream.log", "r")
+            if not fd then
+                core.log.error("failed to open file: ", err)
+                return
+            end
+            local line = fd:read()
+            fd:close()
+            os.remove("mask-servlet-upstream.log")
+
+            local log = core.json.decode(line)
+            if log.request_line ~= "GET /data-mask HTTP/1.1" then
+                ngx.say("unexpected request_line: ", log.request_line)
+                return
+            end
+            if log.upstream_uri ~= "/data-mask;jsessionid=x" then
+                ngx.say("unexpected upstream_uri: ", log.upstream_uri)
+                return
+            end
+
+            ngx.say("passed")
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 10: data-mask preserves remaining query args in upstream_uri during 
servlet normalization
+--- request
+GET /data-mask;jsessionid=x?password=secret&foo=1
+--- more_headers
+Host: servlet-uri.test
+--- response_body eval
+"data-mask-handler\nrequest-uri=/data-mask;jsessionid=x?password=secret&foo=1\n"
+--- no_error_log
+[error]
+
+
+
+=== TEST 11: verify log preserves remaining query args in request_line and 
upstream_uri
+--- config
+    location /t {
+        content_by_lua_block {
+            local core = require("apisix.core")
+            local fd, err = io.open("mask-servlet-upstream.log", "r")
+            if not fd then
+                core.log.error("failed to open file: ", err)
+                return
+            end
+            local line = fd:read()
+            fd:close()
+            os.remove("mask-servlet-upstream.log")
+
+            local log = core.json.decode(line)
+            if log.request_line ~= "GET /data-mask?foo=1 HTTP/1.1" then
+                ngx.say("unexpected request_line: ", log.request_line)
+                return
+            end
+            if log.upstream_uri ~= "/data-mask;jsessionid=x?foo=1" then
+                ngx.say("unexpected upstream_uri: ", log.upstream_uri)
+                return
+            end
+
+            ngx.say("passed")
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 12: delete routes and consumer
 --- config
     location /t {
         content_by_lua_block {
@@ -163,6 +363,8 @@ 
qr/^path-handler\nroute-marker=[a-f]{6}\nrequest-uri=\/anything\/sub;jsessionid=
             local route_ids = {
                 "protected-exact-path",
                 "public-wildcard-fallback",
+                "early-plugin-test",
+                "data-mask-test",
             }
 
             for _, route_id in ipairs(route_ids) do
@@ -175,6 +377,14 @@ 
qr/^path-handler\nroute-marker=[a-f]{6}\nrequest-uri=\/anything\/sub;jsessionid=
                 end
             end
 
+            local code, body = t("/apisix/admin/consumers/jack",
+                ngx.HTTP_DELETE)
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
             ngx.say("passed")
         }
     }

Reply via email to