Skip to content

fix(router): preserve rewrite-phase query argument changes during servlet URI normalization - #14040

Open
Ankit-cs wants to merge 1 commit into
apache:masterfrom
Ankit-cs:fix/preserve-query-during-servlet-normalization
Open

Ankit-cs wants to merge 1 commit into
apache:masterfrom
Ankit-cs:fix/preserve-query-during-servlet-normalization

Conversation

@Ankit-cs

Copy link
Copy Markdown

Description

Background & Problem:

When apisix.normalize_uri_like_servlet is enabled, $upstream_uri was materialized before route rewrite and access plugins executed.

Some plugins modify the request arguments dynamically during these later phases. For example, key-auth and jwt-auth remove query credentials via core.request.set_uri_args() when hide_credentials: true is configured. Because $upstream_uri already contained a snapshot of the earlier query string, those query modifications were not reflected in the URI forwarded upstream, causing credentials to leak and query argument changes to be lost.

Solution:

  1. Store the normalized servlet path separately in api_ctx.servlet_upstream_uri instead of eagerly writing to api_ctx.var.upstream_uri.
  2. Assemble $upstream_uri with the updated $is_args$args after the rewrite and access plugin phases have completed.
  3. Respect plugin precedence: if a plugin like proxy-rewrite explicitly sets api_ctx.var.upstream_uri, do not overwrite it.
  4. Updated proxy-mirror to also respect servlet_upstream_uri.
  5. Added regression test cases in t/router/servlet-upstream-uri.t covering:
    • apisix.normalize_uri_like_servlet: true
    • query-based key-auth with hide_credentials: true
    • unrelated query arguments remaining intact
    • clean URI with no trailing ? when all arguments are stripped.

Which issue(s) this PR fixes:

Fixes #13983

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change (Documentation unchanged: this is a bug fix restoring expected behavior)
  • I have verified that this change is backward compatible

@Ankit-cs

Copy link
Copy Markdown
Author

as i am learning lua for the first time so that is the reason i got late in solving the bug @Baoyuantop sir and looking for feedback also.

Comment thread apisix/init.lua Outdated
api_ctx.var.upstream_uri = core.utils.uri_safe_encode(uri)
-- after ';'. URI-encode it and store separately so $is_args$args can
-- be appended after rewrite and access plugin phases complete.
api_ctx.servlet_upstream_uri = core.utils.uri_safe_encode(uri)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Early plugins lose servlet path parameters

With servlet normalization enabled, upstream_uri stays empty during rewrite and access plugins. The external pre-request runner sees a stripped path, and GraphQL introspection can target a different endpoint than the forwarded request.

Example: For /anything;jsessionid=x, the pre-request runner now receives /anything; the upstream receives /anything;jsessionid=x. A GraphQL endpoint available only at the latter path fails schema discovery at the former path.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK @Baoyuantop i will solve this

@Ankit-cs
Ankit-cs force-pushed the fix/preserve-query-during-servlet-normalization branch from 10d3107 to c1fd74f Compare October 16, 2026 03:52
@Ankit-cs

Copy link
Copy Markdown
Author

Hi @Baoyuantop,looking for another feedback!

I've updated the PR so that api_ctx.var.upstream_uri is populated early with the safe-encoded servlet path (/anything;jsessionid=x), allowing early plugins like ext-plugin and graphql-limit-count to observe the servlet path parameters. The final query string ($is_args$args) is then synchronized after rewrite and access phases finish to preserve query modifications (e.g. hide_credentials).

I also added a regression test in t/router/servlet-upstream-uri.t covering this scenario.

@Ankit-cs

Copy link
Copy Markdown
Author

Hi @Baoyuantop sir can you look a minute for my pr it will be really great if you provide some feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(router): preserve rewrite-phase query argument changes during servlet URI normalization

2 participants