feat(router): add preserve_encoded_slash to keep %2F in path parameters#13626
Draft
AlinsRan wants to merge 1 commit into
Draft
feat(router): add preserve_encoded_slash to keep %2F in path parameters#13626AlinsRan wants to merge 1 commit into
AlinsRan wants to merge 1 commit into
Conversation
6ca9581 to
fa757bc
Compare
3df89d7 to
b9da49e
Compare
Nginx decodes an URL-encoded slash (%2F) into a real '/' in $uri before route matching, so a request like /v1/te%2Fst/products/electronics/list is seen as /v1/te/st/products/electronics/list and fails to match a route with path parameters such as /v1/:id/products/:type/list. Add an opt-in apisix.preserve_encoded_slash option. When enabled, the route matching uri is rebuilt from the raw request_uri with every percent-encoding decoded except %2F, which stays encoded so it is treated as part of a path parameter instead of a separator. The encoded slash is then forwarded to the upstream as is. '.' and '..' segments are still normalized to prevent path traversal, and a decoded null byte is rejected. The rebuild only runs when an encoded slash is present, so normal requests keep using the normalized $uri with no overhead. Closes apache#11810
b9da49e to
6e47607
Compare
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
Nginx decodes an URL-encoded slash (
%2F) into a real/in$uribeforeroute matching happens. As a result a request like
/v1/te%2Fst/products/electronics/listis seen by the router as/v1/te/st/products/electronics/list, which has a different number of pathsegments and therefore fails to match a route defined with path parameters such
as
/v1/:id/products/:type/list(returns404 Route Not Found). This is theproblem reported in #11810, and it cannot be fixed in
lua-resty-radixtree(the parameter pattern
[^/]+must stop at a real slash to keep segmentationcorrect) because the information is already lost by the time the router runs.
This PR adds an opt-in
apisix.preserve_encoded_slashoption (defaultfalse).When enabled, the route matching uri is rebuilt from the raw
request_uriwithevery percent-encoding decoded except
%2F/%2f, which is kept encoded soit is treated as part of a path parameter instead of a separator. The encoded
slash is then forwarded to the upstream as is.
To stay safe while bypassing Nginx's
$urinormalization, the rebuild:.and..segments (so an encoded dot like%2e%2ecannot be usedto bypass route rules via path traversal);
%2Fkeep using the already normalized
$uriwith no overhead.This follows the same access-phase, opt-in pattern as the existing
normalize_uri_like_servletoption.Which issue(s) this PR fixes:
Fixes #11810
Checklist
false)