This is an automated email from the ASF dual-hosted git repository.
AlinsRan 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 a3a8138f6 fix(proxy-rewrite): query string discarded when
use_real_request_uri_… (#12843)
a3a8138f6 is described below
commit a3a8138f6709fd6ebec519a2877e21d7bec84dde
Author: YapWC <[email protected]>
AuthorDate: Wed Jul 8 16:23:22 2026 +0800
fix(proxy-rewrite): query string discarded when use_real_request_uri_…
(#12843)
---
apisix/plugins/proxy-rewrite.lua | 15 +++
t/plugin/proxy-rewrite.t | 285 +++++++++++++++++++++++++++++++++++++++
t/plugin/proxy-rewrite3.t | 48 ++++++-
3 files changed, 346 insertions(+), 2 deletions(-)
diff --git a/apisix/plugins/proxy-rewrite.lua b/apisix/plugins/proxy-rewrite.lua
index c1609c612..6bddfa39a 100644
--- a/apisix/plugins/proxy-rewrite.lua
+++ b/apisix/plugins/proxy-rewrite.lua
@@ -284,13 +284,28 @@ function _M.rewrite(conf, ctx)
local upstream_uri = ctx.var.uri
local separator_escaped = false
+
+ -- resolve_var() below drops the query string, so keep the original one
from
+ -- real_request_uri to re-append it when conf.uri is set.
+ local query_string = ""
if conf.use_real_request_uri_unsafe then
upstream_uri = ctx.var.real_request_uri
+ local index = str_find(upstream_uri, "?")
+ query_string = index and sub_str(upstream_uri, index) or ""
end
if conf.uri ~= nil then
separator_escaped = true
upstream_uri = core.utils.resolve_var(conf.uri, ctx.var,
escape_separator)
+ if query_string ~= "" then
+ -- merge with '&' when conf.uri already carries its own query
string,
+ -- otherwise append the original query string as-is
+ if str_find(upstream_uri, "?") then
+ upstream_uri = upstream_uri .. "&" .. sub_str(query_string, 2)
+ else
+ upstream_uri = upstream_uri .. query_string
+ end
+ end
elseif conf.regex_uri ~= nil then
if not str_find(upstream_uri, "?") then
diff --git a/t/plugin/proxy-rewrite.t b/t/plugin/proxy-rewrite.t
index 276dd02ed..6b75fbe7c 100644
--- a/t/plugin/proxy-rewrite.t
+++ b/t/plugin/proxy-rewrite.t
@@ -1231,3 +1231,288 @@ GET /hello
uri: /uri
host: test.com:6443
x-real-ip: 127.0.0.1
+
+
+
+=== TEST 45: set route(rewrite uri args with unsafe allowed)
+--- 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": "/plugin_proxy_rewrite_args",
+ "use_real_request_uri_unsafe": true
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 46: rewrite uri args
+--- request
+GET /hello?q=apisix&a=iresty HTTP/1.1
+--- response_body
+uri: /plugin_proxy_rewrite_args
+a: iresty
+q: apisix
+
+
+
+=== TEST 47: set route(rewrite uri empty args with unsafe allowed)
+--- 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": "/plugin_proxy_rewrite_args",
+ "use_real_request_uri_unsafe": true
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 48: rewrite uri empty args
+--- request
+GET /hello HTTP/1.1
+--- response_body
+uri: /plugin_proxy_rewrite_args
+
+
+
+=== TEST 49: set route(conf.uri carries its own query,
use_real_request_uri_unsafe)
+--- 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": "/plugin_proxy_rewrite_args?x=1",
+ "use_real_request_uri_unsafe": true
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 50: merge conf.uri query with incoming query (use '&', not double '?')
+--- request
+GET /hello?q=apisix HTTP/1.1
+--- response_body
+uri: /plugin_proxy_rewrite_args
+q: apisix
+x: 1
+
+
+
+=== TEST 51: set route(use_real_request_uri_unsafe only, no conf.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": {
+ "use_real_request_uri_unsafe": true
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/plugin_proxy_rewrite_args"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 52: query string reaches upstream exactly once without conf.uri
+--- request
+GET /plugin_proxy_rewrite_args?q=apisix HTTP/1.1
+--- response_body
+uri: /plugin_proxy_rewrite_args
+q: apisix
+
+
+
+=== TEST 53: set route(conf.uri echoing raw request_uri,
use_real_request_uri_unsafe)
+--- 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": "/print_uri_detailed",
+ "use_real_request_uri_unsafe": true
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 54: query with special characters passed through unchanged (unsafe)
+--- request
+GET /hello?name=a%20b&x=%E4%B8%AD HTTP/1.1
+--- response_body
+ngx.var.uri: /print_uri_detailed
+ngx.var.request_uri: /print_uri_detailed?name=a%20b&x=%E4%B8%AD
+
+
+
+=== TEST 55: query with multiple '?' passed through unchanged (unsafe)
+--- request
+GET /hello?a=1?b=2 HTTP/1.1
+--- response_body
+ngx.var.uri: /print_uri_detailed
+ngx.var.request_uri: /print_uri_detailed?a=1?b=2
+
+
+
+=== TEST 56: set route(same conf.uri with use_real_request_uri_unsafe disabled)
+--- 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": "/print_uri_detailed",
+ "use_real_request_uri_unsafe": false
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 57: query preserved with use_real_request_uri_unsafe disabled (both
variants consistent)
+--- request
+GET /hello?name=a%20b&x=1 HTTP/1.1
+--- response_body
+ngx.var.uri: /print_uri_detailed
+ngx.var.request_uri: /print_uri_detailed?name=a%20b&x=1
diff --git a/t/plugin/proxy-rewrite3.t b/t/plugin/proxy-rewrite3.t
index 55afe14cc..f16a03810 100644
--- a/t/plugin/proxy-rewrite3.t
+++ b/t/plugin/proxy-rewrite3.t
@@ -199,7 +199,7 @@ plugin_proxy_rewrite get method: POST
-=== TEST 8: set route(unsafe uri not normalized at request)
+=== TEST 8: set route(unsafe uri not normalized at request with unsafe allowed)
--- config
location /t {
content_by_lua_block {
@@ -243,7 +243,7 @@ ngx.var.request_uri: /print%5Furi%5Fdetailed
-=== TEST 10: set route(safe uri not normalized at request)
+=== TEST 10: set route(safe uri not normalized at request with unsafe allowed)
--- config
location /t {
content_by_lua_block {
@@ -999,3 +999,47 @@ GET /hello/%ED%85%8C%EC%8A%A4%ED%8A%B8 HTTP/1.1
}
--- response_body
/hello?unsafe_variable=%ED%85%8C%EC%8A%A4%ED%8A%B8
+
+
+
+=== TEST 42: set route(unsafe uri normalized at request with unsafe not
allowed)
+--- 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,
+ [[{
+ "methods": ["GET"],
+ "plugins": {
+ "proxy-rewrite": {
+ "use_real_request_uri_unsafe": false
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/print_uri_detailed"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 43: unsafe uri normalized at request
+--- request
+GET /print%5Furi%5Fdetailed HTTP/1.1
+--- response_body
+ngx.var.uri: /print_uri_detailed
+ngx.var.request_uri: /print_uri_detailed