From cdd8d6ff6c4b29a53c95289e37a8a7f938f7b847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=8E=89=E6=A1=94?= Date: Tue, 8 Oct 2019 15:14:35 +0900 Subject: [PATCH] Support URL exclusion using UrlCleaner in Spring WebFlux adapter (#1049) --- .../sentinel-spring-webflux-adapter/README.md | 2 +- .../spring/webflux/SentinelWebFluxFilter.java | 22 +++++++++---------- .../SentinelWebFluxIntegrationTest.java | 22 ++++++++++++++++++- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/README.md b/sentinel-adapter/sentinel-spring-webflux-adapter/README.md index ed47f5d7..158937fe 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/README.md +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/README.md @@ -50,7 +50,7 @@ public class WebFluxConfig { You can register various customized callback in `WebFluxCallbackManager`: - `setBlockHandler`: register a customized `BlockRequestHandler` to handle the blocked request. The default implementation is `DefaultBlockRequestHandler`, which returns default message like `Blocked by Sentinel: FlowException`. -- `setUrlCleaner`: used for normalization of URL. The function type is `(ServerWebExchange, String) → String`, which means `(webExchange, originalUrl) → finalUrl`. +- `setUrlCleaner`: used for normalization of URL. The function type is `(ServerWebExchange, String) → String`, which means `(webExchange, originalUrl) → finalUrl`, if the finalUrl is `"""` or `null`, the URLs will be excluded (since Sentinel 1.7.0).. - `setRequestOriginParser`: used to resolve the origin from the HTTP request. The function type is `ServerWebExchange → String`. You can also refer to the demo: [sentinel-demo-spring-webflux](https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-spring-webflux). \ No newline at end of file diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxFilter.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxFilter.java index b83767d2..0a776364 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxFilter.java +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxFilter.java @@ -22,6 +22,7 @@ import com.alibaba.csp.sentinel.adapter.reactor.ContextConfig; import com.alibaba.csp.sentinel.adapter.reactor.EntryConfig; import com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer; import com.alibaba.csp.sentinel.adapter.spring.webflux.callback.WebFluxCallbackManager; +import com.alibaba.csp.sentinel.util.StringUtil; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; @@ -36,24 +37,23 @@ public class SentinelWebFluxFilter implements WebFilter { @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - return chain.filter(exchange) - .transform(buildSentinelTransformer(exchange)); - } - - private SentinelReactorTransformer buildSentinelTransformer(ServerWebExchange exchange) { // Maybe we can get the URL pattern elsewhere via: // exchange.getAttributeOrDefault(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, path) - String path = exchange.getRequest().getPath().value(); - String finalPath = Optional.ofNullable(WebFluxCallbackManager.getUrlCleaner()) - .map(f -> f.apply(exchange, path)) - .orElse(path); + + String finalPath = WebFluxCallbackManager.getUrlCleaner().apply(exchange, path); + if (StringUtil.isEmpty(finalPath)) { + return chain.filter(exchange); + } + return chain.filter(exchange).transform(buildSentinelTransformer(exchange, finalPath)); + } + + private SentinelReactorTransformer buildSentinelTransformer(ServerWebExchange exchange, String finalPath) { String origin = Optional.ofNullable(WebFluxCallbackManager.getRequestOriginParser()) .map(f -> f.apply(exchange)) .orElse(EMPTY_ORIGIN); - return new SentinelReactorTransformer<>( - new EntryConfig(finalPath, EntryType.IN, new ContextConfig(finalPath, origin))); + return new SentinelReactorTransformer<>(new EntryConfig(finalPath, EntryType.IN, new ContextConfig(finalPath, origin))); } private static final String EMPTY_ORIGIN = ""; diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxIntegrationTest.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxIntegrationTest.java index 91d7b923..2e0ec9e4 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxIntegrationTest.java +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxIntegrationTest.java @@ -101,6 +101,26 @@ public class SentinelWebFluxIntegrationTest { WebFluxCallbackManager.resetUrlCleaner(); } + @Test + public void testCustomizedIgnoreUrlCleaner() throws Exception { + final String fooPrefix = "/foo/"; + String url1 = fooPrefix + 1; + WebFluxCallbackManager.setUrlCleaner(((exchange, originUrl) -> { + if (originUrl.startsWith(fooPrefix)) { + return ""; + } + return originUrl; + })); + this.webClient.get() + .uri(url1) + .exchange() + .expectStatus().isOk() + .expectBody(String.class).isEqualTo("Hello 1"); + + assertNull(ClusterBuilderSlot.getClusterNode(url1)); + WebFluxCallbackManager.resetUrlCleaner(); + } + @Test public void testCustomizedBlockRequestHandler() throws Exception { String url = "/error"; @@ -166,4 +186,4 @@ public class SentinelWebFluxIntegrationTest { FlowRuleManager.loadRules(new ArrayList<>()); ClusterBuilderSlot.resetClusterNodes(); } -} \ No newline at end of file +}