Repository navigation
fix(router): preserve rewrite-phase query argument changes during servlet URI normalization #14040
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -556,13 +556,13 @@ 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 | ||
| end | ||
|
|
||
|
|
||
|
|
@@ -1080,6 +1080,15 @@ function _M.http_access_phase() | |
| end | ||
| span:finish(ngx_ctx) | ||
|
|
||
| if api_ctx.servlet_upstream_uri then | ||
| if 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 "") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the update. I compared base With data-mask does not sanitize Could you handle this field during log masking and add a regression test for this combination?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will do it by today I did not get the eye on that |
||
| end | ||
| end | ||
|
|
||
| _M.handle_upstream(api_ctx, route, enable_websocket) | ||
| end | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -91,8 +91,12 @@ 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 ctx.var.upstream_uri == ctx.servlet_upstream_uri and | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has the same equality-check issue as the final URI assembly in init.lua: it can re-append query arguments that proxy-rewrite explicitly removed. With normalize_uri_like_servlet: true, this configuration makes rewriting run before mirroring:
Could you also preserve the explicit plugin URI override here and add a regression test for this execution order? |
||
| (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 | ||
|
|
||
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.
Thanks for the update!
The equality check upstream_uri == servlet_upstream_uri cannot distinguish an untouched URI from one explicitly rewritten to the same path without a query string.
With normalize_uri_like_servlet: true and this configuration:
{
"proxy-rewrite": {
"use_real_request_uri_unsafe": true,
"regex_uri": ["^.*$", "/anything;jsessionid=x"]
}
}
For /anything;jsessionid=x?foo=1, proxy-rewrite explicitly sets the upstream URI to /anything;jsessionid=x. This condition evaluates to true, and the following concatenation re-appends ?foo=1 from var.is_args and var.args.
I verified this with real HTTP requests using the APISIX 3.19.0 container runtime with each source tree mounted:
Could you preserve the explicit plugin URI override and add a regression test for this case, while keeping the existing hide_credentials tests passing?