optimize router label resolver spi (#449)

pull/450/head
lepdou 2 years ago committed by GitHub
parent 3c4bddd6d1
commit 7f27e79d5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,3 +9,4 @@
- [Optimize: add EncodeTransferMedataRestTemplateInterceptor to RestTemplate](https://github.com/Tencent/spring-cloud-tencent/pull/434) - [Optimize: add EncodeTransferMedataRestTemplateInterceptor to RestTemplate](https://github.com/Tencent/spring-cloud-tencent/pull/434)
- [feat:enhance Feign and RestTemplate and support Polaris monitor.](https://github.com/Tencent/spring-cloud-tencent/pull/435) - [feat:enhance Feign and RestTemplate and support Polaris monitor.](https://github.com/Tencent/spring-cloud-tencent/pull/435)
- [Optimize: Specification apollo code reference notes](https://github.com/Tencent/spring-cloud-tencent/pull/442) - [Optimize: Specification apollo code reference notes](https://github.com/Tencent/spring-cloud-tencent/pull/442)
- [Optimize: optimize router label resolver spi](https://github.com/Tencent/spring-cloud-tencent/pull/449)

@ -24,7 +24,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.BeanFactoryUtils; import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.scg.PolarisLoadBalancerClientFilter; import com.tencent.cloud.polaris.router.scg.PolarisLoadBalancerClientFilter;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
@ -56,7 +56,7 @@ public class LoadBalancerClientFilterBeanPostProcessor implements BeanPostProces
// Replaces the default LoadBalancerClientFilter implementation and returns a custom PolarisLoadBalancerClientFilter // Replaces the default LoadBalancerClientFilter implementation and returns a custom PolarisLoadBalancerClientFilter
LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class); LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class);
LoadBalancerProperties loadBalancerProperties = this.factory.getBean(LoadBalancerProperties.class); LoadBalancerProperties loadBalancerProperties = this.factory.getBean(LoadBalancerProperties.class);
List<RouterLabelResolver> routerLabelResolvers = BeanFactoryUtils.getBeans(factory, RouterLabelResolver.class); List<SpringWebRouterLabelResolver> routerLabelResolvers = BeanFactoryUtils.getBeans(factory, SpringWebRouterLabelResolver.class);
MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class); MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class);
RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class); RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class);

@ -24,7 +24,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.BeanFactoryUtils; import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerInterceptor; import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
@ -57,7 +57,7 @@ public class LoadBalancerInterceptorBeanPostProcessor implements BeanPostProcess
// Replaces the default LoadBalancerInterceptor implementation and returns a custom PolarisLoadBalancerInterceptor // Replaces the default LoadBalancerInterceptor implementation and returns a custom PolarisLoadBalancerInterceptor
LoadBalancerRequestFactory requestFactory = this.factory.getBean(LoadBalancerRequestFactory.class); LoadBalancerRequestFactory requestFactory = this.factory.getBean(LoadBalancerRequestFactory.class);
LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class); LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class);
List<RouterLabelResolver> routerLabelResolvers = BeanFactoryUtils.getBeans(factory, RouterLabelResolver.class); List<SpringWebRouterLabelResolver> routerLabelResolvers = BeanFactoryUtils.getBeans(factory, SpringWebRouterLabelResolver.class);
MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class); MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class);
RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class); RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class);

@ -24,7 +24,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory; import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory;
import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor; import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.netflix.ribbon.RibbonClients; import org.springframework.cloud.netflix.ribbon.RibbonClients;
@ -45,7 +45,7 @@ import org.springframework.lang.Nullable;
public class FeignAutoConfiguration { public class FeignAutoConfiguration {
@Bean @Bean
public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List<RouterLabelResolver> routerLabelResolvers, public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List<FeignRouterLabelResolver> routerLabelResolvers,
MetadataLocalProperties metadataLocalProperties, MetadataLocalProperties metadataLocalProperties,
RouterRuleLabelResolver routerRuleLabelResolver) { RouterRuleLabelResolver routerRuleLabelResolver) {
return new RouterLabelFeignInterceptor(routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver); return new RouterLabelFeignInterceptor(routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver);

@ -33,7 +33,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.router.RouterConstants; import com.tencent.cloud.polaris.router.RouterConstants;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver;
import feign.RequestInterceptor; import feign.RequestInterceptor;
import feign.RequestTemplate; import feign.RequestTemplate;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -52,11 +52,11 @@ import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered { public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered {
private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelFeignInterceptor.class); private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelFeignInterceptor.class);
private final List<RouterLabelResolver> routerLabelResolvers; private final List<FeignRouterLabelResolver> routerLabelResolvers;
private final MetadataLocalProperties metadataLocalProperties; private final MetadataLocalProperties metadataLocalProperties;
private final RouterRuleLabelResolver routerRuleLabelResolver; private final RouterRuleLabelResolver routerRuleLabelResolver;
public RouterLabelFeignInterceptor(List<RouterLabelResolver> routerLabelResolvers, public RouterLabelFeignInterceptor(List<FeignRouterLabelResolver> routerLabelResolvers,
MetadataLocalProperties metadataLocalProperties, MetadataLocalProperties metadataLocalProperties,
RouterRuleLabelResolver routerRuleLabelResolver) { RouterRuleLabelResolver routerRuleLabelResolver) {
if (!CollectionUtils.isEmpty(routerLabelResolvers)) { if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
@ -82,14 +82,16 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered
// labels from rule expression // labels from rule expression
String peerServiceName = requestTemplate.feignTarget().name(); String peerServiceName = requestTemplate.feignTarget().name();
Map<String, String> ruleExpressionLabels = getRuleExpressionLabels(requestTemplate, peerServiceName); Set<String> expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE, peerServiceName);
Map<String, String> ruleExpressionLabels = getRuleExpressionLabels(requestTemplate, expressionLabelKeys);
labels.putAll(ruleExpressionLabels); labels.putAll(ruleExpressionLabels);
// labels from request // labels from custom spi
if (!CollectionUtils.isEmpty(routerLabelResolvers)) { if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
routerLabelResolvers.forEach(resolver -> { routerLabelResolvers.forEach(resolver -> {
try { try {
Map<String, String> customResolvedLabels = resolver.resolve(requestTemplate); Map<String, String> customResolvedLabels = resolver.resolve(requestTemplate, expressionLabelKeys);
if (!CollectionUtils.isEmpty(customResolvedLabels)) { if (!CollectionUtils.isEmpty(customResolvedLabels)) {
labels.putAll(customResolvedLabels); labels.putAll(customResolvedLabels);
} }
@ -121,9 +123,7 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered
requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER, encodedLabelsContent); requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER, encodedLabelsContent);
} }
private Map<String, String> getRuleExpressionLabels(RequestTemplate requestTemplate, String peerService) { private Map<String, String> getRuleExpressionLabels(RequestTemplate requestTemplate, Set<String> labelKeys) {
Set<String> labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE, peerService);
if (CollectionUtils.isEmpty(labelKeys)) { if (CollectionUtils.isEmpty(labelKeys)) {
return Collections.emptyMap(); return Collections.emptyMap();

@ -33,7 +33,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils; import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils;
import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.PolarisRouterContext;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -59,7 +59,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
private final LoadBalancerClient loadBalancer; private final LoadBalancerClient loadBalancer;
private final LoadBalancerRequestFactory requestFactory; private final LoadBalancerRequestFactory requestFactory;
private final List<RouterLabelResolver> routerLabelResolvers; private final List<SpringWebRouterLabelResolver> routerLabelResolvers;
private final MetadataLocalProperties metadataLocalProperties; private final MetadataLocalProperties metadataLocalProperties;
private final RouterRuleLabelResolver routerRuleLabelResolver; private final RouterRuleLabelResolver routerRuleLabelResolver;
@ -67,7 +67,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
public PolarisLoadBalancerInterceptor(LoadBalancerClient loadBalancer, public PolarisLoadBalancerInterceptor(LoadBalancerClient loadBalancer,
LoadBalancerRequestFactory requestFactory, LoadBalancerRequestFactory requestFactory,
List<RouterLabelResolver> routerLabelResolvers, List<SpringWebRouterLabelResolver> routerLabelResolvers,
MetadataLocalProperties metadataLocalProperties, MetadataLocalProperties metadataLocalProperties,
RouterRuleLabelResolver routerRuleLabelResolver) { RouterRuleLabelResolver routerRuleLabelResolver) {
super(loadBalancer, requestFactory); super(loadBalancer, requestFactory);
@ -110,7 +110,9 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
Map<String, String> labels = new HashMap<>(metadataLocalProperties.getContent()); Map<String, String> labels = new HashMap<>(metadataLocalProperties.getContent());
// labels from rule expression // labels from rule expression
Map<String, String> ruleExpressionLabels = getExpressionLabels(request, peerServiceName); Set<String> expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE, peerServiceName);
Map<String, String> ruleExpressionLabels = getExpressionLabels(request, expressionLabelKeys);
if (!CollectionUtils.isEmpty(ruleExpressionLabels)) { if (!CollectionUtils.isEmpty(ruleExpressionLabels)) {
labels.putAll(ruleExpressionLabels); labels.putAll(ruleExpressionLabels);
} }
@ -119,7 +121,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
if (!CollectionUtils.isEmpty(routerLabelResolvers)) { if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
routerLabelResolvers.forEach(resolver -> { routerLabelResolvers.forEach(resolver -> {
try { try {
Map<String, String> customResolvedLabels = resolver.resolve(request, body); Map<String, String> customResolvedLabels = resolver.resolve(request, body, expressionLabelKeys);
if (!CollectionUtils.isEmpty(customResolvedLabels)) { if (!CollectionUtils.isEmpty(customResolvedLabels)) {
labels.putAll(customResolvedLabels); labels.putAll(customResolvedLabels);
} }
@ -143,10 +145,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
return routerContext; return routerContext;
} }
private Map<String, String> getExpressionLabels(HttpRequest request, String peerServiceName) { private Map<String, String> getExpressionLabels(HttpRequest request, Set<String> labelKeys) {
Set<String> labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE, peerServiceName);
if (CollectionUtils.isEmpty(labelKeys)) { if (CollectionUtils.isEmpty(labelKeys)) {
return Collections.emptyMap(); return Collections.emptyMap();
} }

@ -32,7 +32,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils; import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils;
import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.PolarisRouterContext;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -57,14 +57,14 @@ public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter {
private final MetadataLocalProperties metadataLocalProperties; private final MetadataLocalProperties metadataLocalProperties;
private final RouterRuleLabelResolver routerRuleLabelResolver; private final RouterRuleLabelResolver routerRuleLabelResolver;
private final List<RouterLabelResolver> routerLabelResolvers; private final List<SpringWebRouterLabelResolver> routerLabelResolvers;
private final boolean isRibbonLoadBalanceClient; private final boolean isRibbonLoadBalanceClient;
public PolarisLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties, public PolarisLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties,
MetadataLocalProperties metadataLocalProperties, MetadataLocalProperties metadataLocalProperties,
RouterRuleLabelResolver routerRuleLabelResolver, RouterRuleLabelResolver routerRuleLabelResolver,
List<RouterLabelResolver> routerLabelResolvers) { List<SpringWebRouterLabelResolver> routerLabelResolvers) {
super(loadBalancer, properties); super(loadBalancer, properties);
this.metadataLocalProperties = metadataLocalProperties; this.metadataLocalProperties = metadataLocalProperties;
this.routerRuleLabelResolver = routerRuleLabelResolver; this.routerRuleLabelResolver = routerRuleLabelResolver;
@ -99,7 +99,9 @@ public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter {
Map<String, String> labels = new HashMap<>(metadataLocalProperties.getContent()); Map<String, String> labels = new HashMap<>(metadataLocalProperties.getContent());
// labels from rule expression // labels from rule expression
Map<String, String> ruleExpressionLabels = getExpressionLabels(exchange, peerServiceName); Set<String> expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE, peerServiceName);
Map<String, String> ruleExpressionLabels = getExpressionLabels(exchange, expressionLabelKeys);
if (!CollectionUtils.isEmpty(ruleExpressionLabels)) { if (!CollectionUtils.isEmpty(ruleExpressionLabels)) {
labels.putAll(ruleExpressionLabels); labels.putAll(ruleExpressionLabels);
} }
@ -108,7 +110,7 @@ public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter {
if (!CollectionUtils.isEmpty(routerLabelResolvers)) { if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
routerLabelResolvers.forEach(resolver -> { routerLabelResolvers.forEach(resolver -> {
try { try {
Map<String, String> customResolvedLabels = resolver.resolve(exchange); Map<String, String> customResolvedLabels = resolver.resolve(exchange, expressionLabelKeys);
if (!CollectionUtils.isEmpty(customResolvedLabels)) { if (!CollectionUtils.isEmpty(customResolvedLabels)) {
labels.putAll(customResolvedLabels); labels.putAll(customResolvedLabels);
} }
@ -132,10 +134,7 @@ public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter {
return routerContext; return routerContext;
} }
private Map<String, String> getExpressionLabels(ServerWebExchange exchange, String peerServiceName) { private Map<String, String> getExpressionLabels(ServerWebExchange exchange, Set<String> labelKeys) {
Set<String> labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE, peerServiceName);
if (CollectionUtils.isEmpty(labelKeys)) { if (CollectionUtils.isEmpty(labelKeys)) {
return Collections.emptyMap(); return Collections.emptyMap();
} }

@ -0,0 +1,41 @@
/*
* 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.polaris.router.spi;
import java.util.Map;
import java.util.Set;
import feign.RequestTemplate;
import org.springframework.core.Ordered;
/**
* Router label resolver for feign request.
* @author lepdou 2022-07-20
*/
public interface FeignRouterLabelResolver extends Ordered {
/**
* Resolve labels from feign request. User can customize expression parser to extract labels.
*
* @param requestTemplate the feign request.
* @param expressionLabelKeys the expression labels which are configured in router rule.
* @return resolved labels
*/
Map<String, String> resolve(RequestTemplate requestTemplate, Set<String> expressionLabelKeys);
}

@ -0,0 +1,57 @@
/*
* 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.polaris.router.spi;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.springframework.core.Ordered;
import org.springframework.http.HttpRequest;
import org.springframework.web.server.ServerWebExchange;
/**
* Router label resolver for spring web http request.
* @author lepdou 2022-07-20
*/
public interface SpringWebRouterLabelResolver extends Ordered {
/**
* resolve labels from rest template request. User can customize expression parser to extract labels.
*
* @param request the rest template request.
* @param body the rest template request body.
* @param expressionLabelKeys the expression labels which are configured in router rule.
* @return resolved labels
*/
default Map<String, String> resolve(HttpRequest request, byte[] body, Set<String> expressionLabelKeys) {
return Collections.emptyMap();
}
/**
* resolve labels from server web exchange. User can customize expression parser to extract labels.
*
* @param exchange the server web exchange.
* @param expressionLabelKeys the expression labels which are configured in router rule.
* @return resolved labels
*/
default Map<String, String> resolve(ServerWebExchange exchange, Set<String> expressionLabelKeys) {
return Collections.emptyMap();
}
}

@ -59,11 +59,13 @@ public class RouterRuleLabelResolverTest {
String validKey2 = "${http.query.name}"; String validKey2 = "${http.query.name}";
String validKey3 = "${http.method}"; String validKey3 = "${http.method}";
String validKey4 = "${http.uri}"; String validKey4 = "${http.uri}";
String invalidKey = "${http.expression.wrong}"; String validKey5 = "${http.body.customkey}";
String invalidKey = "$http.expression.wrong}";
labels.put(validKey1, matchString); labels.put(validKey1, matchString);
labels.put(validKey2, matchString); labels.put(validKey2, matchString);
labels.put(validKey3, matchString); labels.put(validKey3, matchString);
labels.put(validKey4, matchString); labels.put(validKey4, matchString);
labels.put(validKey5, matchString);
labels.put(invalidKey, matchString); labels.put(invalidKey, matchString);
RoutingProto.Source source1 = RoutingProto.Source.newBuilder().putAllMetadata(labels).build(); RoutingProto.Source source1 = RoutingProto.Source.newBuilder().putAllMetadata(labels).build();
@ -83,11 +85,12 @@ public class RouterRuleLabelResolverTest {
Set<String> resolvedExpressionLabelKeys = resolver.getExpressionLabelKeys(testNamespace, testSourceService, testDstService); Set<String> resolvedExpressionLabelKeys = resolver.getExpressionLabelKeys(testNamespace, testSourceService, testDstService);
Assert.assertNotNull(resolvedExpressionLabelKeys); Assert.assertNotNull(resolvedExpressionLabelKeys);
Assert.assertEquals(4, resolvedExpressionLabelKeys.size()); Assert.assertEquals(5, resolvedExpressionLabelKeys.size());
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey1)); Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey1));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey2)); Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey2));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey3)); Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey3));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey4)); Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey4));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey5));
Assert.assertFalse(resolvedExpressionLabelKeys.contains(invalidKey)); Assert.assertFalse(resolvedExpressionLabelKeys.contains(invalidKey));
} }
} }

@ -34,7 +34,7 @@ import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.router.RouterConstants; import com.tencent.cloud.polaris.router.RouterConstants;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver;
import feign.RequestTemplate; import feign.RequestTemplate;
import feign.Target; import feign.Target;
import org.junit.Assert; import org.junit.Assert;
@ -62,7 +62,7 @@ public class RouterLabelFeignInterceptorTest {
@Mock @Mock
private RouterRuleLabelResolver routerRuleLabelResolver; private RouterRuleLabelResolver routerRuleLabelResolver;
@Mock @Mock
private RouterLabelResolver routerLabelResolver; private FeignRouterLabelResolver routerLabelResolver;
@Test @Test
public void testResolveRouterLabel() { public void testResolveRouterLabel() {
@ -96,12 +96,6 @@ public class RouterLabelFeignInterceptorTest {
try (MockedStatic<MetadataContextHolder> mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) { try (MockedStatic<MetadataContextHolder> mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext); mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
// mock custom resolved labels from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k2", "v2");
customResolvedLabels.put("k3", "v3");
when(routerLabelResolver.resolve(requestTemplate)).thenReturn(customResolvedLabels);
// mock expression rule labels // mock expression rule labels
Set<String> expressionKeys = new HashSet<>(); Set<String> expressionKeys = new HashSet<>();
expressionKeys.add("${http.header.uid}"); expressionKeys.add("${http.header.uid}");
@ -109,6 +103,12 @@ public class RouterLabelFeignInterceptorTest {
when(routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, when(routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE, peerService)).thenReturn(expressionKeys); MetadataContext.LOCAL_SERVICE, peerService)).thenReturn(expressionKeys);
// mock custom resolved labels from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k2", "v2");
customResolvedLabels.put("k3", "v3");
when(routerLabelResolver.resolve(requestTemplate, expressionKeys)).thenReturn(customResolvedLabels);
// mock local metadata // mock local metadata
Map<String, String> localMetadata = new HashMap<>(); Map<String, String> localMetadata = new HashMap<>();
localMetadata.put("k3", "v31"); localMetadata.put("k3", "v31");

@ -22,7 +22,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.BeanFactoryUtils; import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.beanprocessor.LoadBalancerInterceptorBeanPostProcessor; import com.tencent.cloud.polaris.router.beanprocessor.LoadBalancerInterceptorBeanPostProcessor;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -65,7 +65,7 @@ public class PolarisLoadBalancerBeanPostProcessorTest {
when(beanFactory.getBean(RouterRuleLabelResolver.class)).thenReturn(routerRuleLabelResolver); when(beanFactory.getBean(RouterRuleLabelResolver.class)).thenReturn(routerRuleLabelResolver);
try (MockedStatic<BeanFactoryUtils> mockedBeanFactoryUtils = Mockito.mockStatic(BeanFactoryUtils.class)) { try (MockedStatic<BeanFactoryUtils> mockedBeanFactoryUtils = Mockito.mockStatic(BeanFactoryUtils.class)) {
mockedBeanFactoryUtils.when(() -> BeanFactoryUtils.getBeans(beanFactory, RouterLabelResolver.class)) mockedBeanFactoryUtils.when(() -> BeanFactoryUtils.getBeans(beanFactory, SpringWebRouterLabelResolver.class))
.thenReturn(null); .thenReturn(null);
LoadBalancerInterceptor loadBalancerInterceptor = new LoadBalancerInterceptor(loadBalancerClient, loadBalancerRequestFactory); LoadBalancerInterceptor loadBalancerInterceptor = new LoadBalancerInterceptor(loadBalancerClient, loadBalancerRequestFactory);

@ -33,7 +33,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.PolarisRouterContext;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -71,7 +71,7 @@ public class PolarisLoadBalancerInterceptorTest {
@Mock @Mock
private LoadBalancerRequestFactory loadBalancerRequestFactory; private LoadBalancerRequestFactory loadBalancerRequestFactory;
@Mock @Mock
private RouterLabelResolver routerLabelResolver; private SpringWebRouterLabelResolver routerLabelResolver;
@Mock @Mock
private MetadataLocalProperties metadataLocalProperties; private MetadataLocalProperties metadataLocalProperties;
@Mock @Mock
@ -89,19 +89,19 @@ public class PolarisLoadBalancerInterceptorTest {
localMetadata.put("k2", "v2"); localMetadata.put("k2", "v2");
when(metadataLocalProperties.getContent()).thenReturn(localMetadata); when(metadataLocalProperties.getContent()).thenReturn(localMetadata);
// mock custom resolved from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k3", "v3");
customResolvedLabels.put("k4", "v4");
when(routerLabelResolver.resolve(request, null)).thenReturn(customResolvedLabels);
// mock expression rule labels // mock expression rule labels
Set<String> expressionKeys = new HashSet<>(); Set<String> expressionKeys = new HashSet<>();
expressionKeys.add("${http.method}"); expressionKeys.add("${http.method}");
expressionKeys.add("${http.uri}"); expressionKeys.add("${http.uri}");
when(routerRuleLabelResolver.getExpressionLabelKeys(callerService, callerService, calleeService)).thenReturn(expressionKeys); when(routerRuleLabelResolver.getExpressionLabelKeys(callerService, callerService, calleeService)).thenReturn(expressionKeys);
// mock custom resolved from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k3", "v3");
customResolvedLabels.put("k4", "v4");
when(routerLabelResolver.resolve(request, null, expressionKeys)).thenReturn(customResolvedLabels);
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn(callerService); .thenReturn(callerService);
@ -127,7 +127,7 @@ public class PolarisLoadBalancerInterceptorTest {
verify(metadataLocalProperties).getContent(); verify(metadataLocalProperties).getContent();
verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService); verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService);
verify(routerLabelResolver).resolve(request, null); verify(routerLabelResolver).resolve(request, null, expressionKeys);
} }
} }
} }
@ -158,7 +158,7 @@ public class PolarisLoadBalancerInterceptorTest {
} }
@Test @Test
public void testRouterContext() throws Exception { public void testRouterContext() {
String callerService = "callerService"; String callerService = "callerService";
String calleeService = "calleeService"; String calleeService = "calleeService";
HttpRequest request = new MockedHttpRequest("http://" + calleeService + "/user/get"); HttpRequest request = new MockedHttpRequest("http://" + calleeService + "/user/get");
@ -169,19 +169,18 @@ public class PolarisLoadBalancerInterceptorTest {
localMetadata.put("k2", "v2"); localMetadata.put("k2", "v2");
when(metadataLocalProperties.getContent()).thenReturn(localMetadata); when(metadataLocalProperties.getContent()).thenReturn(localMetadata);
// mock custom resolved from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k2", "v22");
customResolvedLabels.put("k4", "v4");
when(routerLabelResolver.resolve(request, null)).thenReturn(customResolvedLabels);
// mock expression rule labels // mock expression rule labels
Set<String> expressionKeys = new HashSet<>(); Set<String> expressionKeys = new HashSet<>();
expressionKeys.add("${http.method}"); expressionKeys.add("${http.method}");
expressionKeys.add("${http.uri}"); expressionKeys.add("${http.uri}");
when(routerRuleLabelResolver.getExpressionLabelKeys(callerService, callerService, calleeService)).thenReturn(expressionKeys); when(routerRuleLabelResolver.getExpressionLabelKeys(callerService, callerService, calleeService)).thenReturn(expressionKeys);
// mock custom resolved from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k2", "v22");
customResolvedLabels.put("k4", "v4");
when(routerLabelResolver.resolve(request, null, expressionKeys)).thenReturn(customResolvedLabels);
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn(callerService); .thenReturn(callerService);
@ -206,7 +205,7 @@ public class PolarisLoadBalancerInterceptorTest {
verify(metadataLocalProperties).getContent(); verify(metadataLocalProperties).getContent();
verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService); verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService);
verify(routerLabelResolver).resolve(request, null); verify(routerLabelResolver).resolve(request, null, expressionKeys);
Assert.assertEquals("v1", routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).get("k1")); Assert.assertEquals("v1", routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).get("k1"));
Assert.assertEquals("v22", routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).get("k2")); Assert.assertEquals("v22", routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).get("k2"));

@ -32,7 +32,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.PolarisRouterContext;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -73,7 +73,7 @@ public class PolarisLoadBalancerClientFilterTest {
@Mock @Mock
private RouterRuleLabelResolver routerRuleLabelResolver; private RouterRuleLabelResolver routerRuleLabelResolver;
@Mock @Mock
private RouterLabelResolver routerLabelResolver; private SpringWebRouterLabelResolver routerLabelResolver;
@Mock @Mock
private LoadBalancerClient loadBalancerClient; private LoadBalancerClient loadBalancerClient;
@Mock @Mock
@ -124,7 +124,7 @@ public class PolarisLoadBalancerClientFilterTest {
Map<String, String> customMetadata = new HashMap<>(); Map<String, String> customMetadata = new HashMap<>();
customMetadata.put("k2", "v2"); customMetadata.put("k2", "v2");
when(routerLabelResolver.resolve(webExchange)).thenReturn(customMetadata); when(routerLabelResolver.resolve(webExchange, expressionLabelKeys)).thenReturn(customMetadata);
PolarisRouterContext routerContext = polarisLoadBalancerClientFilter.genRouterContext(webExchange, calleeService); PolarisRouterContext routerContext = polarisLoadBalancerClientFilter.genRouterContext(webExchange, calleeService);
@ -181,7 +181,7 @@ public class PolarisLoadBalancerClientFilterTest {
Map<String, String> customMetadata = new HashMap<>(); Map<String, String> customMetadata = new HashMap<>();
customMetadata.put("k2", "v2"); customMetadata.put("k2", "v2");
when(routerLabelResolver.resolve(webExchange)).thenReturn(customMetadata); when(routerLabelResolver.resolve(webExchange, expressionLabelKeys)).thenReturn(customMetadata);
polarisLoadBalancerClientFilter.choose(webExchange); polarisLoadBalancerClientFilter.choose(webExchange);

@ -33,6 +33,10 @@ import org.springframework.util.CollectionUtils;
*/ */
public final class ExpressionLabelUtils { public final class ExpressionLabelUtils {
/**
* the prefix of expression.
*/
public static final String LABEL_PREFIX = "${";
/** /**
* the expression prefix of header label. * the expression prefix of header label.
*/ */
@ -77,14 +81,7 @@ public final class ExpressionLabelUtils {
if (StringUtils.isEmpty(labelKey)) { if (StringUtils.isEmpty(labelKey)) {
return false; return false;
} }
if (StringUtils.equalsIgnoreCase(LABEL_METHOD, labelKey) || return StringUtils.startsWith(labelKey, LABEL_PREFIX) && StringUtils.endsWith(labelKey, LABEL_SUFFIX);
StringUtils.startsWithIgnoreCase(LABEL_URI, labelKey)) {
return true;
}
return (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX) ||
StringUtils.startsWithIgnoreCase(labelKey, LABEL_QUERY_PREFIX) ||
StringUtils.startsWithIgnoreCase(labelKey, LABEL_COOKIE_PREFIX))
&& StringUtils.endsWith(labelKey, LABEL_SUFFIX);
} }
public static String parseHeaderKey(String expression) { public static String parseHeaderKey(String expression) {

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

@ -13,54 +13,41 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.polaris.router.example; package com.tencent.cloud.polaris.router.example;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver;
import feign.RequestTemplate; import feign.RequestTemplate;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* * Custom router label resolver for feign request.
* Customize the business tag information obtained from the request * @author lepdou 2022-07-20
*
*@author lepdou 2022-05-12
*/ */
@Component @Component
public class CustomRouterLabelResolver implements RouterLabelResolver { public class CustomFeignRouterLabelResolver implements FeignRouterLabelResolver {
private final Gson gson = new Gson(); private final Gson gson = new Gson();
@Override @Override
public Map<String, String> resolve(RequestTemplate requestTemplate) { public int getOrder() {
Map<String, String> labels = new HashMap<>(); return 0;
User user = gson.fromJson(new String(requestTemplate.body()), User.class);
labels.put("user", user.getName());
return labels;
} }
@Override @Override
public Map<String, String> resolve(HttpRequest request, byte[] body) { public Map<String, String> resolve(RequestTemplate requestTemplate, Set<String> expressionLabelKeys) {
Map<String, String> labels = new HashMap<>(); Map<String, String> labels = new HashMap<>();
User user = gson.fromJson(new String(body), User.class);
labels.put("user", user.getName()); User user = gson.fromJson(new String(requestTemplate.body()), User.class);
return labels;
}
labels.put("user", user.getName());
@Override return labels;
public int getOrder() {
return 0;
} }
} }

@ -0,0 +1,52 @@
/*
* 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.polaris.router.example;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.google.gson.Gson;
import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
/**
* Custom router label resolver for spring web request.
* @author lepdou 2022-07-20
*/
@Component
public class CustomSpringWebRouterLabelResolver implements SpringWebRouterLabelResolver {
private final Gson gson = new Gson();
@Override
public int getOrder() {
return 0;
}
@Override
public Map<String, String> resolve(HttpRequest request, byte[] body, Set<String> expressionLabelKeys) {
Map<String, String> labels = new HashMap<>();
User user = gson.fromJson(new String(body), User.class);
labels.put("user", user.getName());
return labels;
}
}

@ -35,7 +35,7 @@ import org.apache.commons.lang.StringUtils;
public class FeatureEnvRouterRequestInterceptor implements RouterRequestInterceptor { public class FeatureEnvRouterRequestInterceptor implements RouterRequestInterceptor {
private static final String LABEL_KEY_FEATURE_ENV_ROUTER_KEY = "system-feature-env-router-label"; private static final String LABEL_KEY_FEATURE_ENV_ROUTER_KEY = "system-feature-env-router-label";
private static final String DEFAULT_FEATURE_ENV_ROUTER_LABEL = "env"; private static final String DEFAULT_FEATURE_ENV_ROUTER_LABEL = "featureenv";
private static final String NOT_EXISTED_ENV = "NOT_EXISTED_ENV"; private static final String NOT_EXISTED_ENV = "NOT_EXISTED_ENV";
@Override @Override

@ -44,7 +44,7 @@ public class FeatureEnvRouterRequestInterceptorTest {
@Test @Test
public void testDefaultRouterKey() { public void testDefaultRouterKey() {
Map<String, String> labels = new HashMap<>(); Map<String, String> labels = new HashMap<>();
labels.put("env", "blue"); labels.put("featureenv", "blue");
PolarisRouterContext routerContext = new PolarisRouterContext(); PolarisRouterContext routerContext = new PolarisRouterContext();
routerContext.putLabels(PolarisRouterContext.ROUTER_LABELS, labels); routerContext.putLabels(PolarisRouterContext.ROUTER_LABELS, labels);
@ -58,7 +58,7 @@ public class FeatureEnvRouterRequestInterceptorTest {
Map<String, String> metadataRouterLabels = request.getRouterMetadata().get(MetadataRouter.ROUTER_TYPE_METADATA); Map<String, String> metadataRouterLabels = request.getRouterMetadata().get(MetadataRouter.ROUTER_TYPE_METADATA);
Assert.assertEquals(1, metadataRouterLabels.size()); Assert.assertEquals(1, metadataRouterLabels.size());
Assert.assertEquals("blue", metadataRouterLabels.get("env")); Assert.assertEquals("blue", metadataRouterLabels.get("featureenv"));
} }
@Test @Test

Loading…
Cancel
Save