From 7e672d175a025137ad1569bcb2a4a5d673d1dd2a Mon Sep 17 00:00:00 2001 From: cheese8 Date: Mon, 20 Jun 2022 13:21:57 +0800 Subject: [PATCH] change escape way into encode (#251) --- .../feign/PolarisFeignLoadBalancer.java | 28 ++++++------- .../feign/RouterLabelFeignInterceptor.java | 29 +++++++------- .../RouterLabelFeignInterceptorTest.java | 40 +++++++++---------- .../common/util/ExpressionLabelUtils.java | 19 +-------- .../common/util/ExpressionLabelUtilsTest.java | 36 +---------------- 5 files changed, 53 insertions(+), 99 deletions(-) diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java index e46b17498..76c824f62 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.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.HashMap; import java.util.Map; @@ -27,7 +30,6 @@ import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.reactive.LoadBalancerCommand; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; -import com.tencent.cloud.common.util.ExpressionLabelUtils; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.RouterConstants; @@ -39,7 +41,8 @@ import org.springframework.util.CollectionUtils; /** * In order to pass router context for {@link com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule}. * - *@author lepdou 2022-05-16 + * @author lepdou 2022-05-16 + * @author cheese8 2022-06-18 */ public class PolarisFeignLoadBalancer extends FeignLoadBalancer { @@ -70,18 +73,15 @@ public class PolarisFeignLoadBalancer extends FeignLoadBalancer { 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..4eb59a208 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-18 */ 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/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..16f15c372 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-18 */ @RunWith(MockitoJUnitRunner.class) public class RouterLabelFeignInterceptorTest { @@ -116,27 +119,24 @@ public class RouterLabelFeignInterceptorTest { routerLabelFeignInterceptor.apply(requestTemplate); 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(routerLabelsMap); + for (String value : routerLabelsMap.values()) { + 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-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/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..0dedc4698 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 + * @auther 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}";