This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new e27895d710 [ISSUE #6628] Preserve query when collapsing URI slashes
(#7194)
e27895d710 is described below
commit e27895d710ab9ef188a6bb2fd186f67b270e4968
Author: Liming Deng <[email protected]>
AuthorDate: Wed Sep 30 12:12:52 2026 +0800
[ISSUE #6628] Preserve query when collapsing URI slashes (#7194)
* fix(web): preserve query when collapsing slashes
* perf(web): reuse the repeated-slash pattern
---
.../apache/shenyu/web/filter/CollapseSlashesFilter.java | 11 +++++++++--
.../shenyu/web/filter/CollapseSlashesFilterTest.java | 16 +++++++++++++++-
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git
a/shenyu-web/src/main/java/org/apache/shenyu/web/filter/CollapseSlashesFilter.java
b/shenyu-web/src/main/java/org/apache/shenyu/web/filter/CollapseSlashesFilter.java
index a8c4c1b840..60a7c7b27a 100644
---
a/shenyu-web/src/main/java/org/apache/shenyu/web/filter/CollapseSlashesFilter.java
+++
b/shenyu-web/src/main/java/org/apache/shenyu/web/filter/CollapseSlashesFilter.java
@@ -21,21 +21,28 @@ import
org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
+import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import java.net.URI;
+import java.util.regex.Pattern;
/**
* The type Collapse slashes filter.
*/
public class CollapseSlashesFilter implements WebFilter {
+
+ private static final Pattern REPEATED_SLASHES = Pattern.compile("/{2,}");
@Override
public Mono<Void> filter(final ServerWebExchange exchange, final
WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
- String newPath = request.getURI().getRawPath().replaceAll("/{2,}",
"/");
+ String newPath =
REPEATED_SLASHES.matcher(request.getURI().getRawPath()).replaceAll("/");
if (!request.getURI().getRawPath().equals(newPath)) {
- URI newUri = request.getURI().resolve(newPath);
+ URI newUri = UriComponentsBuilder.fromUri(request.getURI())
+ .replacePath(newPath)
+ .build(true)
+ .toUri();
ServerHttpRequest newRequest =
request.mutate().uri(newUri).build();
return chain.filter(exchange.mutate().request(newRequest).build());
}
diff --git
a/shenyu-web/src/test/java/org/apache/shenyu/web/filter/CollapseSlashesFilterTest.java
b/shenyu-web/src/test/java/org/apache/shenyu/web/filter/CollapseSlashesFilterTest.java
index 18331812a2..1acfe7141a 100644
---
a/shenyu-web/src/test/java/org/apache/shenyu/web/filter/CollapseSlashesFilterTest.java
+++
b/shenyu-web/src/test/java/org/apache/shenyu/web/filter/CollapseSlashesFilterTest.java
@@ -19,6 +19,8 @@ package org.apache.shenyu.web.filter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.springframework.http.HttpMethod;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.server.ServerWebExchange;
@@ -26,8 +28,12 @@ import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
@@ -48,8 +54,16 @@ public final class CollapseSlashesFilterTest {
@Test
public void filter() {
- ServerWebExchange webExchange =
MockServerWebExchange.from(MockServerHttpRequest.post("http://localhost:8080///////test"));
+ ServerWebExchange webExchange = MockServerWebExchange.from(
+ MockServerHttpRequest.method(HttpMethod.POST,
+
URI.create("http://localhost:8080///////test?name=shenyu%20gateway#section")));
Mono<Void> filter = collapseSlashesFilter.filter(webExchange,
webFilterChain);
StepVerifier.create(filter).verifyComplete();
+
+ ArgumentCaptor<ServerWebExchange> exchangeCaptor =
ArgumentCaptor.forClass(ServerWebExchange.class);
+ verify(webFilterChain).filter(exchangeCaptor.capture());
+ assertEquals("/test",
exchangeCaptor.getValue().getRequest().getURI().getRawPath());
+ assertEquals("name=shenyu%20gateway",
exchangeCaptor.getValue().getRequest().getURI().getRawQuery());
+ assertEquals("section",
exchangeCaptor.getValue().getRequest().getURI().getRawFragment());
}
}