-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Fix: prevent duplicated encoding request parameters filter #3598
base: main
Are you sure you want to change the base?
Fix: prevent duplicated encoding request parameters filter #3598
Conversation
@spencergibb |
ServerHttpRequest req = exchange.getRequest(); | ||
|
||
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUri(req.getURI()); | ||
if (req.getQueryParams().containsKey(config.getName())) { | ||
uriComponentsBuilder.replaceQueryParam(config.getName(), config.getReplacement()); | ||
|
||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>(req.getQueryParams()); | ||
if (queryParams.containsKey(config.getName())) { | ||
queryParams.remove(config.getName()); | ||
queryParams.add(config.getName(), config.getReplacement()); | ||
} |
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.
The ServerHttpRequest.getQueryParams()
method returns the decoded query parameters
.
Therefore, it can replace new parameter
in the decoded query parameters
.
try { | ||
MultiValueMap<String, String> encodedQueryParams = UriUtils.encodeQueryParams(queryParams); | ||
URI uri = uriComponentsBuilder.replaceQueryParams(unmodifiableMultiValueMap(encodedQueryParams)) | ||
.build(true) |
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.
Indicates that it is encoded.
URI uri = uriComponentsBuilder.build().toUri(); | ||
ServerHttpRequest request = req.mutate().uri(uri).build(); | ||
try { | ||
MultiValueMap<String, String> encodedQueryParams = UriUtils.encodeQueryParams(queryParams); |
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.
Encode only query parameters
including replaced parameter
.
(excluding uri paths, fragment, etc.)
@@ -57,14 +58,19 @@ public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { | |||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>(request.getQueryParams()); | |||
queryParams.remove(config.getName()); |
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.
ServerHttpRequest.getRequest()
returns decoded query parameters
as a response.
So, it finds the parameter
in the decoded query parameters
and removes them.
.build() | ||
.toUri(); | ||
try { | ||
MultiValueMap<String, String> encodedQueryParams = UriUtils.encodeQueryParams(queryParams); |
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.
Encode only query parameters
including replaced parameter
.
(excluding uri paths, fragment, etc.)
MultiValueMap<String, String> encodedQueryParams = UriUtils.encodeQueryParams(queryParams); | ||
URI newUri = UriComponentsBuilder.fromUri(request.getURI()) | ||
.replaceQueryParams(unmodifiableMultiValueMap(encodedQueryParams)) | ||
.build(true) |
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.
Indicates that it is encoded.
Motivation
Hello.
I found that there is a case where the encoded query parameter in the
RewriteRequestParameterGatewayFilterFactory
andRemoveRequestHeaderGatewayFilterFactory
factory filters encodes the%
character again.For example, if we apply the
RemoveRequestHeaderGatewayFilterFactory
filter tohttp://localhost?foo%5B%5D=123&bar=456
to remove the bar parameter,%
becomes an encoding target, and the query parameter is duplicated and encoded ashttp://localhost?foo%255B%255D=123
.I think I should keep the existing encoded query parameter as
http://localhost?foo%5B%5D=123
.Therefore, I will explain the items processed for each filter in more detail.
RewriteRequestParameterGatewayFilterFactory
Reason
config.getName()
existed inServerWebExchange.getRequest().getQueryParams()
and directly replacedconfig.getReplacement()
inUriComponentsBuilder
.If the query parameter to be replaced is encoded, there is a problem that the
name
andreplacement
ofconfig
may not be replaced properly.Even if we inject it by encoding it in config, it may be encoded twice as a result and it may not be found in
ServerWebExchange.getRequest().getQueryParams()
.(since
UriComponentsBuilder.build()
encodes them by default)For example, if it is
http://localhost?foo=123#bar=baz%5B%5D
, it can be encoded once more up to the fragment, likehttp://localhost?foo=123#bar=baz%255B%255D
.Solve
Modify to replace query parameters based on the return value of
ServerWebExchange.getRequest().getQueryParams()
.(
ServerWebExchange.getRequest().getQueryParams()
internally returns decoded query parameters).Encode only the query parameters and inject them into the
UriComponentsBuilder
, and do not attempt to encode other segments.RemoveRequestHeaderGatewayFilterFactory
RewriteRequestParameterGatewayFilterFactory
is the same.Modify it to encode only the query parameters segment.
Thanks.