diff --git a/.github/workflows/junit_test.yml b/.github/workflows/junit_test.yml
index f2693c44f..51e9cce15 100644
--- a/.github/workflows/junit_test.yml
+++ b/.github/workflows/junit_test.yml
@@ -5,24 +5,47 @@ name: Test with Junit
on:
push:
- branches: [ 2020.0 ]
+ branches:
+ - main
+ - 2021.0
+ - 2020.0
+ - greenwich
pull_request:
- branches: [ 2020.0 ]
+ branches:
+ - main
+ - 2021.0
+ - 2020.0
+ - greenwich
jobs:
build:
+ strategy:
+ matrix:
+ java: [ 8, 11, 17 ]
+ os: [ 'windows-latest', 'macos-latest', 'ubuntu-latest' ]
- runs-on: ubuntu-latest
+ runs-on: ${{ matrix.os }}
steps:
- name: Checkout codes
- uses: actions/checkout@v2
- - name: Set up JDK 8
- uses: actions/setup-java@v2
+ uses: actions/checkout@v3
+ - name: Set up JDK ${{ matrix.java }}
+ uses: actions/setup-java@v3
with:
- java-version: '8'
- distribution: 'adopt'
+ distribution: 'temurin'
+ java-version: ${{ matrix.java }}
+ - name: Cache local Maven repository
+ uses: actions/cache@v3
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
# - name: Build with Maven
# run: mvn -B package --file pom.xml
- name: Test with Maven
run: mvn -B test --file pom.xml
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v3
+ with:
+ file: '**/target/site/jacoco/jacoco.xml'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 874b31279..cd1e5d177 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,3 +6,7 @@
- [Feature: Add config module unit test](https://github.com/Tencent/spring-cloud-tencent/pull/255)
- [Upgrade: fix third-party lib CVEs & upgrade core spring libs version](https://github.com/Tencent/spring-cloud-tencent/pull/258)
- [feat:support reading configuration from application.yml or application.properties.](https://github.com/Tencent/spring-cloud-tencent/pull/261)
+- [change the way from escape to encode in 2020.0](https://github.com/Tencent/spring-cloud-tencent/pull/257)
+- [fix:fix ClassNotFoundException while not importing openfeign when using circuit-breaker module.](https://github.com/Tencent/spring-cloud-tencent/pull/270)
+- [fix:solve the chaos code problem on rejectTips](https://github.com/Tencent/spring-cloud-tencent/pull/283)
+- [fix:solve ratelimit-callee-service UnknownHostException.](https://github.com/Tencent/spring-cloud-tencent/pull/291)
diff --git a/pom.xml b/pom.xml
index a20e5fdf4..ff568384d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,7 +95,7 @@
5.3.21
- 0.8.3
+ 0.8.8
3.2.0
1.2.7
3.0.1
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisFeignClientAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisFeignClientAutoConfiguration.java
index bcaaf3ea9..ae699dead 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisFeignClientAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisFeignClientAutoConfiguration.java
@@ -25,6 +25,7 @@ import com.tencent.polaris.factory.api.DiscoveryAPIFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.context.annotation.Bean;
@@ -41,6 +42,7 @@ import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
*/
@ConditionalOnProperty(value = "spring.cloud.polaris.circuitbreaker.enabled", havingValue = "true", matchIfMissing = true)
@Configuration(proxyBeanMethods = false)
+@ConditionalOnClass(name = "org.springframework.cloud.openfeign.FeignAutoConfiguration")
@AutoConfigureAfter(PolarisContextAutoConfiguration.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class PolarisFeignClientAutoConfiguration {
diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListenerTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListenerTest.java
index f3f70b4bc..c408f4f54 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListenerTest.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListenerTest.java
@@ -66,7 +66,7 @@ public class ConfigChangeListenerTest {
Sets.newHashSet("timeout"));
applicationEventPublisher.publishEvent(event);
-
+ Thread.sleep(200);
//after change
Assert.assertEquals(2, testConfig.getChangeCnt());
Assert.assertEquals(2000, testConfig.getTimeout());
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
index 7340c73de..8796fc1ab 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
@@ -55,7 +55,7 @@ import static com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant.LAB
/**
* Reactive filter to check quota.
*
- * @author Haotian Zhang, lepdou
+ * @author Haotian Zhang, lepdou, cheese8
*/
public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
@@ -106,7 +106,7 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
ServerHttpResponse response = exchange.getResponse();
response.setRawStatusCode(polarisRateLimitProperties.getRejectHttpCode());
- response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
+ response.getHeaders().setContentType(MediaType.TEXT_HTML);
DataBuffer dataBuffer = response.bufferFactory().allocateBuffer()
.write(rejectTips.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(dataBuffer));
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
index 08767b721..f3e4c3b07 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
@@ -53,7 +53,7 @@ import static com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant.LAB
/**
* Servlet filter to check quota.
*
- * @author Haotian Zhang, lepdou
+ * @author Haotian Zhang, lepdou, cheese8
*/
@Order(RateLimitConstant.FILTER_ORDER)
public class QuotaCheckServletFilter extends OncePerRequestFilter {
@@ -99,6 +99,7 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
response.setStatus(polarisRateLimitProperties.getRejectHttpCode());
+ response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(rejectTips);
return;
}
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilterTest.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilterTest.java
index 3bae2e3bd..0a9a4988f 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilterTest.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilterTest.java
@@ -65,7 +65,7 @@ import static org.mockito.Mockito.when;
/**
* Test for {@link QuotaCheckReactiveFilter}.
*
- * @author Haotian Zhang
+ * @author Haotian Zhang, cheese8
*/
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(classes = QuotaCheckReactiveFilterTest.TestApplication.class, properties = {
@@ -118,7 +118,7 @@ public class QuotaCheckReactiveFilterTest {
});
PolarisRateLimitProperties polarisRateLimitProperties = new PolarisRateLimitProperties();
- polarisRateLimitProperties.setRejectRequestTips("RejectRequestTips");
+ polarisRateLimitProperties.setRejectRequestTips("RejectRequestTips提示消息");
polarisRateLimitProperties.setRejectHttpCode(419);
RateLimitRuleLabelResolver rateLimitRuleLabelResolver = mock(RateLimitRuleLabelResolver.class);
@@ -138,7 +138,7 @@ public class QuotaCheckReactiveFilterTest {
try {
Field rejectTips = QuotaCheckReactiveFilter.class.getDeclaredField("rejectTips");
rejectTips.setAccessible(true);
- assertThat(rejectTips.get(quotaCheckReactiveFilter)).isEqualTo("RejectRequestTips");
+ assertThat(rejectTips.get(quotaCheckReactiveFilter)).isEqualTo("RejectRequestTips提示消息");
}
catch (NoSuchFieldException | IllegalAccessException e) {
fail("Exception encountered.", e);
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilterTest.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilterTest.java
index a2cc344dc..3f93f0a3b 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilterTest.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilterTest.java
@@ -65,7 +65,7 @@ import static org.mockito.Mockito.when;
/**
* Test for {@link QuotaCheckServletFilter}.
*
- * @author Haotian Zhang
+ * @author Haotian Zhang, cheese8
*/
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(classes = QuotaCheckServletFilterTest.TestApplication.class, properties = {
@@ -77,6 +77,8 @@ public class QuotaCheckServletFilterTest {
private QuotaCheckServletFilter quotaCheckServletFilter;
+ private QuotaCheckServletFilter quotaCheckWithHtmlRejectTipsServletFilter;
+
private static MockedStatic mockedApplicationContextAwareUtils;
private static MockedStatic expressionLabelUtilsMockedStatic;
@BeforeClass
@@ -87,7 +89,6 @@ public class QuotaCheckServletFilterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
-
}
@AfterClass
@@ -118,13 +119,18 @@ public class QuotaCheckServletFilterTest {
});
PolarisRateLimitProperties polarisRateLimitProperties = new PolarisRateLimitProperties();
- polarisRateLimitProperties.setRejectRequestTips("RejectRequestTips");
+ polarisRateLimitProperties.setRejectRequestTips("RejectRequestTips提示消息");
polarisRateLimitProperties.setRejectHttpCode(419);
+ PolarisRateLimitProperties polarisRateLimitWithHtmlRejectTipsProperties = new PolarisRateLimitProperties();
+ polarisRateLimitWithHtmlRejectTipsProperties.setRejectRequestTips("RejectRequestTips提示消息
");
+ polarisRateLimitWithHtmlRejectTipsProperties.setRejectHttpCode(419);
+
RateLimitRuleLabelResolver rateLimitRuleLabelResolver = mock(RateLimitRuleLabelResolver.class);
when(rateLimitRuleLabelResolver.getExpressionLabelKeys(anyString(), anyString())).thenReturn(Collections.EMPTY_SET);
this.quotaCheckServletFilter = new QuotaCheckServletFilter(limitAPI, labelResolver, polarisRateLimitProperties, rateLimitRuleLabelResolver);
+ this.quotaCheckWithHtmlRejectTipsServletFilter = new QuotaCheckServletFilter(limitAPI, labelResolver, polarisRateLimitWithHtmlRejectTipsProperties, rateLimitRuleLabelResolver);
}
@Test
@@ -133,7 +139,16 @@ public class QuotaCheckServletFilterTest {
try {
Field rejectTips = QuotaCheckServletFilter.class.getDeclaredField("rejectTips");
rejectTips.setAccessible(true);
- assertThat(rejectTips.get(quotaCheckServletFilter)).isEqualTo("RejectRequestTips");
+ assertThat(rejectTips.get(quotaCheckServletFilter)).isEqualTo("RejectRequestTips提示消息");
+ }
+ catch (NoSuchFieldException | IllegalAccessException e) {
+ fail("Exception encountered.", e);
+ }
+ quotaCheckWithHtmlRejectTipsServletFilter.init();
+ try {
+ Field rejectTips = QuotaCheckServletFilter.class.getDeclaredField("rejectTips");
+ rejectTips.setAccessible(true);
+ assertThat(rejectTips.get(quotaCheckWithHtmlRejectTipsServletFilter)).isEqualTo("RejectRequestTips提示消息
");
}
catch (NoSuchFieldException | IllegalAccessException e) {
fail("Exception encountered.", e);
@@ -201,8 +216,11 @@ public class QuotaCheckServletFilterTest {
MetadataContext.LOCAL_SERVICE = "TestApp3";
quotaCheckServletFilter.doFilterInternal(request, response, filterChain);
assertThat(response.getStatus()).isEqualTo(419);
- assertThat(response.getContentAsString()).isEqualTo("RejectRequestTips");
+ assertThat(response.getContentAsString()).isEqualTo("RejectRequestTips提示消息");
+ quotaCheckWithHtmlRejectTipsServletFilter.doFilterInternal(request, response, filterChain);
+ assertThat(response.getStatus()).isEqualTo(419);
+ assertThat(response.getContentAsString()).isEqualTo("RejectRequestTips提示消息");
// Exception
MetadataContext.LOCAL_SERVICE = "TestApp4";
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplier.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplier.java
index 13b4afc17..d2f5e2f4e 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplier.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplier.java
@@ -17,6 +17,9 @@
package com.tencent.cloud.polaris.router;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -27,7 +30,6 @@ import java.util.Map;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
-import com.tencent.cloud.common.util.ExpressionLabelUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.loadbalancer.LoadBalancerUtils;
import com.tencent.cloud.polaris.router.config.PolarisMetadataRouterProperties;
@@ -66,7 +68,7 @@ import org.springframework.util.CollectionUtils;
* And {@link PolarisRouterServiceInstanceListSupplier#get(Request)} provides the ability to pass in http headers,
* so routing capabilities are implemented through IRule.
*
- * @author Haotian Zhang, lepdou
+ * @author Haotian Zhang, lepdou, cheese8
*/
public class PolarisRouterServiceInstanceListSupplier extends DelegatingServiceInstanceListSupplier {
@@ -123,19 +125,15 @@ public class PolarisRouterServiceInstanceListSupplier extends DelegatingServiceI
routerContext.setLabels(PolarisRouterContext.TRANSITIVE_LABELS, MetadataContextHolder.get()
.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE));
- labelHeaderValues.forEach(labelHeaderValue -> {
- Map labels = JacksonUtils.deserialize2Map(labelHeaderValue);
- if (!CollectionUtils.isEmpty(labels)) {
- Map unescapeLabels = new HashMap<>(labels.size());
- for (Map.Entry entry : labels.entrySet()) {
- String escapedKey = ExpressionLabelUtils.unescape(entry.getKey());
- String escapedValue = ExpressionLabelUtils.unescape(entry.getValue());
- unescapeLabels.put(escapedKey, escapedValue);
- }
- routerContext.setLabels(PolarisRouterContext.RULE_ROUTER_LABELS, unescapeLabels);
- }
- });
-
+ Map labelHeaderValuesMap = new HashMap<>();
+ try {
+ String labelHeaderValuesContent = labelHeaderValues.stream().findFirst().get();
+ labelHeaderValuesMap.putAll(JacksonUtils.deserialize2Map(URLDecoder.decode(labelHeaderValuesContent, StandardCharsets.UTF_8.name())));
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("unsupported charset exception " + StandardCharsets.UTF_8.name());
+ }
+ routerContext.setLabels(PolarisRouterContext.RULE_ROUTER_LABELS, labelHeaderValuesMap);
return routerContext;
}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java
index fac0879b4..c2f339b02 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java
@@ -18,6 +18,9 @@
package com.tencent.cloud.polaris.router.feign;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -28,7 +31,6 @@ import java.util.Set;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
-import com.tencent.cloud.common.util.ExpressionLabelUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.router.RouterConstants;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
@@ -44,7 +46,8 @@ import org.springframework.util.CollectionUtils;
/**
* Resolver labels from request.
*
- *@author lepdou 2022-05-12
+ * @author lepdou 2022-05-12
+ * @author cheese8 2022-06-20
*/
public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered {
private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelFeignInterceptor.class);
@@ -102,22 +105,20 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered
.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
labels.putAll(transitiveLabels);
- // Because when the label is placed in RequestTemplate.header,
- // RequestTemplate will parse the header according to the regular, which conflicts with the expression.
- // Avoid conflicts by escaping.
- Map escapeLabels = new HashMap<>(labels.size());
- for (Map.Entry entry : labels.entrySet()) {
- String escapedKey = ExpressionLabelUtils.escape(entry.getKey());
- String escapedValue = ExpressionLabelUtils.escape(entry.getValue());
- escapeLabels.put(escapedKey, escapedValue);
- }
-
// pass label by header
- if (escapeLabels.size() == 0) {
+ if (labels.size() == 0) {
requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER);
return;
}
- requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER, JacksonUtils.serialize2Json(escapeLabels));
+
+ String encodedLabelsContent;
+ try {
+ encodedLabelsContent = URLEncoder.encode(JacksonUtils.serialize2Json(labels), StandardCharsets.UTF_8.name());
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("unsupported charset exception " + StandardCharsets.UTF_8.name());
+ }
+ requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER, encodedLabelsContent);
}
private Map getRuleExpressionLabels(RequestTemplate requestTemplate, String peerService) {
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java
index eb7c90ce0..2006a373f 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java
@@ -19,7 +19,10 @@
package com.tencent.cloud.polaris.router.resttemplate;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.net.URI;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -52,7 +55,8 @@ import org.springframework.util.CollectionUtils;
* PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor capabilities.
* Parses the label from the request and puts it into the RouterContext for routing.
*
- *@author lepdou 2022-05-18
+ * @author lepdou 2022-05-18
+ * @author cheese8 2022-06-20
*/
public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisLoadBalancerInterceptor.class);
@@ -126,22 +130,19 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
labels.putAll(transitiveLabels);
- // Because when the label is placed in RequestTemplate.header,
- // RequestTemplate will parse the header according to the regular, which conflicts with the expression.
- // Avoid conflicts by escaping.
- Map escapeLabels = new HashMap<>(labels.size());
- for (Map.Entry entry : labels.entrySet()) {
- String escapedKey = ExpressionLabelUtils.escape(entry.getKey());
- String escapedValue = ExpressionLabelUtils.escape(entry.getValue());
- escapeLabels.put(escapedKey, escapedValue);
- }
-
// pass label by header
- if (escapeLabels.size() == 0) {
+ if (labels.size() == 0) {
request.getHeaders().set(RouterConstants.ROUTER_LABEL_HEADER, null);
return;
}
- request.getHeaders().set(RouterConstants.ROUTER_LABEL_HEADER, JacksonUtils.serialize2Json(escapeLabels));
+ String encodedLabelsContent;
+ try {
+ encodedLabelsContent = URLEncoder.encode(JacksonUtils.serialize2Json(labels), StandardCharsets.UTF_8.name());
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("unsupported charset exception " + StandardCharsets.UTF_8.name());
+ }
+ request.getHeaders().set(RouterConstants.ROUTER_LABEL_HEADER, encodedLabelsContent);
}
private Map getExpressionLabels(HttpRequest request, String peerServiceName) {
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java
index d5f7076fc..b2824b7ea 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java
@@ -18,6 +18,9 @@
package com.tencent.cloud.polaris.router.feign;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -29,7 +32,6 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
-import com.tencent.cloud.common.util.ExpressionLabelUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.router.RouterConstants;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
@@ -50,6 +52,7 @@ import static org.mockito.Mockito.when;
/**
* test for {@link RouterLabelFeignInterceptor}
* @author lepdou 2022-05-26
+ * @author cheese8 2022-06-20
*/
@RunWith(MockitoJUnitRunner.class)
public class RouterLabelFeignInterceptorTest {
@@ -117,26 +120,24 @@ public class RouterLabelFeignInterceptorTest {
Collection routerLabels = requestTemplate.headers().get(RouterConstants.ROUTER_LABEL_HEADER);
- Assert.assertNotNull(routerLabels);
- for (String value : routerLabels) {
- Map labels = unescape(JacksonUtils.deserialize2Map(value));
-
- Assert.assertEquals("v1", labels.get("k1"));
- Assert.assertEquals("v22", labels.get("k2"));
- Assert.assertEquals("v3", labels.get("k3"));
- Assert.assertEquals("v4", labels.get("k4"));
- Assert.assertEquals(headerUidValue, labels.get("${http.header.uid}"));
- Assert.assertEquals("", labels.get("${http.header.name}"));
+ Map routerLabelsMap = new HashMap<>();
+ try {
+ String routerLabelContent = routerLabels.stream().findFirst().get();
+ routerLabelsMap.putAll(JacksonUtils.deserialize2Map(URLDecoder.decode(routerLabelContent, StandardCharsets.UTF_8.name())));
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("unsupported charset exception " + StandardCharsets.UTF_8.name());
}
+
+ Assert.assertNotNull(routerLabels);
+ Assert.assertEquals("v1", routerLabelsMap.get("k1"));
+ Assert.assertEquals("v22", routerLabelsMap.get("k2"));
+ Assert.assertEquals("v3", routerLabelsMap.get("k3"));
+ Assert.assertEquals("v4", routerLabelsMap.get("k4"));
+ Assert.assertEquals(headerUidValue, routerLabelsMap.get("${http.header.uid}"));
+ Assert.assertEquals("", routerLabelsMap.get("${http.header.name}"));
}
}
}
- private Map unescape(Map labels) {
- Map result = new HashMap<>();
- for (Map.Entry entry : labels.entrySet()) {
- result.put(ExpressionLabelUtils.unescape(entry.getKey()), ExpressionLabelUtils.unescape(entry.getValue()));
- }
- return result;
- }
}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptorTest.java
index 5162d8a8d..11319f650 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptorTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptorTest.java
@@ -18,8 +18,9 @@
package com.tencent.cloud.polaris.router.resttemplate;
-
import java.net.URI;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -60,6 +61,7 @@ import static org.mockito.Mockito.when;
/**
* test for {@link PolarisLoadBalancerInterceptor}
* @author lepdou 2022-05-26
+ * @author cheese8 2022-06-20
*/
@RunWith(MockitoJUnitRunner.class)
public class PolarisLoadBalancerInterceptorTest {
@@ -184,13 +186,13 @@ public class PolarisLoadBalancerInterceptorTest {
verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService);
verify(routerLabelResolver).resolve(request, null);
- Map headers = JacksonUtils.deserialize2Map(request.getHeaders()
- .get(RouterConstants.ROUTER_LABEL_HEADER).get(0));
+ Map headers = JacksonUtils.deserialize2Map(URLDecoder.decode(request.getHeaders()
+ .get(RouterConstants.ROUTER_LABEL_HEADER).get(0), StandardCharsets.UTF_8.name()));
Assert.assertEquals("v1", headers.get("k1"));
Assert.assertEquals("v22", headers.get("k2"));
Assert.assertEquals("v4", headers.get("k4"));
- Assert.assertEquals("GET", headers.get("##@$@##http.method}"));
- Assert.assertEquals("/user/get", headers.get("##@$@##http.uri}"));
+ Assert.assertEquals("GET", headers.get("${http.method}"));
+ Assert.assertEquals("/user/get", headers.get("${http.uri}"));
}
static class MockedLoadBalancerRequest implements LoadBalancerRequest {
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ExpressionLabelUtils.java
index 41d70abd7..a4c53ccc1 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ExpressionLabelUtils.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ExpressionLabelUtils.java
@@ -40,7 +40,8 @@ import org.springframework.web.server.ServerWebExchange;
/**
* the utils for parse label expression.
*
- *@author lepdou 2022-05-13
+ * @author lepdou 2022-05-13
+ * @author cheese8 2022-06-20
*/
public class ExpressionLabelUtils {
@@ -76,18 +77,10 @@ public class ExpressionLabelUtils {
* the expression of uri.
*/
public static final String LABEL_URI = "${http.uri}";
- /**
- * the prefix of expression.
- */
- public static final String LABEL_PREFIX = "${";
/**
* the suffix of expression.
*/
public static final String LABEL_SUFFIX = "}";
- /**
- * the escape prefix of label.
- */
- public static final String LABEL_ESCAPE_PREFIX = "##@$@##";
public static boolean isExpressionLabel(String labelKey) {
if (StringUtils.isEmpty(labelKey)) {
@@ -103,14 +96,6 @@ public class ExpressionLabelUtils {
&& StringUtils.endsWith(labelKey, LABEL_SUFFIX);
}
- public static String escape(String str) {
- return StringUtils.replace(str, LABEL_PREFIX, LABEL_ESCAPE_PREFIX);
- }
-
- public static String unescape(String str) {
- return StringUtils.replace(str, LABEL_ESCAPE_PREFIX, LABEL_PREFIX);
- }
-
public static Map resolve(HttpServletRequest request, Set labelKeys) {
if (CollectionUtils.isEmpty(labelKeys)) {
return Collections.emptyMap();
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ResourceFileUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ResourceFileUtils.java
index d79bfce8b..b5ea45d5d 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ResourceFileUtils.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ResourceFileUtils.java
@@ -23,6 +23,7 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.springframework.core.io.ClassPathResource;
+import org.springframework.util.StreamUtils;
/**
* Read file content from classpath resource.
@@ -35,20 +36,15 @@ public final class ResourceFileUtils {
}
public static String readFile(String path) throws IOException {
- StringBuilder sb = new StringBuilder();
ClassPathResource classPathResource = new ClassPathResource(path);
if (classPathResource.exists() && classPathResource.isReadable()) {
try (InputStream inputStream = classPathResource.getInputStream()) {
- byte[] buffer = new byte[1024 * 10];
- int len;
- while ((len = inputStream.read(buffer)) != -1) {
- sb.append(new String(buffer, 0, len, StandardCharsets.UTF_8));
- }
+ return StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
}
}
- return sb.toString();
+ return "";
}
}
diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java
index 3c7eabed7..46b3fa1fe 100644
--- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java
+++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java
@@ -38,7 +38,8 @@ import org.springframework.mock.web.server.MockServerWebExchange;
/**
* test for {@link ExpressionLabelUtils}
- *@author lepdou 2022-05-27
+ * @author lepdou 2022-05-27
+ * @author cheese8 2022-06-20
*/
@RunWith(MockitoJUnitRunner.class)
public class ExpressionLabelUtilsTest {
@@ -76,39 +77,6 @@ public class ExpressionLabelUtilsTest {
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel9));
}
- @Test
- public void testEscape() {
- String validLabel1 = "${http.query.uid}";
- String validLabel2 = "${http.header.uid}";
- String validLabel3 = "${http.cookie.uid}";
- String validLabel4 = "${http.method}";
- String validLabel5 = "${http.uri}";
- String invalidLabel1 = "${http.queryuid}";
- String invalidLabel2 = "{http.query.uid}";
- String invalidLabel3 = "${http.query.uid";
- String invalidLabel4 = "$ {http.query.uid}";
- String invalidLabel5 = "${ http.query.uid}";
- String invalidLabel6 = "${query.uid}";
- String invalidLabel7 = "http.query.uid";
- String invalidLabel8 = "$${http.uri}";
- String invalidLabel9 = "#{http.uri}";
-
- Assert.assertEquals(validLabel1, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel1)));
- Assert.assertEquals(validLabel2, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel2)));
- Assert.assertEquals(validLabel3, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel3)));
- Assert.assertEquals(validLabel4, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel4)));
- Assert.assertEquals(validLabel5, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel5)));
- Assert.assertEquals(invalidLabel1, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel1)));
- Assert.assertEquals(invalidLabel2, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel2)));
- Assert.assertEquals(invalidLabel3, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel3)));
- Assert.assertEquals(invalidLabel4, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel4)));
- Assert.assertEquals(invalidLabel5, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel5)));
- Assert.assertEquals(invalidLabel6, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel6)));
- Assert.assertEquals(invalidLabel7, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel7)));
- Assert.assertEquals(invalidLabel8, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel8)));
- Assert.assertEquals(invalidLabel9, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel9)));
- }
-
@Test
public void testResolveHttpServletRequest() {
String validLabel1 = "${http.query.uid}";
diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ResourceFileUtilsTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ResourceFileUtilsTest.java
index 334cd4e20..769d99ce7 100644
--- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ResourceFileUtilsTest.java
+++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ResourceFileUtilsTest.java
@@ -35,7 +35,7 @@ public class ResourceFileUtilsTest {
@Test
public void testReadExistedFile() throws IOException {
String content = ResourceFileUtils.readFile("test.txt");
- Assert.assertEquals("just for test\n", content);
+ Assert.assertEquals("just for test", content);
}
@Test
diff --git a/spring-cloud-tencent-commons/src/test/resources/test.txt b/spring-cloud-tencent-commons/src/test/resources/test.txt
index 63d3c2d75..e18c37483 100644
--- a/spring-cloud-tencent-commons/src/test/resources/test.txt
+++ b/spring-cloud-tencent-commons/src/test/resources/test.txt
@@ -1 +1 @@
-just for test
+just for test
\ No newline at end of file
diff --git a/spring-cloud-tencent-examples/polaris-ratelimit-example/ratelimit-callee-service/pom.xml b/spring-cloud-tencent-examples/polaris-ratelimit-example/ratelimit-callee-service/pom.xml
index dd28040b5..bf89b34d6 100644
--- a/spring-cloud-tencent-examples/polaris-ratelimit-example/ratelimit-callee-service/pom.xml
+++ b/spring-cloud-tencent-examples/polaris-ratelimit-example/ratelimit-callee-service/pom.xml
@@ -18,6 +18,11 @@
spring-boot-starter-web
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-polaris-discovery
+
+
com.tencent.cloud
spring-cloud-starter-tencent-polaris-ratelimit