From de8bdc3711abd2d396fe4f5fd05ce11af7bca771 Mon Sep 17 00:00:00 2001 From: cheese8 Date: Sat, 18 Jun 2022 16:12:01 +0800 Subject: [PATCH] change escape way into encode --- .../feign/PolarisFeignLoadBalancer.java | 35 +++++++-------- .../feign/RouterLabelFeignInterceptor.java | 40 ++++++++--------- .../RouterLabelFeignInterceptorTest.java | 45 +++++++++++-------- .../common/util/ExpressionLabelUtils.java | 18 ++++---- 4 files changed, 70 insertions(+), 68 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..d6e45f854 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,10 +18,6 @@ package com.tencent.cloud.polaris.router.feign; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.reactive.LoadBalancerCommand; @@ -31,11 +27,17 @@ 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; - import org.springframework.cloud.netflix.ribbon.ServerIntrospector; import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer; import org.springframework.util.CollectionUtils; +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; + /** * In order to pass router context for {@link com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule}. * @@ -69,19 +71,16 @@ 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..346a7b09d 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,17 +18,9 @@ package com.tencent.cloud.polaris.router.feign; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -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; @@ -37,10 +29,19 @@ import feign.RequestInterceptor; import feign.RequestTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.core.Ordered; import org.springframework.util.CollectionUtils; +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; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Resolver labels from request. * @@ -102,22 +103,19 @@ 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 encodedLabels; + try{ + encodedLabels = 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, encodedLabels); } 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..6035bb558 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,13 +18,6 @@ package com.tencent.cloud.polaris.router.feign; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -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; @@ -44,6 +37,16 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; +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; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; @@ -114,19 +117,23 @@ public class RouterLabelFeignInterceptorTest { when(metadataLocalProperties.getContent()).thenReturn(localMetadata); 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}")); } } } 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..eb799276f 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 @@ -18,17 +18,7 @@ package com.tencent.cloud.common.util; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; - import org.apache.commons.lang.StringUtils; - import org.springframework.http.HttpCookie; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; @@ -37,6 +27,14 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + /** * the utils for parse label expression. *