-
Notifications
You must be signed in to change notification settings - Fork 2.8k
fix(proxy-rewrite): query string discarded when use_real_request_uri_… #12843
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
fix(proxy-rewrite): query string discarded when use_real_request_uri_… #12843
Conversation
…unsafe is true When use_real_request_uri_unsafe is set to true, url that was requested with query string, arguments is not parsed. Expected to parse the arguments just like same default behavior when use_real_request_uri_unsafe is set to false. The reason this problem exist is because `if ctx.var.is_args == "?" then` statement is inside `if not conf.use_real_request_uri_unsafe then` which then bypasses args parsing.
Baoyuantop
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the plugin only configures "use_real_request_uri_unsafe": true, it will cause the query to be concatenated repeatedly.
|
Hi @Baoyuantop alright I think I understand what you mean. I think it is better for me to debug it line by line in this case. For your side normally how do you run debugging/printing code output? |
The real issue lies in the fact that when use_real_request_uri_unsafe is set to true and conf.uri is provided, the core.utils.resolve_var output back an upstream uri that does not include query string. Therefore we need to concatenate the query string for the case if conf.uri is true. The previous commit does not solve the issue as the issue is not related in the `if not conf.use_real_request_uri_unsafe then` statement.
| local separator_escaped = false | ||
|
|
||
| local query_string = "" | ||
| -- When use_real_request_uri_unsafe is true, we use real_request_uri directly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please simplify the comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Fixes proxy-rewrite behavior where the original request query string is dropped when use_real_request_uri_unsafe=true and conf.uri is set, aligning unsafe mode with the default (safe) behavior.
Changes:
- Update
proxy-rewriterewrite logic to preserve the query string whenuse_real_request_uri_unsafe=trueanduriis configured. - Add regression tests covering query preservation in unsafe mode.
- Extend/adjust tests around URI normalization behavior when unsafe mode is disabled.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| apisix/plugins/proxy-rewrite.lua | Appends the original query string when building upstream_uri from conf.uri in unsafe mode. |
| t/plugin/proxy-rewrite.t | Adds tests to verify query args are preserved when use_real_request_uri_unsafe=true and uri is rewritten. |
| t/plugin/proxy-rewrite3.t | Updates test descriptions and adds coverage for normalization behavior when unsafe mode is not enabled. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| -- uri has higher priority than regex_uri. | ||
| if conf.uri ~= nil then | ||
| -- Set the upstream_uri by resolving variables in conf.uri | ||
| upstream_uri = core.utils.resolve_var(conf.uri, ctx.var, escape_separator) .. query_string |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When use_real_request_uri_unsafe is true and conf.uri already contains a query string (e.g. /path?x=1), concatenating .. query_string (which starts with ?) produces an invalid URI like /path?x=1?y=2. This also diverges from the non-unsafe branch which merges query params using ?/& logic. Please merge the extracted query into conf.uri the same way: if the resolved conf.uri already has ?, append & plus the extracted query without its leading ?; otherwise append it as-is. Add/adjust a test to cover conf.uri containing its own query when use_real_request_uri_unsafe=true.
| upstream_uri = core.utils.resolve_var(conf.uri, ctx.var, escape_separator) .. query_string | |
| local resolved_uri = core.utils.resolve_var(conf.uri, ctx.var, escape_separator) | |
| if query_string ~= "" then | |
| -- Merge extracted query string into resolved_uri: | |
| -- if resolved_uri already has a query part, append with '&', | |
| -- otherwise append the extracted query as-is. | |
| if str_find(resolved_uri, "?", 1, true) then | |
| upstream_uri = resolved_uri .. "&" .. sub_str(query_string, 2) | |
| else | |
| upstream_uri = resolved_uri .. query_string | |
| end | |
| else | |
| upstream_uri = resolved_uri | |
| end |
…unsafe is true
When use_real_request_uri_unsafe is set to true, url that was requested with query string, arguments is not parsed. Expected to parse the arguments just like same default behavior when use_real_request_uri_unsafe is set to false.
The real issue lies in the fact that when use_real_request_uri_unsafe is set to true and conf.uri is provided, the core.utils.resolve_var output back an upstream uri that does not include query string. Therefore we need to concatenate the query string for the case if conf.uri is true.
Description
Which issue(s) this PR fixes:
Fixes #12623
Checklist