support new label expression (#627)

pull/629/head
lepdou 2 years ago committed by GitHub
parent 008551b15f
commit e33f60bdaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,3 +11,4 @@
- [Bugfix: fix feign report call result error when using feign direct call](https://github.com/Tencent/spring-cloud-tencent/pull/621)
- [fix pr 606: modify a part of changes requested by review.](https://github.com/Tencent/spring-cloud-tencent/pull/620)
- [fix pr 613: modify a judgment logic](https://github.com/Tencent/spring-cloud-tencent/pull/618)
- [Feature: support new label expression](https://github.com/Tencent/spring-cloud-tencent/pull/627)

@ -21,6 +21,7 @@ import java.util.List;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.scg.PolarisReactiveLoadBalancerClientFilter;
import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
@ -59,10 +60,11 @@ public class ReactiveLoadBalancerClientFilterBeanPostProcessor implements BeanPo
List<SpringWebRouterLabelResolver> routerLabelResolvers = BeanFactoryUtils.getBeans(factory, SpringWebRouterLabelResolver.class);
StaticMetadataManager staticMetadataManager = this.factory.getBean(StaticMetadataManager.class);
RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class);
PolarisContextProperties polarisContextProperties = this.factory.getBean(PolarisContextProperties.class);
return new PolarisReactiveLoadBalancerClientFilter(
loadBalancerClientFactory, gatewayLoadBalancerProperties, loadBalancerProperties,
staticMetadataManager, routerRuleLabelResolver, routerLabelResolvers);
staticMetadataManager, routerRuleLabelResolver, routerLabelResolvers, polarisContextProperties);
}
return bean;
}

@ -21,6 +21,7 @@ package com.tencent.cloud.polaris.router.config;
import java.util.List;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor;
import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver;
@ -42,7 +43,8 @@ public class FeignAutoConfiguration {
@Bean
public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List<FeignRouterLabelResolver> routerLabelResolvers,
StaticMetadataManager staticMetadataManager,
RouterRuleLabelResolver routerRuleLabelResolver) {
return new RouterLabelFeignInterceptor(routerLabelResolvers, staticMetadataManager, routerRuleLabelResolver);
RouterRuleLabelResolver routerRuleLabelResolver,
PolarisContextProperties polarisContextProperties) {
return new RouterLabelFeignInterceptor(routerLabelResolvers, staticMetadataManager, routerRuleLabelResolver, polarisContextProperties);
}
}

@ -24,6 +24,7 @@ import java.util.List;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.polaris.context.ServiceRuleManager;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.beanprocessor.ReactiveLoadBalancerClientFilterBeanPostProcessor;
import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties;
@ -106,8 +107,10 @@ public class RouterAutoConfiguration {
public RouterLabelRestTemplateInterceptor routerLabelRestTemplateInterceptor(
List<SpringWebRouterLabelResolver> routerLabelResolvers,
StaticMetadataManager staticMetadataManager,
RouterRuleLabelResolver routerRuleLabelResolver) {
return new RouterLabelRestTemplateInterceptor(routerLabelResolvers, staticMetadataManager, routerRuleLabelResolver);
RouterRuleLabelResolver routerRuleLabelResolver,
PolarisContextProperties polarisContextProperties) {
return new RouterLabelRestTemplateInterceptor(routerLabelResolvers, staticMetadataManager,
routerRuleLabelResolver, polarisContextProperties);
}
@Bean

@ -49,24 +49,24 @@ public final class FeignExpressionLabelUtils {
Map<String, String> labels = new HashMap<>();
for (String labelKey : labelKeys) {
if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_HEADER_PREFIX)) {
if (ExpressionLabelUtils.isHeaderLabel(labelKey)) {
String headerKey = ExpressionLabelUtils.parseHeaderKey(labelKey);
if (StringUtils.isBlank(headerKey)) {
continue;
}
labels.put(labelKey, getHeaderValue(request, headerKey));
}
else if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_QUERY_PREFIX)) {
else if (ExpressionLabelUtils.isQueryLabel(labelKey)) {
String queryKey = ExpressionLabelUtils.parseQueryKey(labelKey);
if (StringUtils.isBlank(queryKey)) {
continue;
}
labels.put(labelKey, getQueryValue(request, queryKey));
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_METHOD, labelKey)) {
else if (ExpressionLabelUtils.isMethodLabel(labelKey)) {
labels.put(labelKey, request.method());
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_URI, labelKey)) {
else if (ExpressionLabelUtils.isUriLabel(labelKey)) {
URI uri = URI.create(request.request().url());
labels.put(labelKey, uri.getPath());
}

@ -32,6 +32,8 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver;
import feign.RequestInterceptor;
@ -55,10 +57,12 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered
private final List<FeignRouterLabelResolver> routerLabelResolvers;
private final StaticMetadataManager staticMetadataManager;
private final RouterRuleLabelResolver routerRuleLabelResolver;
private final PolarisContextProperties polarisContextProperties;
public RouterLabelFeignInterceptor(List<FeignRouterLabelResolver> routerLabelResolvers,
StaticMetadataManager staticMetadataManager,
RouterRuleLabelResolver routerRuleLabelResolver) {
RouterRuleLabelResolver routerRuleLabelResolver,
PolarisContextProperties polarisContextProperties) {
if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
routerLabelResolvers.sort(Comparator.comparingInt(Ordered::getOrder));
this.routerLabelResolvers = routerLabelResolvers;
@ -68,6 +72,7 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered
}
this.staticMetadataManager = staticMetadataManager;
this.routerRuleLabelResolver = routerRuleLabelResolver;
this.polarisContextProperties = polarisContextProperties;
}
@Override
@ -124,6 +129,16 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered
return Collections.emptyMap();
}
return FeignExpressionLabelUtils.resolve(requestTemplate, labelKeys);
//enrich labels from request
Map<String, String> labels = FeignExpressionLabelUtils.resolve(requestTemplate, labelKeys);
//enrich caller ip label
for (String labelKey : labelKeys) {
if (ExpressionLabelUtils.isCallerIPLabel(labelKey)) {
labels.put(labelKey, polarisContextProperties.getLocalIpAddress());
}
}
return labels;
}
}

@ -34,7 +34,9 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils;
import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.slf4j.Logger;
@ -63,12 +65,15 @@ public class RouterLabelRestTemplateInterceptor implements ClientHttpRequestInte
private final List<SpringWebRouterLabelResolver> routerLabelResolvers;
private final StaticMetadataManager staticMetadataManager;
private final RouterRuleLabelResolver routerRuleLabelResolver;
private final PolarisContextProperties polarisContextProperties;
public RouterLabelRestTemplateInterceptor(List<SpringWebRouterLabelResolver> routerLabelResolvers,
StaticMetadataManager staticMetadataManager,
RouterRuleLabelResolver routerRuleLabelResolver) {
RouterRuleLabelResolver routerRuleLabelResolver,
PolarisContextProperties polarisContextProperties) {
this.staticMetadataManager = staticMetadataManager;
this.routerRuleLabelResolver = routerRuleLabelResolver;
this.polarisContextProperties = polarisContextProperties;
if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
routerLabelResolvers.sort(Comparator.comparingInt(Ordered::getOrder));
@ -146,6 +151,16 @@ public class RouterLabelRestTemplateInterceptor implements ClientHttpRequestInte
return Collections.emptyMap();
}
return SpringWebExpressionLabelUtils.resolve(request, labelKeys);
//enrich labels from request
Map<String, String> labels = SpringWebExpressionLabelUtils.resolve(request, labelKeys);
//enrich caller ip label
for (String labelKey : labelKeys) {
if (ExpressionLabelUtils.isCallerIPLabel(labelKey)) {
labels.put(labelKey, polarisContextProperties.getLocalIpAddress());
}
}
return labels;
}
}

@ -32,7 +32,9 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils;
import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
@ -87,13 +89,15 @@ public class PolarisReactiveLoadBalancerClientFilter extends ReactiveLoadBalance
private final StaticMetadataManager staticMetadataManager;
private final RouterRuleLabelResolver routerRuleLabelResolver;
private final List<SpringWebRouterLabelResolver> routerLabelResolvers;
private final PolarisContextProperties polarisContextProperties;
public PolarisReactiveLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory,
GatewayLoadBalancerProperties gatewayLoadBalancerProperties,
LoadBalancerProperties loadBalancerProperties,
StaticMetadataManager staticMetadataManager,
RouterRuleLabelResolver routerRuleLabelResolver,
List<SpringWebRouterLabelResolver> routerLabelResolvers) {
List<SpringWebRouterLabelResolver> routerLabelResolvers,
PolarisContextProperties polarisContextProperties) {
super(clientFactory, gatewayLoadBalancerProperties, loadBalancerProperties);
this.clientFactory = clientFactory;
@ -102,6 +106,7 @@ public class PolarisReactiveLoadBalancerClientFilter extends ReactiveLoadBalance
this.staticMetadataManager = staticMetadataManager;
this.routerRuleLabelResolver = routerRuleLabelResolver;
this.routerLabelResolvers = routerLabelResolvers;
this.polarisContextProperties = polarisContextProperties;
}
/**
@ -262,6 +267,16 @@ public class PolarisReactiveLoadBalancerClientFilter extends ReactiveLoadBalance
return Collections.emptyMap();
}
return SpringWebExpressionLabelUtils.resolve(exchange, labelKeys);
//enrich labels from request
Map<String, String> labels = SpringWebExpressionLabelUtils.resolve(exchange, labelKeys);
//enrich caller ip label
for (String labelKey : labelKeys) {
if (ExpressionLabelUtils.isCallerIPLabel(labelKey)) {
labels.put(labelKey, polarisContextProperties.getLocalIpAddress());
}
}
return labels;
}
}

@ -84,12 +84,12 @@ public class RouterRuleLabelResolverTest {
Set<String> resolvedExpressionLabelKeys = resolver.getExpressionLabelKeys(testNamespace, testSourceService, testDstService);
Assert.assertNotNull(resolvedExpressionLabelKeys);
Assert.assertEquals(5, resolvedExpressionLabelKeys.size());
Assert.assertEquals(6, resolvedExpressionLabelKeys.size());
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey1));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey2));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey3));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey4));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey5));
Assert.assertFalse(resolvedExpressionLabelKeys.contains(invalidKey));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(invalidKey));
}
}

@ -33,6 +33,7 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver;
import feign.RequestTemplate;
@ -61,12 +62,14 @@ public class RouterLabelFeignInterceptorTest {
private RouterRuleLabelResolver routerRuleLabelResolver;
@Mock
private FeignRouterLabelResolver routerLabelResolver;
@Mock
private PolarisContextProperties polarisContextProperties;
@Test
public void testResolveRouterLabel() throws UnsupportedEncodingException {
RouterLabelFeignInterceptor routerLabelFeignInterceptor = new RouterLabelFeignInterceptor(
Collections.singletonList(routerLabelResolver),
staticMetadataManager, routerRuleLabelResolver);
staticMetadataManager, routerRuleLabelResolver, polarisContextProperties);
// mock request template
RequestTemplate requestTemplate = new RequestTemplate();

@ -33,6 +33,7 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.assertj.core.api.Assertions;
@ -68,6 +69,8 @@ public class RouterLabelRestTemplateInterceptorTest {
private StaticMetadataManager staticMetadataManager;
@Mock
private RouterRuleLabelResolver routerRuleLabelResolver;
@Mock
private PolarisContextProperties polarisContextProperties;
@BeforeClass
public static void beforeClass() {
@ -120,7 +123,7 @@ public class RouterLabelRestTemplateInterceptorTest {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
RouterLabelRestTemplateInterceptor routerLabelRestTemplateInterceptor = new RouterLabelRestTemplateInterceptor(
Collections.singletonList(routerLabelResolver), staticMetadataManager, routerRuleLabelResolver);
Collections.singletonList(routerLabelResolver), staticMetadataManager, routerRuleLabelResolver, polarisContextProperties);
routerLabelRestTemplateInterceptor.setLabelsToHeaders(request, null, calleeService);

@ -33,6 +33,7 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.junit.AfterClass;
@ -81,6 +82,8 @@ public class PolarisReactiveLoadBalancerClientFilterTest {
private GatewayLoadBalancerProperties gatewayLoadBalancerProperties;
@Mock
private LoadBalancerProperties loadBalancerProperties;
@Mock
private PolarisContextProperties polarisContextProperties;
@BeforeClass
public static void beforeClass() {
@ -110,7 +113,7 @@ public class PolarisReactiveLoadBalancerClientFilterTest {
public void testGenRouterHttpHeaders() throws UnsupportedEncodingException {
PolarisReactiveLoadBalancerClientFilter filter = new PolarisReactiveLoadBalancerClientFilter(loadBalancerClientFactory,
gatewayLoadBalancerProperties, loadBalancerProperties, staticMetadataManager, routerRuleLabelResolver,
Lists.newArrayList(routerLabelResolver));
Lists.newArrayList(routerLabelResolver), polarisContextProperties);
Map<String, String> localMetadata = new HashMap<>();
localMetadata.put("env", "blue");

@ -18,7 +18,9 @@
package com.tencent.cloud.common.util.expresstion;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
@ -33,69 +35,105 @@ import org.springframework.util.CollectionUtils;
*/
public final class ExpressionLabelUtils {
/**
* the expression prefix of header label.
*/
public static final String LABEL_HEADER_PREFIX = "${http.header.";
/**
* the length of expression header label prefix.
*/
public static final int LABEL_HEADER_PREFIX_LEN = LABEL_HEADER_PREFIX.length();
/**
* the expression prefix of query.
*/
public static final String LABEL_QUERY_PREFIX = "${http.query.";
/**
* the length of expression query label prefix.
*/
public static final int LABEL_QUERY_PREFIX_LEN = LABEL_QUERY_PREFIX.length();
/**
* the expression prefix of cookie.
*/
public static final String LABEL_COOKIE_PREFIX = "${http.cookie.";
/**
* the length of expression cookie label prefix.
*/
public static final int LABEL_COOKIE_PREFIX_LEN = LABEL_COOKIE_PREFIX.length();
/**
* the expression of method.
*/
public static final String LABEL_METHOD = "${http.method}";
/**
* 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 = "}";
private static final List<ExpressionParser> EXPRESSION_PARSERS;
static {
EXPRESSION_PARSERS = new ArrayList<>(2);
EXPRESSION_PARSERS.add(new ExpressionParserV1());
EXPRESSION_PARSERS.add(new ExpressionParserV2());
}
private ExpressionLabelUtils() {
}
public static boolean isExpressionLabel(String labelKey) {
if (StringUtils.isEmpty(labelKey)) {
return false;
public static boolean isExpressionLabel(String expression) {
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isExpressionLabel(expression)) {
return true;
}
}
return StringUtils.startsWith(labelKey, LABEL_PREFIX) && StringUtils.endsWith(labelKey, LABEL_SUFFIX);
return false;
}
public static boolean isHeaderLabel(String expression) {
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isHeaderLabel(expression)) {
return true;
}
}
return false;
}
public static String parseHeaderKey(String expression) {
return expression.substring(LABEL_HEADER_PREFIX_LEN, expression.length() - 1);
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isHeaderLabel(expression)) {
return parser.parseHeaderKey(expression);
}
}
return "";
}
public static boolean isQueryLabel(String expression) {
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isQueryLabel(expression)) {
return true;
}
}
return false;
}
public static String parseQueryKey(String expression) {
return expression.substring(LABEL_QUERY_PREFIX_LEN, expression.length() - 1);
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isQueryLabel(expression)) {
return parser.parseQueryKey(expression);
}
}
return "";
}
public static boolean isCookieLabel(String expression) {
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isCookieLabel(expression)) {
return true;
}
}
return false;
}
public static String parseCookieKey(String expression) {
return expression.substring(LABEL_COOKIE_PREFIX_LEN, expression.length() - 1);
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isCookieLabel(expression)) {
return parser.parseCookieKey(expression);
}
}
return "";
}
public static boolean isMethodLabel(String expression) {
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isMethodLabel(expression)) {
return true;
}
}
return false;
}
public static boolean isUriLabel(String expression) {
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isUriLabel(expression)) {
return true;
}
}
return false;
}
public static boolean isCallerIPLabel(String expression) {
for (ExpressionParser parser : EXPRESSION_PARSERS) {
if (parser.isCallerIPLabel(expression)) {
return true;
}
}
return false;
}
public static String getQueryValue(String queryString, String queryKey) {

@ -0,0 +1,95 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util.expresstion;
/**
* Expression parser for rate limit rule and router rule.
* @author lepdou 2022-10-08
*/
public interface ExpressionParser {
/**
* whether is valid expression.
* @param expression the expression
* @return true if is valid
*/
boolean isExpressionLabel(String expression);
/**
* whether is header expression.
* @param expression the expression
* @return true if is header expression
*/
boolean isHeaderLabel(String expression);
/**
* parse label from header expression.
* @param expression the expression
* @return parsed key from expression
*/
String parseHeaderKey(String expression);
/**
* whether is query expression.
* @param expression the expression
* @return true if is query expression
*/
boolean isQueryLabel(String expression);
/**
* parse label from query expression.
* @param expression the expression
* @return parsed key from expression
*/
String parseQueryKey(String expression);
/**
* whether is cookie expression.
* @param expression the expression
* @return true if is cookie expression
*/
boolean isCookieLabel(String expression);
/**
* parse label from cookie expression.
* @param expression the expression
* @return parsed cookie key from expression
*/
String parseCookieKey(String expression);
/**
* whether is method expression.
* @param expression the expression
* @return true if is method expression
*/
boolean isMethodLabel(String expression);
/**
* whether is uri/path expression.
* @param expression the expression
* @return true if is uri/path expression
*/
boolean isUriLabel(String expression);
/**
* whether is caller ip expression.
* @param expression the expression
* @return true if is caller ip expression
*/
boolean isCallerIPLabel(String expression);
}

@ -0,0 +1,93 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util.expresstion;
import org.apache.commons.lang.StringUtils;
/**
* Old custom expression resolver like ${http.query.key}${http.header.key}.
* New expression like $query.key$header.key
* @author lepdou 2022-10-08
*/
public class ExpressionParserV1 implements ExpressionParser {
private static final String LABEL_HEADER_PREFIX = "${http.header.";
private static final int LABEL_HEADER_PREFIX_LEN = LABEL_HEADER_PREFIX.length();
private static final String LABEL_QUERY_PREFIX = "${http.query.";
private static final int LABEL_QUERY_PREFIX_LEN = LABEL_QUERY_PREFIX.length();
private static final String LABEL_COOKIE_PREFIX = "${http.cookie.";
private static final int LABEL_COOKIE_PREFIX_LEN = LABEL_COOKIE_PREFIX.length();
private static final String LABEL_METHOD = "${http.method}";
private static final String LABEL_URI = "${http.uri}";
private static final String LABEL_CALLER_IP = "${http.caller.ip}";
private static final String LABEL_PREFIX = "${";
private static final String LABEL_SUFFIX = "}";
@Override
public boolean isExpressionLabel(String labelKey) {
if (StringUtils.isEmpty(labelKey)) {
return false;
}
return StringUtils.startsWith(labelKey, LABEL_PREFIX) && StringUtils.endsWith(labelKey, LABEL_SUFFIX);
}
@Override
public boolean isHeaderLabel(String expression) {
return StringUtils.startsWith(expression, LABEL_HEADER_PREFIX) && StringUtils.endsWith(expression, LABEL_SUFFIX);
}
@Override
public String parseHeaderKey(String expression) {
return expression.substring(LABEL_HEADER_PREFIX_LEN, expression.length() - 1);
}
@Override
public boolean isQueryLabel(String expression) {
return StringUtils.startsWith(expression, LABEL_QUERY_PREFIX) && StringUtils.endsWith(expression, LABEL_SUFFIX);
}
@Override
public String parseQueryKey(String expression) {
return expression.substring(LABEL_QUERY_PREFIX_LEN, expression.length() - 1);
}
@Override
public boolean isCookieLabel(String expression) {
return StringUtils.startsWith(expression, LABEL_COOKIE_PREFIX) && StringUtils.endsWith(expression, LABEL_SUFFIX);
}
@Override
public String parseCookieKey(String expression) {
return expression.substring(LABEL_COOKIE_PREFIX_LEN, expression.length() - 1);
}
@Override
public boolean isMethodLabel(String expression) {
return StringUtils.equalsIgnoreCase(expression, LABEL_METHOD);
}
@Override
public boolean isUriLabel(String expression) {
return StringUtils.equalsIgnoreCase(expression, LABEL_URI);
}
@Override
public boolean isCallerIPLabel(String expression) {
return StringUtils.equalsIgnoreCase(expression, LABEL_CALLER_IP);
}
}

@ -0,0 +1,88 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util.expresstion;
import org.apache.commons.lang.StringUtils;
/**
* New custom expression resolver like $query.key$header.key.
* Old expression like ${http.query.key}${http.header.key}
* @author lepdou 2022-10-08
*/
public class ExpressionParserV2 implements ExpressionParser {
private static final String LABEL_HEADER_PREFIX = "$header.";
private static final int LABEL_HEADER_PREFIX_LEN = LABEL_HEADER_PREFIX.length();
private static final String LABEL_QUERY_PREFIX = "$query.";
private static final int LABEL_QUERY_PREFIX_LEN = LABEL_QUERY_PREFIX.length();
private static final String LABEL_METHOD = "$method";
private static final String LABEL_PATH = "$path";
private static final String LABEL_CALLER_IP = "$caller_ip";
private static final String LABEL_PREFIX = "$";
@Override
public boolean isExpressionLabel(String expression) {
return StringUtils.startsWith(expression, LABEL_PREFIX);
}
@Override
public boolean isHeaderLabel(String expression) {
return StringUtils.startsWith(expression, LABEL_HEADER_PREFIX);
}
@Override
public String parseHeaderKey(String expression) {
return StringUtils.substring(expression, LABEL_HEADER_PREFIX_LEN);
}
@Override
public boolean isQueryLabel(String expression) {
return StringUtils.startsWith(expression, LABEL_QUERY_PREFIX);
}
@Override
public String parseQueryKey(String expression) {
return StringUtils.substring(expression, LABEL_QUERY_PREFIX_LEN);
}
@Override
public boolean isCookieLabel(String expression) {
return false;
}
@Override
public String parseCookieKey(String expression) {
return null;
}
@Override
public boolean isMethodLabel(String expression) {
return StringUtils.equalsIgnoreCase(expression, LABEL_METHOD);
}
@Override
public boolean isUriLabel(String expression) {
return StringUtils.equalsIgnoreCase(expression, LABEL_PATH);
}
@Override
public boolean isCallerIPLabel(String expression) {
return StringUtils.equalsIgnoreCase(expression, LABEL_CALLER_IP);
}
}

@ -50,31 +50,31 @@ public final class ServletExpressionLabelUtils {
if (!ExpressionLabelUtils.isExpressionLabel(labelKey)) {
continue;
}
if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_HEADER_PREFIX)) {
if (ExpressionLabelUtils.isHeaderLabel(labelKey)) {
String headerKey = ExpressionLabelUtils.parseHeaderKey(labelKey);
if (StringUtils.isBlank(headerKey)) {
continue;
}
labels.put(labelKey, request.getHeader(headerKey));
}
else if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_QUERY_PREFIX)) {
else if (ExpressionLabelUtils.isQueryLabel(labelKey)) {
String queryKey = ExpressionLabelUtils.parseQueryKey(labelKey);
if (StringUtils.isBlank(queryKey)) {
continue;
}
labels.put(labelKey, ExpressionLabelUtils.getQueryValue(request.getQueryString(), queryKey));
}
else if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_COOKIE_PREFIX)) {
else if (ExpressionLabelUtils.isCookieLabel(labelKey)) {
String cookieKey = ExpressionLabelUtils.parseCookieKey(labelKey);
if (StringUtils.isBlank(cookieKey)) {
continue;
}
labels.put(labelKey, getCookieValue(request.getCookies(), cookieKey));
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_METHOD, labelKey)) {
else if (ExpressionLabelUtils.isMethodLabel(labelKey)) {
labels.put(labelKey, request.getMethod());
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_URI, labelKey)) {
else if (ExpressionLabelUtils.isUriLabel(labelKey)) {
labels.put(labelKey, request.getRequestURI());
}
}

@ -53,31 +53,31 @@ public final class SpringWebExpressionLabelUtils {
if (!ExpressionLabelUtils.isExpressionLabel(labelKey)) {
continue;
}
if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_HEADER_PREFIX)) {
if (ExpressionLabelUtils.isHeaderLabel(labelKey)) {
String headerKey = ExpressionLabelUtils.parseHeaderKey(labelKey);
if (StringUtils.isBlank(headerKey)) {
continue;
}
labels.put(labelKey, getHeaderValue(exchange.getRequest(), headerKey));
}
else if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_QUERY_PREFIX)) {
else if (ExpressionLabelUtils.isQueryLabel(labelKey)) {
String queryKey = ExpressionLabelUtils.parseQueryKey(labelKey);
if (StringUtils.isBlank(queryKey)) {
continue;
}
labels.put(labelKey, getQueryValue(exchange.getRequest(), queryKey));
}
else if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_COOKIE_PREFIX)) {
else if (ExpressionLabelUtils.isCookieLabel(labelKey)) {
String cookieKey = ExpressionLabelUtils.parseCookieKey(labelKey);
if (StringUtils.isBlank(cookieKey)) {
continue;
}
labels.put(labelKey, getCookieValue(exchange.getRequest(), cookieKey));
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_METHOD, labelKey)) {
else if (ExpressionLabelUtils.isMethodLabel(labelKey)) {
labels.put(labelKey, exchange.getRequest().getMethodValue());
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_URI, labelKey)) {
else if (ExpressionLabelUtils.isUriLabel(labelKey)) {
labels.put(labelKey, exchange.getRequest().getURI().getPath());
}
}
@ -96,24 +96,24 @@ public final class SpringWebExpressionLabelUtils {
if (!ExpressionLabelUtils.isExpressionLabel(labelKey)) {
continue;
}
if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_HEADER_PREFIX)) {
if (ExpressionLabelUtils.isHeaderLabel(labelKey)) {
String headerKey = ExpressionLabelUtils.parseHeaderKey(labelKey);
if (StringUtils.isBlank(headerKey)) {
continue;
}
labels.put(labelKey, getHeaderValue(request, headerKey));
}
else if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_QUERY_PREFIX)) {
else if (ExpressionLabelUtils.isQueryLabel(labelKey)) {
String queryKey = ExpressionLabelUtils.parseQueryKey(labelKey);
if (StringUtils.isBlank(queryKey)) {
continue;
}
labels.put(labelKey, getQueryValue(request, queryKey));
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_METHOD, labelKey)) {
else if (ExpressionLabelUtils.isMethodLabel(labelKey)) {
labels.put(labelKey, request.getMethodValue());
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_URI, labelKey)) {
else if (ExpressionLabelUtils.isUriLabel(labelKey)) {
labels.put(labelKey, request.getURI().getPath());
}
}

@ -71,12 +71,12 @@ public class ExpressionLabelUtilsTest {
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel5));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel1));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel2));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel3));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel4));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel3));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel4));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel5));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel6));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel7));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel8));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel8));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel9));
}

@ -0,0 +1,70 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util;
import com.tencent.cloud.common.util.expresstion.ExpressionParserV1;
import org.junit.Assert;
import org.junit.Test;
/**
* Test for {@link ExpressionParserV1}
* @author lepdou 2022-10-08
*/
public class ExpressionParserV1Test {
@Test
public void testExpressionLabel() {
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}";
ExpressionParserV1 parser = new ExpressionParserV1();
Assert.assertTrue(parser.isExpressionLabel(validLabel1));
Assert.assertTrue(parser.isExpressionLabel(validLabel2));
Assert.assertTrue(parser.isExpressionLabel(validLabel3));
Assert.assertTrue(parser.isExpressionLabel(validLabel4));
Assert.assertTrue(parser.isExpressionLabel(validLabel5));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel1));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel2));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel3));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel4));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel5));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel6));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel7));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel8));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel9));
Assert.assertTrue(parser.isQueryLabel(validLabel1));
Assert.assertTrue(parser.isHeaderLabel(validLabel2));
Assert.assertTrue(parser.isCookieLabel(validLabel3));
Assert.assertTrue(parser.isMethodLabel(validLabel4));
Assert.assertTrue(parser.isUriLabel(validLabel5));
}
}

@ -0,0 +1,74 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util;
import com.tencent.cloud.common.util.expresstion.ExpressionParserV2;
import org.junit.Assert;
import org.junit.Test;
/**
* Test for {@link ExpressionParserV2}
* @author lepdou 2022-10-08
*/
public class ExpressionParserV2Test {
@Test
public void testExpressionLabel() {
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}";
ExpressionParserV2 parser = new ExpressionParserV2();
Assert.assertTrue(parser.isExpressionLabel(validLabel1));
Assert.assertTrue(parser.isExpressionLabel(validLabel2));
Assert.assertTrue(parser.isExpressionLabel(validLabel3));
Assert.assertTrue(parser.isExpressionLabel(validLabel4));
Assert.assertTrue(parser.isExpressionLabel(validLabel5));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel1));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel2));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel3));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel4));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel5));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel6));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel7));
Assert.assertTrue(parser.isExpressionLabel(invalidLabel8));
Assert.assertFalse(parser.isExpressionLabel(invalidLabel9));
Assert.assertFalse(parser.isQueryLabel(validLabel1));
Assert.assertFalse(parser.isHeaderLabel(validLabel2));
Assert.assertFalse(parser.isCookieLabel(validLabel3));
Assert.assertFalse(parser.isMethodLabel(validLabel4));
Assert.assertFalse(parser.isUriLabel(validLabel5));
Assert.assertTrue(parser.isHeaderLabel("$header.userId"));
Assert.assertTrue(parser.isMethodLabel("$method"));
Assert.assertTrue(parser.isQueryLabel("$query.userId"));
}
}

@ -76,6 +76,7 @@ public class PolarisContextProperties {
String defaultHost = this.localIpAddress;
if (StringUtils.isBlank(localIpAddress)) {
defaultHost = ipAddressSupplier.get();
this.localIpAddress = defaultHost;
}
configuration.getGlobal().getAPI().setBindIP(defaultHost);

Loading…
Cancel
Save