diff --git a/spring-cloud-gateway-server-webmvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunction.java b/spring-cloud-gateway-server-webmvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunction.java index 5116808ed..f262ffc1f 100644 --- a/spring-cloud-gateway-server-webmvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunction.java +++ b/spring-cloud-gateway-server-webmvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunction.java @@ -98,6 +98,10 @@ public ServerResponse handle(ServerRequest serverRequest) { .replaceQueryParams(params) .build(true) .toUri(); + String rawQuery = serverRequest.uri().getRawQuery(); + if (hasValuelessQueryParameter(rawQuery)) { + url = UriComponentsBuilder.fromUri(url).replaceQuery(rawQuery).build(true).toUri(); + } // @formatter:on HttpHeaders filteredRequestHeaders = filterHeaders(this.requestHttpHeadersFilters, @@ -139,6 +143,18 @@ private HttpHeaders filterHeaders(@Nullable List filter return filtered; } + private boolean hasValuelessQueryParameter(@Nullable String rawQuery) { + if (rawQuery == null || rawQuery.isEmpty()) { + return false; + } + for (String pair : rawQuery.split("&")) { + if (!pair.isEmpty() && pair.indexOf('=') < 0) { + return true; + } + } + return false; + } + public interface URIResolver extends Function { } diff --git a/spring-cloud-gateway-server-webmvc/src/test/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunctionTest.java b/spring-cloud-gateway-server-webmvc/src/test/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunctionTest.java index 5d1313cae..212e73ee7 100644 --- a/spring-cloud-gateway-server-webmvc/src/test/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunctionTest.java +++ b/spring-cloud-gateway-server-webmvc/src/test/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunctionTest.java @@ -103,7 +103,7 @@ public Stream orderedStream() { function.onApplicationEvent(null); MockHttpServletRequest servletRequest = MockMvcRequestBuilders - .get("http://localhost/é?foo=value1 value2&bar=value3=&qux=value4+") + .get("http://localhost/é?foo=value1 value2&bar=value3=&qux=value4+&flag&next=1") .buildRequest(null); servletRequest.setAttribute(MvcUtils.GATEWAY_REQUEST_URL_ATTR, URI.create("http://localhost:8080")); ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); @@ -112,11 +112,8 @@ public Stream orderedStream() { URI uri = proxyExchange.getRequest().getUri(); - assertThat(uri).hasToString("http://localhost:8080/%C3%A9?foo=value1%20value2&bar=value3%3D&qux=value4%2B") - .hasPath("/é") - .hasParameter("foo", "value1 value2") - .hasParameter("bar", "value3=") - .hasParameter("qux", "value4+"); + assertThat(uri).hasToString("http://localhost:8080/%C3%A9?foo=value1%20value2&bar=value3=&qux=value4+&flag&next=1") + .hasPath("/é"); } private class TestProxyExchange extends AbstractProxyExchange {