From 1baac7783db76e6087a46c57a6612b3e78bad20b Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Tue, 23 Apr 2019 18:46:58 +0800 Subject: [PATCH] Refactor and improve Sentinel Zuul Adapter - Now the adapter is based-on sentinel-api-gateway-adapter-common and supports both proxyId and customized APIs Signed-off-by: Eric Zhao --- .../sentinel-zuul-adapter/README.md | 87 ++++++---- .../sentinel-zuul-adapter/pom.xml | 19 +++ .../zuul/RequestContextItemParser.java | 47 ++++++ .../api/ZuulApiDefinitionChangeObserver.java | 33 ++++ .../api/ZuulGatewayApiMatcherManager.java | 69 ++++++++ .../api/matcher/RequestContextApiMatcher.java | 72 ++++++++ .../api/route/PrefixRoutePathMatcher.java | 55 ++++++ .../zuul/api/route/RegexRoutePathMatcher.java | 49 ++++++ .../zuul/api/route/ZuulRouteMatchers.java | 55 ++++++ .../callback}/DefaultRequestOriginParser.java | 3 +- .../zuul/callback}/RequestOriginParser.java | 2 +- .../callback/ZuulGatewayCallbackManager.java | 38 +++++ .../zuul/constants/ZuulConstant.java | 13 +- .../zuul/fallback/BlockResponse.java | 7 +- .../DefaultBlockFallbackProvider.java | 4 +- .../fallback/ZuulBlockFallbackManager.java | 7 +- .../fallback/ZuulBlockFallbackProvider.java | 2 +- .../zuul/filters/SentinelEntryUtils.java | 66 ++++++++ .../zuul/filters/SentinelZuulErrorFilter.java | 75 +++++++++ .../zuul/filters/SentinelZuulPostFilter.java | 66 ++++++++ .../zuul/filters/SentinelZuulPreFilter.java | 159 ++++++++++++++++++ .../zuul/fallback/DefaultUrlCleaner.java | 27 --- .../adapter/zuul/fallback/UrlCleaner.java | 31 ---- .../zuul/filters/AbstractSentinelFilter.java | 46 ----- .../zuul/filters/SentinelErrorFilter.java | 81 --------- .../zuul/filters/SentinelPostFilter.java | 60 ------- .../zuul/filters/SentinelPreFilter.java | 112 ------------ .../properties/SentinelZuulProperties.java | 80 --------- .../adapter/zuul/util/FilterUtil.java | 157 ----------------- ...way.common.api.ApiDefinitionChangeObserver | 1 + .../ZuulBlockFallbackManagerTest.java | 6 +- .../ZuulBlockFallbackProviderTest.java | 6 +- .../filters/SentinelZuulErrorFilterTest.java} | 25 ++- .../filters/SentinelZuulPostFilterTest.java} | 17 +- .../filters/SentinelZuulPreFilterTest.java | 61 +++++++ .../zuul/filters/SentinelPreFilterTest.java | 106 ------------ 36 files changed, 968 insertions(+), 776 deletions(-) create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/RequestContextItemParser.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/ZuulApiDefinitionChangeObserver.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/ZuulGatewayApiMatcherManager.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/matcher/RequestContextApiMatcher.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/PrefixRoutePathMatcher.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/RegexRoutePathMatcher.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/ZuulRouteMatchers.java rename sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/{zuul/fallback => gateway/zuul/callback}/DefaultRequestOriginParser.java (79%) rename sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/{zuul/fallback => gateway/zuul/callback}/RequestOriginParser.java (94%) create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/ZuulGatewayCallbackManager.java rename sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/{ => gateway}/zuul/constants/ZuulConstant.java (80%) rename sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/{ => gateway}/zuul/fallback/BlockResponse.java (93%) rename sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/{ => gateway}/zuul/fallback/DefaultBlockFallbackProvider.java (85%) rename sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/{ => gateway}/zuul/fallback/ZuulBlockFallbackManager.java (88%) rename sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/{ => gateway}/zuul/fallback/ZuulBlockFallbackProvider.java (95%) create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelEntryUtils.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulErrorFilter.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPostFilter.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPreFilter.java delete mode 100755 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultUrlCleaner.java delete mode 100755 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/UrlCleaner.java delete mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/AbstractSentinelFilter.java delete mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelErrorFilter.java delete mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPostFilter.java delete mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPreFilter.java delete mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/properties/SentinelZuulProperties.java delete mode 100755 sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/util/FilterUtil.java create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinitionChangeObserver rename sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/{ => gateway}/zuul/fallback/ZuulBlockFallbackManagerTest.java (94%) rename sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/{ => gateway}/zuul/fallback/ZuulBlockFallbackProviderTest.java (94%) rename sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/{zuul/filters/SentinelErrorFilterTest.java => gateway/zuul/filters/SentinelZuulErrorFilterTest.java} (51%) rename sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/{zuul/filters/SentinelPostFilterTest.java => gateway/zuul/filters/SentinelZuulPostFilterTest.java} (55%) create mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPreFilterTest.java delete mode 100644 sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPreFilterTest.java diff --git a/sentinel-adapter/sentinel-zuul-adapter/README.md b/sentinel-adapter/sentinel-zuul-adapter/README.md index f86b4406..9814a948 100755 --- a/sentinel-adapter/sentinel-zuul-adapter/README.md +++ b/sentinel-adapter/sentinel-zuul-adapter/README.md @@ -1,6 +1,7 @@ # Sentinel Zuul Adapter -Sentinel Zuul Adapter provides **ServiceId level** and **API Path level** flow control for Zuul gateway service. +Sentinel Zuul Adapter provides **route level** and **customized API level** +flow control for Zuul API Gateway. > *Note*: this adapter only support Zuul 1.x. @@ -18,54 +19,68 @@ Sentinel Zuul Adapter provides **ServiceId level** and **API Path level** flow c 2. Register filters -```java -// get registry -final FilterRegistry r = FilterRegistry.instance(); -// this is property config. set filter enable -SentinelZuulProperties properties = new SentinelZuulProperties(); -properties.setEnabled(true); -// set url cleaner, here use default -DefaultUrlCleaner defaultUrlCleaner = new DefaultUrlCleaner(); -// set origin parser. here use default -DefaultRequestOriginParser defaultRequestOriginParser = new DefaultRequestOriginParser(); +For Spring Cloud Zuul users, we only need to inject the three filters in Spring configuration class like this: -// register filters. you must register all three filters. -SentinelPreFilter sentinelPreFilter = new SentinelPreFilter(properties, defaultUrlCleaner, defaultRequestOriginParser); -r.put("sentinelPreFilter", sentinelPreFilter); -SentinelPostFilter postFilter = new SentinelPostFilter(properties); -r.put("sentinelPostFilter", postFilter); -SentinelErrorFilter errorFilter = new SentinelErrorFilter(properties); -r.put("sentinelErrorFilter", errorFilter); +```java +@Configuration +public class ZuulConfig { + + @Bean + public ZuulFilter sentinelZuulPreFilter() { + // We can provider the filter order here. + return new SentinelZuulPreFilter(10000); + } + + @Bean + public ZuulFilter sentinelZuulPostFilter() { + return new SentinelZuulPostFilter(1000); + } + + @Bean + public ZuulFilter sentinelZuulErrorFilter() { + return new SentinelZuulErrorFilter(-1); + } +} +``` + +For original Zuul users: + +```java +// Get filter registry +final FilterRegistry r = FilterRegistry.instance(); + +// We need to register all three filters. +SentinelZuulPreFilter sentinelPreFilter = new SentinelZuulPreFilter(); +r.put("sentinelZuulPreFilter", sentinelPreFilter); +SentinelZuulPostFilter postFilter = new SentinelZuulPostFilter(); +r.put("sentinelZuulPostFilter", postFilter); +SentinelZuulErrorFilter errorFilter = new SentinelZuulErrorFilter(); +r.put("sentinelZuulErrorFilter", errorFilter); ``` ## How it works -As Zuul run as per thread per connection block model, we add filters around `route Filter` to trace sentinel statistics. +As Zuul run as per thread per connection block model, we add filters around route filter to trace Sentinel statistics. -- `SentinelPreFilter`: Get an entry of resource, the first order is **ServiceId** (the key in RequestContext is `serviceId`, this can set in own custom filter), then **API Path**. -- `SentinelPostFilter`: When success response, exit entry. -- `SentinelPreFilter`: When an `Exception` caught, trace the exception and exit context. +- `SentinelZuulPreFilter`: This pre-filter will regard all proxy ID (`proxy` in `RequestContext`) and all customized API as resources. When a `BlockException` caught, the filter will try to find a fallback to execute. +- `SentinelZuulPostFilter`: When the response has no exception caught, the post filter will complete the entries. +- `SentinelZuulPreFilter`: When an exception is caught, the filter will trace the exception and complete the entries. -The order of filters can be changed in property. +The order of filters can be changed via the constructor. The invocation chain resembles this: ```bash -EntranceNode: machine-root(t:3 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) --EntranceNode: coke(t:2 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) ---coke(t:2 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) ----/coke/coke(t:0 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) --EntranceNode: sentinel_default_context(t:0 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) --EntranceNode: book(t:1 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) ---book(t:1 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) ----/book/coke(t:0 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) +-EntranceNode: sentinel_gateway_context$$route$$another-route-b(t:0 pq:0.0 bq:0.0 tq:0.0 rt:0.0 prq:0.0 1mp:8 1mb:1 1mt:9) +--another-route-b(t:0 pq:0.0 bq:0.0 tq:0.0 rt:0.0 prq:0.0 1mp:4 1mb:1 1mt:5) +--another_customized_api(t:0 pq:0.0 bq:0.0 tq:0.0 rt:0.0 prq:0.0 1mp:4 1mb:0 1mt:4) +-EntranceNode: sentinel_gateway_context$$route$$my-route-1(t:0 pq:0.0 bq:0.0 tq:0.0 rt:0.0 prq:0.0 1mp:6 1mb:0 1mt:6) +--my-route-1(t:0 pq:0.0 bq:0.0 tq:0.0 rt:0.0 prq:0.0 1mp:2 1mb:0 1mt:2) +--some_customized_api(t:0 pq:0.0 bq:0.0 tq:0.0 rt:0.0 prq:0.0 1mp:2 1mb:0 1mt:2) ``` -- `book` and `coke` are serviceId. -- `/book/coke` is api path, the real API path is `/coke`. - ## Integration with Sentinel Dashboard 1. Start [Sentinel Dashboard](https://github.com/alibaba/Sentinel/wiki/Dashboard). @@ -76,7 +91,7 @@ EntranceNode: machine-root(t:3 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0) You can implement `SentinelFallbackProvider` to define your own fallback provider when Sentinel `BlockException` is thrown. The default fallback provider is `DefaultBlockFallbackProvider`. -By default fallback route is `ServiveId + URI PATH`, example `/book/coke`, first `book` is serviceId, `/coke` is URI PATH, so that both can be needed. +By default fallback route is proxy ID (or customized API name). Here is an example: @@ -90,7 +105,7 @@ public class MyBlockFallbackProvider implements ZuulBlockFallbackProvider { // you can define root as service level @Override public String getRoute() { - return "/coke/coke"; + return "my-route"; } @Override diff --git a/sentinel-adapter/sentinel-zuul-adapter/pom.xml b/sentinel-adapter/sentinel-zuul-adapter/pom.xml index 41228d52..68f67b8d 100755 --- a/sentinel-adapter/sentinel-zuul-adapter/pom.xml +++ b/sentinel-adapter/sentinel-zuul-adapter/pom.xml @@ -21,6 +21,11 @@ com.alibaba.csp sentinel-core + + com.alibaba.csp + sentinel-api-gateway-adapter-common + + javax.servlet javax.servlet-api @@ -39,6 +44,20 @@ + + + org.springframework + spring-core + 4.3.20.RELEASE + provided + + + + org.springframework.cloud + spring-cloud-starter-netflix-zuul + 1.4.6.RELEASE + test + junit diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/RequestContextItemParser.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/RequestContextItemParser.java new file mode 100644 index 00000000..c1e081e8 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/RequestContextItemParser.java @@ -0,0 +1,47 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul; + +import com.alibaba.csp.sentinel.adapter.gateway.common.param.RequestItemParser; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public class RequestContextItemParser implements RequestItemParser { + + @Override + public String getPath(RequestContext requestContext) { + return requestContext.getRequest().getServletPath(); + } + + @Override + public String getRemoteAddress(RequestContext requestContext) { + return requestContext.getRequest().getRemoteAddr(); + } + + @Override + public String getHeader(RequestContext requestContext, String headerKey) { + return requestContext.getRequest().getHeader(headerKey); + } + + @Override + public String getUrlParam(RequestContext requestContext, String paramName) { + return requestContext.getRequest().getParameter(paramName); + } +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/ZuulApiDefinitionChangeObserver.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/ZuulApiDefinitionChangeObserver.java new file mode 100644 index 00000000..a53c9a4e --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/ZuulApiDefinitionChangeObserver.java @@ -0,0 +1,33 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul.api; + +import java.util.Set; + +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinitionChangeObserver; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public class ZuulApiDefinitionChangeObserver implements ApiDefinitionChangeObserver { + + @Override + public void onChange(Set apiDefinitions) { + ZuulGatewayApiMatcherManager.loadApiDefinitions(apiDefinitions); + } +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/ZuulGatewayApiMatcherManager.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/ZuulGatewayApiMatcherManager.java new file mode 100644 index 00000000..b9ba7bc5 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/ZuulGatewayApiMatcherManager.java @@ -0,0 +1,69 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul.api; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.api.matcher.RequestContextApiMatcher; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public final class ZuulGatewayApiMatcherManager { + + private static final Map API_MATCHER_MAP = new ConcurrentHashMap<>(); + + public static Map getApiMatcherMap() { + return Collections.unmodifiableMap(API_MATCHER_MAP); + } + + public static RequestContextApiMatcher getMatcher(final String apiName) { + if (apiName == null) { + return null; + } + return API_MATCHER_MAP.get(apiName); + } + + public static Set getApiDefinitionSet() { + Set set = new HashSet<>(); + for (RequestContextApiMatcher matcher : API_MATCHER_MAP.values()) { + set.add(matcher.getApiDefinition()); + } + return set; + } + + static synchronized void loadApiDefinitions(/*@Valid*/ Set definitions) { + if (definitions == null || definitions.isEmpty()) { + API_MATCHER_MAP.clear(); + return; + } + for (ApiDefinition definition : definitions) { + addApiDefinition(definition); + } + } + + static void addApiDefinition(ApiDefinition definition) { + API_MATCHER_MAP.put(definition.getApiName(), new RequestContextApiMatcher(definition)); + } + + private ZuulGatewayApiMatcherManager() {} +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/matcher/RequestContextApiMatcher.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/matcher/RequestContextApiMatcher.java new file mode 100644 index 00000000..90718db1 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/matcher/RequestContextApiMatcher.java @@ -0,0 +1,72 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul.api.matcher; + +import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.matcher.AbstractApiMatcher; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.api.route.ZuulRouteMatchers; +import com.alibaba.csp.sentinel.util.StringUtil; +import com.alibaba.csp.sentinel.util.function.Predicate; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public class RequestContextApiMatcher extends AbstractApiMatcher { + + public RequestContextApiMatcher(ApiDefinition apiDefinition) { + super(apiDefinition); + } + + @Override + protected void initializeMatchers() { + if (apiDefinition.getPredicateItems() != null) { + for (ApiPredicateItem item : apiDefinition.getPredicateItems()) { + Predicate predicate = fromApiPredicate(item); + if (predicate != null) { + matchers.add(predicate); + } + } + } + } + + private Predicate fromApiPredicate(/*@NonNull*/ ApiPredicateItem item) { + if (item instanceof ApiPathPredicateItem) { + return fromApiPathPredicate((ApiPathPredicateItem)item); + } + return null; + } + + private Predicate fromApiPathPredicate(/*@Valid*/ ApiPathPredicateItem item) { + String pattern = item.getPattern(); + if (StringUtil.isBlank(pattern)) { + return null; + } + switch (item.getMatchStrategy()) { + case SentinelGatewayConstants.PARAM_MATCH_STRATEGY_REGEX: + return ZuulRouteMatchers.regexPath(pattern); + case SentinelGatewayConstants.PARAM_MATCH_STRATEGY_PREFIX: + return ZuulRouteMatchers.antPath(pattern); + default: + return ZuulRouteMatchers.exactPath(pattern); + } + } +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/PrefixRoutePathMatcher.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/PrefixRoutePathMatcher.java new file mode 100644 index 00000000..21e636e5 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/PrefixRoutePathMatcher.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul.api.route; + +import com.alibaba.csp.sentinel.util.AssertUtil; +import com.alibaba.csp.sentinel.util.function.Predicate; + +import com.netflix.zuul.context.RequestContext; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public class PrefixRoutePathMatcher implements Predicate { + + private final String pattern; + + private final PathMatcher pathMatcher; + private final boolean canMatch; + + public PrefixRoutePathMatcher(String pattern) { + AssertUtil.assertNotBlank(pattern, "pattern cannot be blank"); + this.pattern = pattern; + this.pathMatcher = new AntPathMatcher(); + this.canMatch = pathMatcher.isPattern(pattern); + } + + @Override + public boolean test(RequestContext context) { + String path = context.getRequest().getServletPath(); + if (canMatch) { + return pathMatcher.match(pattern, path); + } + return false; + } + + public String getPattern() { + return pattern; + } +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/RegexRoutePathMatcher.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/RegexRoutePathMatcher.java new file mode 100644 index 00000000..daf1310e --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/RegexRoutePathMatcher.java @@ -0,0 +1,49 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul.api.route; + +import java.util.regex.Pattern; + +import com.alibaba.csp.sentinel.util.AssertUtil; +import com.alibaba.csp.sentinel.util.function.Predicate; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public class RegexRoutePathMatcher implements Predicate { + + private final String pattern; + private final Pattern regex; + + public RegexRoutePathMatcher(String pattern) { + AssertUtil.assertNotBlank(pattern, "pattern cannot be blank"); + this.pattern = pattern; + this.regex = Pattern.compile(pattern); + } + + @Override + public boolean test(RequestContext context) { + String path = context.getRequest().getServletPath(); + return regex.matcher(path).matches(); + } + + public String getPattern() { + return pattern; + } +} \ No newline at end of file diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/ZuulRouteMatchers.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/ZuulRouteMatchers.java new file mode 100644 index 00000000..970c30e1 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/api/route/ZuulRouteMatchers.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul.api.route; + +import com.alibaba.csp.sentinel.util.function.Predicate; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public final class ZuulRouteMatchers { + + public static Predicate all() { + return new Predicate() { + @Override + public boolean test(RequestContext requestContext) { + return true; + } + }; + } + + public static Predicate antPath(String pathPattern) { + return new PrefixRoutePathMatcher(pathPattern); + } + + public static Predicate exactPath(final String path) { + return new Predicate() { + @Override + public boolean test(RequestContext exchange) { + return exchange.getRequest().getServletPath().equals(path); + } + }; + } + + public static Predicate regexPath(String pathPattern) { + return new RegexRoutePathMatcher(pathPattern); + } + + private ZuulRouteMatchers() {} +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultRequestOriginParser.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/DefaultRequestOriginParser.java similarity index 79% rename from sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultRequestOriginParser.java rename to sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/DefaultRequestOriginParser.java index 45dba4d7..e2d07843 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultRequestOriginParser.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/DefaultRequestOriginParser.java @@ -1,4 +1,4 @@ -package com.alibaba.csp.sentinel.adapter.zuul.fallback; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.callback; import javax.servlet.http.HttpServletRequest; @@ -6,6 +6,7 @@ import javax.servlet.http.HttpServletRequest; * @author tiger */ public class DefaultRequestOriginParser implements RequestOriginParser { + @Override public String parseOrigin(HttpServletRequest request) { return ""; diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/RequestOriginParser.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/RequestOriginParser.java similarity index 94% rename from sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/RequestOriginParser.java rename to sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/RequestOriginParser.java index 20f6d744..caacd0a0 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/RequestOriginParser.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/RequestOriginParser.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.fallback; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.callback; import javax.servlet.http.HttpServletRequest; diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/ZuulGatewayCallbackManager.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/ZuulGatewayCallbackManager.java new file mode 100644 index 00000000..03bfa246 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/callback/ZuulGatewayCallbackManager.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul.callback; + +import com.alibaba.csp.sentinel.util.AssertUtil; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public final class ZuulGatewayCallbackManager { + + private static volatile RequestOriginParser originParser = new DefaultRequestOriginParser(); + + public static RequestOriginParser getOriginParser() { + return originParser; + } + + public static void setOriginParser(RequestOriginParser originParser) { + AssertUtil.notNull(originParser, "originParser cannot be null"); + ZuulGatewayCallbackManager.originParser = originParser; + } + + private ZuulGatewayCallbackManager() {} +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/constants/ZuulConstant.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/constants/ZuulConstant.java similarity index 80% rename from sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/constants/ZuulConstant.java rename to sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/constants/ZuulConstant.java index 244fbf4a..30428053 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/constants/ZuulConstant.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/constants/ZuulConstant.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.constants; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.constants; import com.netflix.zuul.ZuulFilter; @@ -27,6 +27,10 @@ public class ZuulConstant { * Zuul {@link com.netflix.zuul.context.RequestContext} key for use in load balancer. */ public static final String SERVICE_ID_KEY = "serviceId"; + /** + * Zuul {@link com.netflix.zuul.context.RequestContext} key for proxying (route ID). + */ + public static final String PROXY_ID_KEY = "proxy"; /** * {@link ZuulFilter#filterType()} error type. @@ -58,5 +62,12 @@ public class ZuulConstant { */ public static final String ZUUL_DEFAULT_CONTEXT = "zuul_default_context"; + /** + * Zuul context key for keeping Sentinel entries. + * + * @since 1.6.0 + */ + public static final String ZUUL_CTX_SENTINEL_ENTRIES_KEY = "_sentinel_entries"; + private ZuulConstant(){} } diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/BlockResponse.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/BlockResponse.java similarity index 93% rename from sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/BlockResponse.java rename to sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/BlockResponse.java index 6fd617fd..435850fc 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/BlockResponse.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/BlockResponse.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.fallback; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback; /** * Fall back response for {@link com.alibaba.csp.sentinel.slots.block.BlockException} @@ -22,7 +22,12 @@ package com.alibaba.csp.sentinel.adapter.zuul.fallback; * @author tiger */ public class BlockResponse { + + /** + * HTTP status code. + */ private int code; + private String message; private String route; diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultBlockFallbackProvider.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/DefaultBlockFallbackProvider.java similarity index 85% rename from sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultBlockFallbackProvider.java rename to sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/DefaultBlockFallbackProvider.java index 432db872..1bd94034 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultBlockFallbackProvider.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/DefaultBlockFallbackProvider.java @@ -14,9 +14,8 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.fallback; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback; -import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.slots.block.BlockException; /** @@ -33,7 +32,6 @@ public class DefaultBlockFallbackProvider implements ZuulBlockFallbackProvider { @Override public BlockResponse fallbackResponse(String route, Throwable cause) { - RecordLog.info(String.format("[Sentinel DefaultBlockFallbackProvider] Run fallback route: %s", route)); if (cause instanceof BlockException) { return new BlockResponse(429, "Sentinel block exception", route); } else { diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackManager.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackManager.java similarity index 88% rename from sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackManager.java rename to sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackManager.java index 2760acff..18701762 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackManager.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackManager.java @@ -14,11 +14,13 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.fallback; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback; import java.util.HashMap; import java.util.Map; +import com.alibaba.csp.sentinel.util.AssertUtil; + /** * This provide fall back class manager. * @@ -26,7 +28,7 @@ import java.util.Map; */ public class ZuulBlockFallbackManager { - private static Map fallbackProviderCache = new HashMap(); + private static Map fallbackProviderCache = new HashMap<>(); private static ZuulBlockFallbackProvider defaultFallbackProvider = new DefaultBlockFallbackProvider(); @@ -34,6 +36,7 @@ public class ZuulBlockFallbackManager { * Register special provider for different route. */ public static synchronized void registerProvider(ZuulBlockFallbackProvider provider) { + AssertUtil.notNull(provider, "fallback provider cannot be null"); String route = provider.getRoute(); if ("*".equals(route) || route == null) { defaultFallbackProvider = provider; diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackProvider.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackProvider.java similarity index 95% rename from sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackProvider.java rename to sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackProvider.java index e6b3acb0..766220eb 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackProvider.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackProvider.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.fallback; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback; /** * This interface is compatible for different spring cloud version. diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelEntryUtils.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelEntryUtils.java new file mode 100644 index 00000000..8c93a1b7 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelEntryUtils.java @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.adapter.gateway.zuul.filters; + +import java.util.Deque; + +import com.alibaba.csp.sentinel.AsyncEntry; +import com.alibaba.csp.sentinel.Tracer; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant; +import com.alibaba.csp.sentinel.context.ContextUtil; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +final class SentinelEntryUtils { + + @SuppressWarnings("unchecked") + static void tryExitFromCurrentContext() { + RequestContext ctx = RequestContext.getCurrentContext(); + if (ctx.containsKey(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY)) { + Deque asyncEntries = (Deque) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); + AsyncEntry entry; + while (!asyncEntries.isEmpty()) { + entry = asyncEntries.pop(); + entry.exit(); + } + ctx.remove(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); + } + + ContextUtil.exit(); + } + + @SuppressWarnings("unchecked") + static void tryTraceExceptionThenExitFromCurrentContext(Throwable t) { + RequestContext ctx = RequestContext.getCurrentContext(); + if (ctx.containsKey(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY)) { + Deque asyncEntries = (Deque) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); + AsyncEntry entry; + while (!asyncEntries.isEmpty()) { + entry = asyncEntries.pop(); + Tracer.traceEntry(t, entry); + entry.exit(); + } + ctx.remove(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); + } + ContextUtil.exit(); + } + + private SentinelEntryUtils() {} +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulErrorFilter.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulErrorFilter.java new file mode 100644 index 00000000..2e1d856b --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulErrorFilter.java @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.csp.sentinel.adapter.gateway.zuul.filters; + +import com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant; +import com.alibaba.csp.sentinel.log.RecordLog; +import com.alibaba.csp.sentinel.slots.block.BlockException; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; +import com.netflix.zuul.exception.ZuulException; + +/** + * This filter track routing exception and exit entry; + * + * @author tiger + * @author Eric Zhao + */ +public class SentinelZuulErrorFilter extends ZuulFilter { + + private final int order; + + public SentinelZuulErrorFilter() { + this(-1); + } + + public SentinelZuulErrorFilter(int order) { + this.order = order; + } + + @Override + public String filterType() { + return ZuulConstant.ERROR_TYPE; + } + + @Override + public boolean shouldFilter() { + RequestContext ctx = RequestContext.getCurrentContext(); + return ctx.getThrowable() != null; + } + + @Override + public int filterOrder() { + return order; + } + + @Override + public Object run() throws ZuulException { + RequestContext ctx = RequestContext.getCurrentContext(); + Throwable throwable = ctx.getThrowable(); + if (throwable != null) { + if (!BlockException.isBlockException(throwable)) { + // Trace exception for each entry and exit entries in order. + // The entries can be retrieved from the request context. + SentinelEntryUtils.tryTraceExceptionThenExitFromCurrentContext(throwable); + RecordLog.info("[SentinelZuulErrorFilter] Trace error cause", throwable.getCause()); + } + } + return null; + } +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPostFilter.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPostFilter.java new file mode 100644 index 00000000..03cdddbf --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPostFilter.java @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.csp.sentinel.adapter.gateway.zuul.filters; + +import com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.exception.ZuulException; + +import static com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant.SEND_RESPONSE_FILTER_ORDER; + +/** + * This filter will mark complete and exit {@link com.alibaba.csp.sentinel.Entry}. + * + * @author tiger + * @author Eric Zhao + */ +public class SentinelZuulPostFilter extends ZuulFilter { + + private final int order; + + public SentinelZuulPostFilter() { + this(SEND_RESPONSE_FILTER_ORDER); + } + + public SentinelZuulPostFilter(int order) { + this.order = order; + } + + @Override + public String filterType() { + return ZuulConstant.POST_TYPE; + } + + @Override + public int filterOrder() { + return order; + } + + @Override + public boolean shouldFilter() { + return true; + } + + @Override + public Object run() throws ZuulException { + // Exit the entries in order. + // The entries can be retrieved from the request context. + SentinelEntryUtils.tryExitFromCurrentContext(); + return null; + } +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPreFilter.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPreFilter.java new file mode 100644 index 00000000..da6a8b82 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPreFilter.java @@ -0,0 +1,159 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.csp.sentinel.adapter.gateway.zuul.filters; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashSet; +import java.util.Set; + +import com.alibaba.csp.sentinel.AsyncEntry; +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.adapter.gateway.common.param.GatewayParamParser; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.RequestContextItemParser; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.api.ZuulGatewayApiMatcherManager; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.api.matcher.RequestContextApiMatcher; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.callback.ZuulGatewayCallbackManager; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.BlockResponse; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackManager; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackProvider; +import com.alibaba.csp.sentinel.context.ContextUtil; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.util.StringUtil; +import com.alibaba.csp.sentinel.util.function.Predicate; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; +import com.netflix.zuul.exception.ZuulException; + +import javax.servlet.http.HttpServletRequest; + +import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*; + +/** + * This pre-filter will regard all {@code proxyId} and all customized API as resources. + * When a BlockException caught, the filter will try to find a fallback to execute. + * + * @author tiger + * @author Eric Zhao + */ +public class SentinelZuulPreFilter extends ZuulFilter { + + private final int order; + + private final GatewayParamParser paramParser = new GatewayParamParser<>( + new RequestContextItemParser()); + + public SentinelZuulPreFilter() { + this(10000); + } + + public SentinelZuulPreFilter(int order) { + this.order = order; + } + + @Override + public String filterType() { + return ZuulConstant.PRE_TYPE; + } + + /** + * This run before route filter so we can get more accurate RT time. + */ + @Override + public int filterOrder() { + return order; + } + + @Override + public boolean shouldFilter() { + return true; + } + + private void doSentinelEntry(String resourceName, final int resType, RequestContext requestContext, + Deque asyncEntries) throws BlockException { + Object[] params = paramParser.parseParameterFor(resourceName, requestContext, + new Predicate() { + @Override + public boolean test(GatewayFlowRule r) { + return r.getResourceMode() == resType; + } + }); + AsyncEntry entry = SphU.asyncEntry(resourceName, EntryType.IN, 1, params); + asyncEntries.push(entry); + } + + @Override + public Object run() throws ZuulException { + RequestContext ctx = RequestContext.getCurrentContext(); + String origin = parseOrigin(ctx.getRequest()); + String routeId = (String)ctx.get(ZuulConstant.PROXY_ID_KEY); + + Deque asyncEntries = new ArrayDeque<>(); + String fallBackRoute = routeId; + try { + if (StringUtil.isNotBlank(routeId)) { + ContextUtil.enter(GATEWAY_CONTEXT_ROUTE_PREFIX + routeId, origin); + doSentinelEntry(routeId, RESOURCE_MODE_ROUTE_ID, ctx, asyncEntries); + } + + Set matchingApis = pickMatchingApiDefinitions(ctx); + if (!matchingApis.isEmpty() && ContextUtil.getContext() == null) { + ContextUtil.enter(ZuulConstant.ZUUL_DEFAULT_CONTEXT, origin); + } + for (String apiName : matchingApis) { + fallBackRoute = apiName; + doSentinelEntry(apiName, RESOURCE_MODE_CUSTOM_API_NAME, ctx, asyncEntries); + } + } catch (BlockException ex) { + ZuulBlockFallbackProvider zuulBlockFallbackProvider = ZuulBlockFallbackManager.getFallbackProvider( + fallBackRoute); + BlockResponse blockResponse = zuulBlockFallbackProvider.fallbackResponse(fallBackRoute, ex); + // Prevent routing from running + ctx.setRouteHost(null); + ctx.set(ZuulConstant.SERVICE_ID_KEY, null); + + // Set fallback response. + ctx.setResponseBody(blockResponse.toString()); + ctx.setResponseStatusCode(blockResponse.getCode()); + } finally { + // We don't exit the entry here. We need to exit the entries in post filter to record Rt correctly. + // So here the entries will be carried in the request context. + if (!asyncEntries.isEmpty()) { + ctx.put(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY, asyncEntries); + } + } + return null; + } + + private String parseOrigin(HttpServletRequest request) { + return ZuulGatewayCallbackManager.getOriginParser().parseOrigin(request); + } + + private Set pickMatchingApiDefinitions(RequestContext requestContext) { + Set apis = new HashSet<>(); + for (RequestContextApiMatcher matcher : ZuulGatewayApiMatcherManager.getApiMatcherMap().values()) { + if (matcher.test(requestContext)) { + apis.add(matcher.getApiName()); + } + } + return apis; + } +} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultUrlCleaner.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultUrlCleaner.java deleted file mode 100755 index 09780820..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/DefaultUrlCleaner.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.fallback; - -/*** - * @author tiger - */ -public class DefaultUrlCleaner implements UrlCleaner { - - @Override - public String clean(String originUrl) { - return originUrl; - } -} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/UrlCleaner.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/UrlCleaner.java deleted file mode 100755 index d6b9a33b..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/UrlCleaner.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.fallback; - -/*** - * @author tiger - */ -public interface UrlCleaner { - - /*** - *

Process the url. Some path variables should be handled and unified.

- *

e.g. collect_item_relation--10200012121-.html will be converted to collect_item_relation.html

- * - * @param originUrl original url - * @return processed url - */ - String clean(String originUrl); -} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/AbstractSentinelFilter.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/AbstractSentinelFilter.java deleted file mode 100644 index 0becdf53..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/AbstractSentinelFilter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.filters; - -import com.alibaba.csp.sentinel.adapter.zuul.properties.SentinelZuulProperties; -import com.alibaba.csp.sentinel.util.AssertUtil; -import com.netflix.zuul.ZuulFilter; - -/** - * Abstract class for sentinel filters. - * - * @author tiger - */ -public abstract class AbstractSentinelFilter extends ZuulFilter { - - private final SentinelZuulProperties sentinelZuulProperties; - - public SentinelZuulProperties getSentinelZuulProperties() { - return sentinelZuulProperties; - } - - public AbstractSentinelFilter(SentinelZuulProperties sentinelZuulProperties) { - AssertUtil.notNull(sentinelZuulProperties,"SentinelZuulProperties can not be null"); - this.sentinelZuulProperties = sentinelZuulProperties; - } - - @Override - public boolean shouldFilter() { - return sentinelZuulProperties.isEnabled(); - } - -} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelErrorFilter.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelErrorFilter.java deleted file mode 100644 index dc192dba..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelErrorFilter.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.filters; - -import com.alibaba.csp.sentinel.Tracer; -import com.alibaba.csp.sentinel.adapter.zuul.properties.SentinelZuulProperties; -import com.alibaba.csp.sentinel.context.ContextUtil; -import com.alibaba.csp.sentinel.log.RecordLog; -import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.netflix.zuul.context.RequestContext; -import com.netflix.zuul.exception.ZuulException; - -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.ERROR_TYPE; - -/** - * This filter track routing exception and exit entry; - * - * @author tiger - */ -public class SentinelErrorFilter extends AbstractSentinelFilter { - - public SentinelErrorFilter(SentinelZuulProperties sentinelZuulProperties) { - super(sentinelZuulProperties); - } - - @Override - public String filterType() { - return ERROR_TYPE; - } - - @Override - public boolean shouldFilter() { - RequestContext ctx = RequestContext.getCurrentContext(); - return getSentinelZuulProperties().isEnabled() && ctx.getThrowable() != null; - } - - @Override - public int filterOrder() { - return getSentinelZuulProperties().getOrder().getError(); - } - - /** - * Trace not {@link BlockException} ex. - * While loop will exit all entries, - * Case serviceId and URL entry twice in {@link SentinelPreFilter}. - * The ContextUtil.getContext().getCurEntry() will exit from inner to outer. - */ - @Override - public Object run() throws ZuulException { - try { - RequestContext ctx = RequestContext.getCurrentContext(); - Throwable throwable = ctx.getThrowable(); - if (throwable != null) { - if (!BlockException.isBlockException(throwable)) { - Tracer.trace(throwable.getCause()); - RecordLog.info("[Sentinel Error Filter] Trace cause", throwable.getCause()); - } - } - } finally { - while (ContextUtil.getContext() != null && ContextUtil.getContext().getCurEntry() != null) { - ContextUtil.getContext().getCurEntry().exit(); - } - ContextUtil.exit(); - } - return null; - } -} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPostFilter.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPostFilter.java deleted file mode 100644 index 9159489c..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPostFilter.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.filters; - -import com.alibaba.csp.sentinel.adapter.zuul.properties.SentinelZuulProperties; -import com.alibaba.csp.sentinel.context.ContextUtil; -import com.alibaba.csp.sentinel.log.RecordLog; -import com.netflix.zuul.exception.ZuulException; - -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.POST_TYPE; - -/** - * This filter do success routing RT statistic and exit {@link com.alibaba.csp.sentinel.Entry} - * - * @author tiger - */ -public class SentinelPostFilter extends AbstractSentinelFilter { - - public SentinelPostFilter(SentinelZuulProperties sentinelZuulProperties) { - super(sentinelZuulProperties); - } - - @Override - public String filterType() { - return POST_TYPE; - } - - @Override - public int filterOrder() { - return getSentinelZuulProperties().getOrder().getPost(); - } - - /** - * While loop will exit all entries, - * Case serviceId and URL entry twice in {@link SentinelPreFilter}. - * The ContextUtil.getContext().getCurEntry() will exit from inner to outer. - */ - @Override - public Object run() throws ZuulException { - while (ContextUtil.getContext() != null && ContextUtil.getContext().getCurEntry() != null) { - ContextUtil.getContext().getCurEntry().exit(); - } - ContextUtil.exit(); - return null; - } -} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPreFilter.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPreFilter.java deleted file mode 100644 index 7ef2c787..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPreFilter.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.filters; - -import com.alibaba.csp.sentinel.EntryType; -import com.alibaba.csp.sentinel.SphU; -import com.alibaba.csp.sentinel.adapter.zuul.fallback.*; -import com.alibaba.csp.sentinel.adapter.zuul.properties.SentinelZuulProperties; -import com.alibaba.csp.sentinel.adapter.zuul.util.FilterUtil; -import com.alibaba.csp.sentinel.context.ContextUtil; -import com.alibaba.csp.sentinel.log.RecordLog; -import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.alibaba.csp.sentinel.util.AssertUtil; -import com.alibaba.csp.sentinel.util.StringUtil; -import com.netflix.zuul.context.RequestContext; -import com.netflix.zuul.exception.ZuulException; - -import javax.servlet.http.HttpServletRequest; - -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.PRE_TYPE; -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.SERVICE_ID_KEY; -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.ZUUL_DEFAULT_CONTEXT; - -/** - * This pre filter get an entry of resource,the first order is ServiceId, then API Path. - * When get a BlockException run fallback logic. - * - * @author tiger - */ -public class SentinelPreFilter extends AbstractSentinelFilter { - - private final UrlCleaner urlCleaner; - - private final RequestOriginParser requestOriginParser; - - public SentinelPreFilter(SentinelZuulProperties sentinelZuulProperties, - UrlCleaner urlCleaner, - RequestOriginParser requestOriginParser) { - super(sentinelZuulProperties); - AssertUtil.notNull(urlCleaner, "UrlCleaner can not be null"); - AssertUtil.notNull(requestOriginParser, "RequestOriginParser can not be null"); - this.urlCleaner = urlCleaner; - this.requestOriginParser = requestOriginParser; - } - - @Override - public String filterType() { - return PRE_TYPE; - } - - /** - * This run before route filter so we can get more accurate RT time. - */ - @Override - public int filterOrder() { - return getSentinelZuulProperties().getOrder().getPre(); - } - - @Override - public Object run() throws ZuulException { - RequestContext ctx = RequestContext.getCurrentContext(); - String origin = parseOrigin(ctx.getRequest()); - String serviceTarget = (String) ctx.get(SERVICE_ID_KEY); - // When serviceId blocked first get the service level fallback provider. - String fallBackRoute = serviceTarget; - try { - if (StringUtil.isNotEmpty(serviceTarget)) { - RecordLog.info(String.format("[Sentinel Pre Filter] Origin: %s enter ServiceId: %s", origin, serviceTarget)); - ContextUtil.enter(serviceTarget, origin); - SphU.entry(serviceTarget, EntryType.IN); - } else { - RecordLog.info("[Sentinel Pre Filter] ServiceId is empty"); - ContextUtil.enter(ZUUL_DEFAULT_CONTEXT, origin); - } - String uriTarget = FilterUtil.filterTarget(ctx.getRequest()); - // Clean and unify the URL. - // For REST APIs, you have to clean the URL (e.g. `/foo/1` and `/foo/2` -> `/foo/:id`), or - // the amount of context and resources will exceed the threshold. - uriTarget = urlCleaner.clean(uriTarget); - fallBackRoute = uriTarget; - RecordLog.info(String.format("[Sentinel Pre Filter] Origin: %s enter Uri Path: %s", origin, uriTarget)); - SphU.entry(uriTarget, EntryType.IN); - } catch (BlockException ex) { - RecordLog.warn(String.format("[Sentinel Pre Filter] Block Exception when Origin: %s enter fall back route: %s", origin, fallBackRoute), ex); - ZuulBlockFallbackProvider zuulBlockFallbackProvider = ZuulBlockFallbackManager.getFallbackProvider(fallBackRoute); - BlockResponse blockResponse = zuulBlockFallbackProvider.fallbackResponse(fallBackRoute, ex); - // prevent routing from running - ctx.setRouteHost(null); - ctx.set(SERVICE_ID_KEY, null); - ctx.setResponseBody(blockResponse.toString()); - } - return null; - } - - private String parseOrigin(HttpServletRequest request) { - return requestOriginParser.parseOrigin(request); - } -} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/properties/SentinelZuulProperties.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/properties/SentinelZuulProperties.java deleted file mode 100644 index 8e7681ed..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/properties/SentinelZuulProperties.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.properties; - -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.SEND_RESPONSE_FILTER_ORDER; - -/** - * Sentinel Spring Cloud Zuul AutoConfiguration property. - * - * @author tiger - */ -public class SentinelZuulProperties { - - private boolean enabled = false; - - private Order order = new Order(); - - public static class Order { - - private int post = SEND_RESPONSE_FILTER_ORDER - 10; - - private int pre = 10000; - - private int error = -1; - - public int getPost() { - return post; - } - - public void setPost(int post) { - this.post = post; - } - - public int getPre() { - return pre; - } - - public void setPre(int pre) { - this.pre = pre; - } - - public int getError() { - return error; - } - - public void setError(int error) { - this.error = error; - } - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public Order getOrder() { - return order; - } - - public void setOrder(Order order) { - this.order = order; - } -} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/util/FilterUtil.java b/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/util/FilterUtil.java deleted file mode 100755 index cc00ccee..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/zuul/util/FilterUtil.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.util; - -import com.alibaba.csp.sentinel.util.StringUtil; - -import javax.servlet.http.HttpServletRequest; - -/** - * Util class for web servlet filter. - * This is same as servlet adapter util class - * - * @author tiger - */ -public final class FilterUtil { - - public static String filterTarget(HttpServletRequest request) { - String pathInfo = getResourcePath(request); - if (!pathInfo.startsWith("/")) { - pathInfo = "/" + pathInfo; - } - - if ("/".equals(pathInfo)) { - return pathInfo; - } - - // Note: pathInfo should be converted to camelCase style. - int lastSlashIndex = pathInfo.lastIndexOf("/"); - - if (lastSlashIndex >= 0) { - pathInfo = pathInfo.substring(0, lastSlashIndex) + "/" - + StringUtil.trim(pathInfo.substring(lastSlashIndex + 1)); - } else { - pathInfo = "/" + StringUtil.trim(pathInfo); - } - - return pathInfo; - } - - private static String getResourcePath(HttpServletRequest request) { - String pathInfo = normalizeAbsolutePath(request.getPathInfo(), false); - String servletPath = normalizeAbsolutePath(request.getServletPath(), pathInfo.length() != 0); - - return servletPath + pathInfo; - } - - private static String normalizeAbsolutePath(String path, boolean removeTrailingSlash) throws IllegalStateException { - return normalizePath(path, true, false, removeTrailingSlash); - } - - private static String normalizePath(String path, boolean forceAbsolute, boolean forceRelative, - boolean removeTrailingSlash) throws IllegalStateException { - char[] pathChars = StringUtil.trimToEmpty(path).toCharArray(); - int length = pathChars.length; - - // Check path and slash. - boolean startsWithSlash = false; - boolean endsWithSlash = false; - - if (length > 0) { - char firstChar = pathChars[0]; - char lastChar = pathChars[length - 1]; - - startsWithSlash = firstChar == '/' || firstChar == '\\'; - endsWithSlash = lastChar == '/' || lastChar == '\\'; - } - - StringBuilder buf = new StringBuilder(length); - boolean isAbsolutePath = forceAbsolute || !forceRelative && startsWithSlash; - int index = startsWithSlash ? 0 : -1; - int level = 0; - - if (isAbsolutePath) { - buf.append("/"); - } - - while (index < length) { - index = indexOfSlash(pathChars, index + 1, false); - - if (index == length) { - break; - } - - int nextSlashIndex = indexOfSlash(pathChars, index, true); - - String element = new String(pathChars, index, nextSlashIndex - index); - index = nextSlashIndex; - - // Ignore "." - if (".".equals(element)) { - continue; - } - - // Backtrack ".." - if ("..".equals(element)) { - if (level == 0) { - if (isAbsolutePath) { - throw new IllegalStateException(path); - } else { - buf.append("../"); - } - } else { - buf.setLength(pathChars[--level]); - } - - continue; - } - - pathChars[level++] = (char)buf.length(); - buf.append(element).append('/'); - } - - // remove the last "/" - if (buf.length() > 0) { - if (!endsWithSlash || removeTrailingSlash) { - buf.setLength(buf.length() - 1); - } - } - - return buf.toString(); - } - - private static int indexOfSlash(char[] chars, int beginIndex, boolean slash) { - int i = beginIndex; - - for (; i < chars.length; i++) { - char ch = chars[i]; - - if (slash) { - if (ch == '/' || ch == '\\') { - break; // if a slash - } - } else { - if (ch != '/' && ch != '\\') { - break; // if not a slash - } - } - } - - return i; - } - - private FilterUtil() {} -} diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinitionChangeObserver b/sentinel-adapter/sentinel-zuul-adapter/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinitionChangeObserver new file mode 100644 index 00000000..a924cf5b --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinitionChangeObserver @@ -0,0 +1 @@ +com.alibaba.csp.sentinel.adapter.gateway.zuul.api.ZuulApiDefinitionChangeObserver \ No newline at end of file diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackManagerTest.java b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackManagerTest.java similarity index 94% rename from sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackManagerTest.java rename to sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackManagerTest.java index 81425be2..f3c0b3e2 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackManagerTest.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackManagerTest.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.fallback; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback; import com.alibaba.csp.sentinel.slots.block.flow.FlowException; + import org.junit.Assert; import org.junit.Test; - /** * @author tiger */ @@ -56,7 +56,7 @@ public class ZuulBlockFallbackManagerTest { ZuulBlockFallbackManager.registerProvider(myNullResponseFallBackProvider); Assert.assertEquals(myNullResponseFallBackProvider.getRoute(), ROUTE); ZuulBlockFallbackManager.clear(); - Assert.assertEquals(ZuulBlockFallbackManager.getFallbackProvider(ROUTE).getRoute(),DEFAULT_ROUTE); + Assert.assertEquals(ZuulBlockFallbackManager.getFallbackProvider(ROUTE).getRoute(), DEFAULT_ROUTE); } } \ No newline at end of file diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackProviderTest.java b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackProviderTest.java similarity index 94% rename from sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackProviderTest.java rename to sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackProviderTest.java index f701d4a9..f7ec49bc 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/fallback/ZuulBlockFallbackProviderTest.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/fallback/ZuulBlockFallbackProviderTest.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.fallback; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback; import com.alibaba.csp.sentinel.slots.block.flow.FlowException; + import org.junit.Assert; import org.junit.Test; @@ -48,7 +49,8 @@ public class ZuulBlockFallbackProviderTest { @Test public void testFlowControlFallbackResponse() throws Exception { ZuulBlockFallbackProvider fallbackProvider = ZuulBlockFallbackManager.getFallbackProvider(ALL_ROUTE); - BlockResponse clientHttpResponse = fallbackProvider.fallbackResponse(ALL_ROUTE, new FlowException("flow exception")); + BlockResponse clientHttpResponse = fallbackProvider.fallbackResponse(ALL_ROUTE, + new FlowException("flow exception")); Assert.assertEquals(clientHttpResponse.getCode(), 429); } diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelErrorFilterTest.java b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulErrorFilterTest.java similarity index 51% rename from sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelErrorFilterTest.java rename to sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulErrorFilterTest.java index 8f2bca89..4c9096d5 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelErrorFilterTest.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulErrorFilterTest.java @@ -14,42 +14,37 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.filters; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.filters; -import com.alibaba.csp.sentinel.adapter.zuul.properties.SentinelZuulProperties; import com.netflix.zuul.context.RequestContext; import org.junit.Assert; import org.junit.Test; -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.ERROR_TYPE; +import static com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant.ERROR_TYPE; /** * @author tiger */ -public class SentinelErrorFilterTest { +public class SentinelZuulErrorFilterTest { + @Test public void testFilterType() throws Exception { - SentinelZuulProperties properties = new SentinelZuulProperties(); - SentinelErrorFilter sentinelErrorFilter = new SentinelErrorFilter(properties); - Assert.assertEquals(sentinelErrorFilter.filterType(), ERROR_TYPE); + SentinelZuulErrorFilter sentinelZuulErrorFilter = new SentinelZuulErrorFilter(); + Assert.assertEquals(sentinelZuulErrorFilter.filterType(), ERROR_TYPE); } @Test public void testShouldFilter() { - SentinelZuulProperties properties = new SentinelZuulProperties(); - Assert.assertFalse(properties.isEnabled()); - properties.setEnabled(true); - SentinelErrorFilter sentinelErrorFilter = new SentinelErrorFilter(properties); + SentinelZuulErrorFilter sentinelZuulErrorFilter = new SentinelZuulErrorFilter(); RequestContext ctx = RequestContext.getCurrentContext(); ctx.setThrowable(new RuntimeException()); - Assert.assertTrue(sentinelErrorFilter.shouldFilter()); + Assert.assertTrue(sentinelZuulErrorFilter.shouldFilter()); } @Test public void testRun() throws Exception { - SentinelZuulProperties properties = new SentinelZuulProperties(); - SentinelErrorFilter sentinelErrorFilter = new SentinelErrorFilter(properties); - Object result = sentinelErrorFilter.run(); + SentinelZuulErrorFilter sentinelZuulErrorFilter = new SentinelZuulErrorFilter(); + Object result = sentinelZuulErrorFilter.run(); Assert.assertNull(result); } diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPostFilterTest.java b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPostFilterTest.java similarity index 55% rename from sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPostFilterTest.java rename to sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPostFilterTest.java index 6ccd6cae..8d804619 100644 --- a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPostFilterTest.java +++ b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPostFilterTest.java @@ -14,31 +14,28 @@ * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.zuul.filters; +package com.alibaba.csp.sentinel.adapter.gateway.zuul.filters; -import com.alibaba.csp.sentinel.adapter.zuul.properties.SentinelZuulProperties; import org.junit.Assert; import org.junit.Test; -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.POST_TYPE; +import static com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant.POST_TYPE; /** * @author tiger */ -public class SentinelPostFilterTest { +public class SentinelZuulPostFilterTest { @Test public void testFilterType() throws Exception { - SentinelZuulProperties properties = new SentinelZuulProperties(); - SentinelPostFilter sentinelPostFilter = new SentinelPostFilter(properties); - Assert.assertEquals(sentinelPostFilter.filterType(), POST_TYPE); + SentinelZuulPostFilter sentinelZuulPostFilter = new SentinelZuulPostFilter(); + Assert.assertEquals(sentinelZuulPostFilter.filterType(), POST_TYPE); } @Test public void testRun() throws Exception { - SentinelZuulProperties properties = new SentinelZuulProperties(); - SentinelPostFilter sentinelPostFilter = new SentinelPostFilter(properties); - Object result = sentinelPostFilter.run(); + SentinelZuulPostFilter sentinelZuulPostFilter = new SentinelZuulPostFilter(); + Object result = sentinelZuulPostFilter.run(); Assert.assertNull(result); } diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPreFilterTest.java b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPreFilterTest.java new file mode 100644 index 00000000..289a9b92 --- /dev/null +++ b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/zuul/filters/SentinelZuulPreFilterTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.csp.sentinel.adapter.gateway.zuul.filters; + +import com.netflix.zuul.context.RequestContext; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import javax.servlet.http.HttpServletRequest; + +import static com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant.PRE_TYPE; +import static com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant.SERVICE_ID_KEY; +import static org.mockito.Mockito.when; + +/** + * @author tiger + */ +public class SentinelZuulPreFilterTest { + + private String SERVICE_ID = "servicea"; + + private String URI = "/servicea/test"; + + @Mock + private HttpServletRequest httpServletRequest; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(httpServletRequest.getContextPath()).thenReturn(""); + when(httpServletRequest.getPathInfo()).thenReturn(URI); + RequestContext requestContext = new RequestContext(); + requestContext.set(SERVICE_ID_KEY, SERVICE_ID); + requestContext.setRequest(httpServletRequest); + RequestContext.testSetCurrentContext(requestContext); + } + + @Test + public void testFilterType() throws Exception { + SentinelZuulPreFilter sentinelZuulPreFilter = new SentinelZuulPreFilter(); + Assert.assertEquals(sentinelZuulPreFilter.filterType(), PRE_TYPE); + } + +} \ No newline at end of file diff --git a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPreFilterTest.java b/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPreFilterTest.java deleted file mode 100644 index ab71e5cf..00000000 --- a/sentinel-adapter/sentinel-zuul-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/zuul/filters/SentinelPreFilterTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.csp.sentinel.adapter.zuul.filters; - -import com.alibaba.csp.sentinel.adapter.zuul.fallback.DefaultRequestOriginParser; -import com.alibaba.csp.sentinel.adapter.zuul.fallback.RequestOriginParser; -import com.alibaba.csp.sentinel.adapter.zuul.fallback.UrlCleaner; -import com.alibaba.csp.sentinel.adapter.zuul.properties.SentinelZuulProperties; -import com.alibaba.csp.sentinel.slots.block.flow.FlowException; -import com.netflix.zuul.context.RequestContext; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import javax.servlet.http.HttpServletRequest; - -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.PRE_TYPE; -import static com.alibaba.csp.sentinel.adapter.zuul.constants.ZuulConstant.SERVICE_ID_KEY; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.when; - -/** - * @author tiger - */ -public class SentinelPreFilterTest { - - private String SERVICE_ID = "servicea"; - - private String URI = "/servicea/test"; - - @Mock - private HttpServletRequest httpServletRequest; - - @Mock - private UrlCleaner urlCleaner; - - private final RequestOriginParser requestOriginParser = new DefaultRequestOriginParser(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(httpServletRequest.getContextPath()).thenReturn(""); - when(httpServletRequest.getPathInfo()).thenReturn(URI); - RequestContext requestContext = new RequestContext(); - requestContext.set(SERVICE_ID_KEY, SERVICE_ID); - requestContext.setRequest(httpServletRequest); - RequestContext.testSetCurrentContext(requestContext); - } - - @Test - public void testFilterType() throws Exception { - SentinelZuulProperties properties = new SentinelZuulProperties(); - SentinelPreFilter sentinelPreFilter = new SentinelPreFilter(properties, urlCleaner, requestOriginParser); - Assert.assertEquals(sentinelPreFilter.filterType(), PRE_TYPE); - } - - @Test - public void testRun() throws Exception { - RequestContext ctx = RequestContext.getCurrentContext(); - SentinelZuulProperties properties = new SentinelZuulProperties(); - SentinelPreFilter sentinelPreFilter = new SentinelPreFilter(properties, urlCleaner, requestOriginParser); - given(urlCleaner.clean(URI)).willReturn(URI); - sentinelPreFilter.run(); - Assert.assertNull(ctx.getRouteHost()); - Assert.assertEquals(ctx.get(SERVICE_ID_KEY), SERVICE_ID); - } - - @Test - public void testServiceFallBackRun() throws Exception { - RequestContext ctx = RequestContext.getCurrentContext(); - SentinelZuulProperties properties = new SentinelZuulProperties(); - properties.setEnabled(true); - SentinelPreFilter sentinelPreFilter = new SentinelPreFilter(properties, urlCleaner, requestOriginParser); - - given(urlCleaner.clean(URI)).willAnswer( - new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - throw new FlowException("flow ex"); - } - } - ); - sentinelPreFilter.run(); - Assert.assertNull(ctx.getRouteHost()); - Assert.assertNull(ctx.get(SERVICE_ID_KEY)); - } - -} \ No newline at end of file