Open jluiz20 opened 3 months ago
Possible fix:
public class ProxyExchangeHandlerFunction
implements HandlerFunction<ServerResponse>, ApplicationListener<ContextRefreshedEvent> {
[...]
@Override
public ServerResponse handle(ServerRequest serverRequest) {
URI uri = uriResolver.apply(serverRequest);
boolean encoded = containsEncodedQueryOrPath(serverRequest.uri());
// @formatter:off
URI url = UriComponentsBuilder.fromUri(serverRequest.uri())
.scheme(uri.getScheme())
.host(uri.getHost())
.port(uri.getPort())
.replaceQueryParams(encoded ? UriUtils.encodeQueryParams(serverRequest.params()) : serverRequest.params())
.build(encoded)
.toUri();
// @formatter:on
[...]
private static boolean containsEncodedQueryOrPath(URI uri) {
String rawQuery = uri.getRawQuery();
return (rawQuery != null && rawQuery.contains("%")) || (uri.getRawPath() != null && uri.getRawPath().contains("%"));
}
[...]
Of course, @jluiz20 would need to remove his workaround afterwards.
Describe the bug When passing certain query parameters with encoded characters (like
%26
) I am expecting that they are passed encoded like this to the downstream services but what is happening is that they are being decoded.For example, when using the example https://github.com/spencergibb/spring-cloud-gateway-mvc-sample
src/main/java/com/example/gatewaymvcsample/Route01FirstRoute.java
endpoint passing some encoded characters, we can see that they are being decoded in the parametersGET localhost:8080/anything/first?company=H%26M&search=one%20two
The other weird part is that the URI is not encoded.
with the
&
in the parameters, when it calls the downstream services it does not behave well as it thinks is a parameter separation character and not part of the company parameter.I was able to make it work by creating a before filter and encoding the query parameters before calling the downstream services but for me, it seems a bit of a workaround.
I am not sure which behavior is correct (I think it should remain encoded) but the weird thing is that the parameters and URI are different (one encoded, the other not)
Is this the expected behavior?
Versions: org.springframework.boot:3.3.2 org.springframework.cloud:spring-cloud-dependencies:2023.0.3 org.springframework.cloud:spring-cloud-gateway-server-mvc:4.1.5
Sample You can just call the
GET localhost:8080/anything/first?company=H%26M&search=one%20two
for Route01FirstRoute in the sample project https://github.com/spencergibb/spring-cloud-gateway-mvc-sample