You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by li...@apache.org on 2023/05/05 11:51:19 UTC
[shenyu] branch master updated: refactor webfilter (#4614)
This is an automated email from the ASF dual-hosted git repository.
likeguo 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 cf506eb08 refactor webfilter (#4614)
cf506eb08 is described below
commit cf506eb081c1cbf2435824f36b8842f1e148f063
Author: xiaoyu <xi...@apache.org>
AuthorDate: Fri May 5 19:51:13 2023 +0800
refactor webfilter (#4614)
Co-authored-by: xiaoyu137 <xi...@jd.com>
---
.../config/CollapseSlashesConfiguration.java | 59 ----------------------
.../src/main/resources/application.yml | 5 +-
.../starter/gateway/ShenyuConfiguration.java | 34 +++++++++----
.../shenyu/web/filter/CollapseSlashesFilter.java | 44 ++++++++++++++++
.../org/apache/shenyu/web/filter/HealthFilter.java | 19 ++++---
.../apache/shenyu/web/filter/HealthFilterTest.java | 40 +++++++--------
6 files changed, 97 insertions(+), 104 deletions(-)
diff --git a/shenyu-bootstrap/src/main/java/org/apache/shenyu/bootstrap/config/CollapseSlashesConfiguration.java b/shenyu-bootstrap/src/main/java/org/apache/shenyu/bootstrap/config/CollapseSlashesConfiguration.java
deleted file mode 100644
index 72607b2b8..000000000
--- a/shenyu-bootstrap/src/main/java/org/apache/shenyu/bootstrap/config/CollapseSlashesConfiguration.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shenyu.bootstrap.config;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-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 java.net.URI;
-
-/**
- * Tolerant Path Slash.
- */
-@Configuration
-public class CollapseSlashesConfiguration {
-
- /**
- * declaration collapseSlashesFilter.
- * @return collapseSlashesFilter
- */
- @Bean
- @ConditionalOnProperty(
- value = "shenyu.switchConfig.collapseSlashes",
- havingValue = "true"
- )
- public WebFilter collapseSlashesFilter() {
- return (ServerWebExchange exchange, WebFilterChain chain) -> {
- ServerHttpRequest request = exchange.getRequest();
- String newPath = request.getURI().getRawPath().replaceAll("/{2,}", "/");
- if (!request.getURI().getRawPath().equals(newPath)) {
- URI newUri = request.getURI().resolve(newPath);
- ServerHttpRequest newRequest = request.mutate().uri(newUri).build();
- return chain.filter(exchange.mutate().request(newRequest).build());
- }
- return chain.filter(exchange);
- };
- }
-}
-
-
diff --git a/shenyu-bootstrap/src/main/resources/application.yml b/shenyu-bootstrap/src/main/resources/application.yml
index 5646682ec..87e400a51 100644
--- a/shenyu-bootstrap/src/main/resources/application.yml
+++ b/shenyu-bootstrap/src/main/resources/application.yml
@@ -234,12 +234,11 @@ shenyu:
paths:
- /fallback/hystrix
- /fallback/resilience4j
+ - /fallback/sentinel
health:
enabled: false
paths:
- - /actuator/health
- - /actuator/health/readiness
- - /actuator/health/liveness
+ - /actuator
- /health_check
extPlugin:
path:
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/gateway/ShenyuConfiguration.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/gateway/ShenyuConfiguration.java
index 89bd4920e..070c0cb69 100644
--- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/gateway/ShenyuConfiguration.java
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/gateway/ShenyuConfiguration.java
@@ -32,6 +32,7 @@ import org.apache.shenyu.sync.data.api.PluginDataSubscriber;
import org.apache.shenyu.web.configuration.ErrorHandlerConfiguration;
import org.apache.shenyu.web.configuration.ShenyuExtConfiguration;
import org.apache.shenyu.web.configuration.SpringExtConfiguration;
+import org.apache.shenyu.web.filter.CollapseSlashesFilter;
import org.apache.shenyu.web.filter.CrossFilter;
import org.apache.shenyu.web.filter.ExcludeFilter;
import org.apache.shenyu.web.filter.FallbackFilter;
@@ -78,12 +79,12 @@ public class ShenyuConfiguration {
* logger.
*/
private static final Logger LOG = LoggerFactory.getLogger(ShenyuConfiguration.class);
-
+
/**
* Init ShenyuWebHandler.
*
- * @param plugins this plugins is All impl ShenyuPlugin.
- * @param config the config
+ * @param plugins this plugins is All impl ShenyuPlugin.
+ * @param config the config
* @param shenyuLoaderService theLoaderServer
* @return {@linkplain ShenyuWebHandler}
*/
@@ -131,7 +132,7 @@ public class ShenyuConfiguration {
return new CommonPluginDataSubscriber(pluginDataHandlerList.getIfAvailable(Collections::emptyList),
eventPublisher.getIfAvailable(), shenyuConfig.getTrie());
}
-
+
/**
* common meta data subscriber.
*
@@ -169,6 +170,18 @@ public class ShenyuConfiguration {
return new ForwardedRemoteAddressResolver(1);
}
+ /**
+ * Collapse slashes filter web filter.
+ *
+ * @return the web filter
+ */
+ @Bean
+ @Order(-300)
+ @ConditionalOnProperty(value = "shenyu.switchConfig.collapseSlashes", havingValue = "true")
+ public WebFilter collapseSlashesFilter() {
+ return new CollapseSlashesFilter();
+ }
+
/**
* Local dispatcher filter.
*
@@ -243,14 +256,15 @@ public class ShenyuConfiguration {
/**
* Health filter.
*
+ * @param dispatcherHandler the dispatcher handler
* @param shenyuConfig the shenyu config
* @return the web filter
*/
@Bean
@Order(-99)
@ConditionalOnProperty(name = "shenyu.health.enabled", havingValue = "true")
- public WebFilter healthFilter(final ShenyuConfig shenyuConfig) {
- return new HealthFilter(shenyuConfig.getHealth().getPaths());
+ public WebFilter healthFilter(final DispatcherHandler dispatcherHandler, final ShenyuConfig shenyuConfig) {
+ return new HealthFilter(dispatcherHandler, shenyuConfig.getHealth().getPaths());
}
/**
@@ -263,23 +277,23 @@ public class ShenyuConfiguration {
public ShenyuConfig shenyuConfig() {
return new ShenyuConfig();
}
-
+
/**
* shenyu trie config.
*
* @param shenyuConfig shenyu trie config
- * @return ShenyuTrie
+ * @return ShenyuTrie shenyu trie
*/
@Bean
public ShenyuTrie shenyuTrie(final ShenyuConfig shenyuConfig) {
return new ShenyuTrie(shenyuConfig.getTrie().getChildrenSize(), shenyuConfig.getTrie().getPathRuleCacheSize(),
shenyuConfig.getTrie().getPathVariableSize(), shenyuConfig.getTrie().getMatchMode());
}
-
+
/**
* shenyu trie listener.
*
- * @return ShenyuTrieRuleListener
+ * @return ShenyuTrieRuleListener shenyu trie rule listener
*/
@Bean
public ShenyuTrieRuleListener shenyuTrieRuleListener() {
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
new file mode 100644
index 000000000..a8c4c1b84
--- /dev/null
+++ b/shenyu-web/src/main/java/org/apache/shenyu/web/filter/CollapseSlashesFilter.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.web.filter;
+
+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 reactor.core.publisher.Mono;
+
+import java.net.URI;
+
+/**
+ * The type Collapse slashes filter.
+ */
+public class CollapseSlashesFilter implements WebFilter {
+
+ @Override
+ public Mono<Void> filter(final ServerWebExchange exchange, final WebFilterChain chain) {
+ ServerHttpRequest request = exchange.getRequest();
+ String newPath = request.getURI().getRawPath().replaceAll("/{2,}", "/");
+ if (!request.getURI().getRawPath().equals(newPath)) {
+ URI newUri = request.getURI().resolve(newPath);
+ ServerHttpRequest newRequest = request.mutate().uri(newUri).build();
+ return chain.filter(exchange.mutate().request(newRequest).build());
+ }
+ return chain.filter(exchange);
+ }
+}
diff --git a/shenyu-web/src/main/java/org/apache/shenyu/web/filter/HealthFilter.java b/shenyu-web/src/main/java/org/apache/shenyu/web/filter/HealthFilter.java
index e2b5e62af..ac16327fc 100644
--- a/shenyu-web/src/main/java/org/apache/shenyu/web/filter/HealthFilter.java
+++ b/shenyu-web/src/main/java/org/apache/shenyu/web/filter/HealthFilter.java
@@ -18,14 +18,11 @@
package org.apache.shenyu.web.filter;
import org.apache.commons.collections4.CollectionUtils;
-import org.apache.shenyu.common.utils.JsonUtils;
-import org.springframework.boot.actuate.health.Health;
-import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
-import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -36,16 +33,20 @@ import java.util.Set;
*/
public final class HealthFilter extends AbstractWebFilter {
+ private final DispatcherHandler dispatcherHandler;
+
private final Set<String> paths;
/**
* Instantiates a new Health filter.
*
+ * @param dispatcherHandler the dispatcher handler
* @param paths the paths
*/
- public HealthFilter(final List<String> paths) {
+ public HealthFilter(final DispatcherHandler dispatcherHandler, final List<String> paths) {
+ this.dispatcherHandler = dispatcherHandler;
if (CollectionUtils.isEmpty(paths)) {
- this.paths = new HashSet<>(Arrays.asList("/actuator/health", "/actuator/health/readiness", "/actuator/health/liveness", "/health_check"));
+ this.paths = new HashSet<>(Arrays.asList("/actuator", "/health_check"));
} else {
this.paths = new HashSet<>(paths);
}
@@ -53,13 +54,11 @@ public final class HealthFilter extends AbstractWebFilter {
@Override
protected Mono<Boolean> doMatcher(final ServerWebExchange exchange, final WebFilterChain chain) {
- return Mono.just(paths.contains(exchange.getRequest().getURI().getPath()));
+ return Mono.just(paths.stream().anyMatch(path -> exchange.getRequest().getURI().getPath().startsWith(path)));
}
@Override
protected Mono<Void> doFilter(final ServerWebExchange exchange) {
- String result = JsonUtils.toJson(new Health.Builder().up().build());
- DataBuffer dataBuffer = exchange.getResponse().bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
- return exchange.getResponse().writeWith(Mono.just(dataBuffer));
+ return dispatcherHandler.handle(exchange);
}
}
diff --git a/shenyu-web/src/test/java/org/apache/shenyu/web/filter/HealthFilterTest.java b/shenyu-web/src/test/java/org/apache/shenyu/web/filter/HealthFilterTest.java
index d5fc156e2..376ee367a 100644
--- a/shenyu-web/src/test/java/org/apache/shenyu/web/filter/HealthFilterTest.java
+++ b/shenyu-web/src/test/java/org/apache/shenyu/web/filter/HealthFilterTest.java
@@ -25,6 +25,7 @@ import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
+import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@@ -51,25 +52,29 @@ public final class HealthFilterTest {
@BeforeEach
public void setUp() {
List<String> paths = new ArrayList<>();
- paths.add("/testFilterMatch");
- healthFilter = new HealthFilter(paths);
+ paths.add("/health_check");
+ paths.add("/actuator");
+ DispatcherHandler dispatcherHandler = mock(DispatcherHandler.class);
+ when(dispatcherHandler.handle(any())).thenReturn(Mono.empty());
+ healthFilter = new HealthFilter(dispatcherHandler, paths);
webFilterChain = mock(WebFilterChain.class);
when(webFilterChain.filter(any())).thenReturn(Mono.empty());
}
@Test
public void testDoMatcher() {
- ServerWebExchange webExchange =
- MockServerWebExchange.from(MockServerHttpRequest
- .post("http://localhost:8080/testFilterMatch"));
- Mono<Boolean> filter = healthFilter.doMatcher(webExchange, webFilterChain);
- StepVerifier.create(filter).expectNext(Boolean.TRUE).verifyComplete();
- }
-
- @Test
- public void testPathNull() {
- List<String> paths = new ArrayList<>();
- new HealthFilter(paths);
+ Mono<Boolean> health = healthFilter.doMatcher(MockServerWebExchange
+ .from(MockServerHttpRequest.post("http://localhost:8080/actuator/health")), webFilterChain);
+ StepVerifier.create(health).expectNext(Boolean.TRUE).verifyComplete();
+
+ Mono<Boolean> healthCheck = healthFilter.doMatcher(MockServerWebExchange
+ .from(MockServerHttpRequest.post("http://localhost:8080/health_check")), webFilterChain);
+ StepVerifier.create(healthCheck).expectNext(Boolean.TRUE).verifyComplete();
+
+ Mono<Boolean> readiness = healthFilter.doMatcher(MockServerWebExchange
+ .from(MockServerHttpRequest.post("http://localhost:8080/actuator/health/readiness")), webFilterChain);
+ StepVerifier.create(readiness).expectNext(Boolean.TRUE).verifyComplete();
+
}
@Test
@@ -81,13 +86,4 @@ public final class HealthFilterTest {
StepVerifier.create(filter).expectNext(Boolean.FALSE).verifyComplete();
}
- @Test
- public void testDoFilter() {
- ServerWebExchange webExchange =
- MockServerWebExchange.from(MockServerHttpRequest
- .post("http://localhost:8080/"));
- Mono<Void> filter = healthFilter.doFilter(webExchange);
- StepVerifier.create(filter).verifyComplete();
- }
-
}