Conversation
With `normalize_uri_like_servlet` enabled, the access phase pins $upstream_uri to the original path so upstreams still receive the parameters after ';'. Assigning $upstream_uri at all switches off nginx's "empty proxy_pass URI" passthrough, and that passthrough is what otherwise hands the client's request line -- query string included -- to the upstream, so every proxied request lost its query string. Re-append $is_args$args to the forwarded path, the same way proxy-rewrite already does when it rewrites the path itself.
nic-6443
approved these changes
Sep 23, 2026
membphis
approved these changes
Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
With
apisix.normalize_uri_like_servlet: true, every proxied request loses its query string: the upstream receives the path only._M.http_access_phase()sets$upstream_urito the original path so that servlet upstreams still see the parameters after;:uriisngx.var.uri, which never carries the query string. Assigning$upstream_uriat all is what causes the loss: with the variable left empty,proxy_pass $upstream_scheme://apisix_backend$upstream_urifalls back to forwarding the client's request line verbatim, query string included. A non-empty value turns that fallback off, and nothing puts the query string back.This PR re-appends
$is_args$argsto the forwarded path, the same wayproxy-rewritealready does when it rewrites the path itself, so the two paths that set$upstream_urinow produce the same shape. That also fixesproxy-mirror, which treats a non-empty$upstream_urias already containing the query string.An encoded question mark stays percent-encoded in the forwarded path, as before —
uri_safe_encode()escapes?, so the appended?is the only unencoded one.Which issue(s) this PR fixes:
N/A
Checklist
Documentation is unchanged: the query string reaching the upstream is the behavior the option was always meant to have and is not described anywhere as being dropped, so there is nothing to correct in
docs/.Tests:
t/router/servlet-upstream-uri.tgains a case asserting the upstream sees both the servlet parameters and the query string. It fails onmaster(upstream receives/anything/sub;jsessionid=x, query gone) and passes with this change. The existing case covering%3Fstaying percent-encoded is unaffected.