From d4c8fff31ab0eeca32cd33f2f100bd8e1cac0f8b Mon Sep 17 00:00:00 2001
From: shedfreewu <49236872+shedfreewu@users.noreply.github.com>
Date: Tue, 26 Mar 2024 16:53:32 +0800
Subject: [PATCH] feat: support lane router (#1250)
---
CHANGELOG.md | 3 +-
.../pom.xml | 24 +++
.../MetadataTransferAutoConfiguration.java | 70 +++------
.../DecodeTransferMetadataReactiveFilter.java | 23 +--
.../DecodeTransferMetadataServletFilter.java | 21 +--
...codeTransferMedataFeignEnhancedPlugin.java | 140 ++++++++++++++++++
.../EncodeTransferMedataFeignInterceptor.java | 102 -------------
...sferMedataRestTemplateEnhancedPlugin.java} | 63 ++++----
...ncodeTransferMedataScgEnhancedPlugin.java} | 62 +++++---
...ransferMedataWebClientEnhancedPlugin.java} | 58 +++++---
...deTransferMetadataZuulEnhancedPlugin.java} | 67 ++++-----
.../provider/ReactiveMetadataProvider.java | 66 +++++++++
.../provider/ServletMetadataProvider.java | 67 +++++++++
...MetadataTransferAutoConfigurationTest.java | 52 ++-----
...odeTransferMedataFeignInterceptorTest.java | 2 +-
...sferMedataRestTemplateInterceptorTest.java | 50 ++++++-
.../EncodeTransferMedataScgFilterTest.java | 134 +++++++++++++----
...codeTransferMedataWebClientFilterTest.java | 2 +-
.../EncodeTransferMetadataZuulFilterTest.java | 35 ++++-
.../provider/MetadataProviderTest.java | 135 +++++++++++++++++
.../pom.xml | 4 +
.../cloud/common/constant/OrderConstant.java | 19 ---
.../metadata/MetadataContextHolder.java | 10 +-
.../cloud/common/util/ReflectionUtils.java | 16 ++
.../tencent/cloud/common/util/UrlUtils.java | 78 ++++++++++
.../expresstion/ExpressionLabelUtils.java | 10 +-
.../ServletExpressionLabelUtils.java | 8 +-
.../SpringWebExpressionLabelUtils.java | 20 ++-
.../metadata/MetadataContextHolderTest.java | 2 +-
.../cloud/common/util/UrlUtilsTest.java | 68 +++++++++
.../callee/QuickstartCalleeController.java | 22 +++
.../loadbalancer/PolarisLoadBalancer.java | 4 +-
.../feign/EnhancedFeignClient.java | 1 +
.../plugin/EnhancedPluginContext.java | 10 ++
.../plugin/PluginOrderConstant.java | 14 ++
.../EnhancedRestTemplateInterceptor.java | 1 +
.../scg/EnhancedGatewayGlobalFilter.java | 12 +-
...hancedWebClientExchangeFilterFunction.java | 14 +-
.../zuul/EnhancedPreZuulFilter.java | 1 +
39 files changed, 1070 insertions(+), 420 deletions(-)
create mode 100644 spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java
delete mode 100644 spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptor.java
rename spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/{EncodeTransferMedataRestTemplateInterceptor.java => EncodeTransferMedataRestTemplateEnhancedPlugin.java} (60%)
rename spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/{EncodeTransferMedataScgFilter.java => EncodeTransferMedataScgEnhancedPlugin.java} (58%)
rename spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/{EncodeTransferMedataWebClientFilter.java => EncodeTransferMedataWebClientEnhancedPlugin.java} (57%)
rename spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/{EncodeTransferMetadataZuulFilter.java => EncodeTransferMetadataZuulEnhancedPlugin.java} (56%)
create mode 100644 spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ReactiveMetadataProvider.java
create mode 100644 spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ServletMetadataProvider.java
create mode 100644 spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/provider/MetadataProviderTest.java
create mode 100644 spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/UrlUtils.java
create mode 100644 spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/UrlUtilsTest.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc61a27f..ac7c92ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,4 +3,5 @@
- [feat: support lossless register and deregister at #977](https://github.com/Tencent/spring-cloud-tencent/pull/1242)
- [feat: PolarisServiceRegistry#deregister support idempotency.](https://github.com/Tencent/spring-cloud-tencent/pull/1243)
-- [feat: SCT元数据管理能力与polaris-java元数据管理能力进行下沉及整合](https://github.com/Tencent/spring-cloud-tencent/pull/1249)
\ No newline at end of file
+- [feat: SCT元数据管理能力与polaris-java元数据管理能力进行下沉及整合](https://github.com/Tencent/spring-cloud-tencent/pull/1249)
+- [feat: support lane router](https://github.com/Tencent/spring-cloud-tencent/pull/1250)
\ No newline at end of file
diff --git a/spring-cloud-starter-tencent-metadata-transfer/pom.xml b/spring-cloud-starter-tencent-metadata-transfer/pom.xml
index ad4714f7..35b783da 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/pom.xml
+++ b/spring-cloud-starter-tencent-metadata-transfer/pom.xml
@@ -19,6 +19,12 @@
com.tencent.cloud
spring-cloud-tencent-commons
+
+
+ com.tencent.cloud
+ spring-cloud-tencent-rpc-enhancement
+
+
@@ -56,6 +62,24 @@
spring-cloud-starter-netflix-ribbon
test
+
+
+ com.tencent.polaris
+ polaris-test-mock-discovery
+ test
+
+
+
+ com.tencent.polaris
+ polaris-test-common
+ test
+
+
+
+ org.mockito
+ mockito-inline
+ test
+
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java
index bbb03328..b9b44089 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java
@@ -18,31 +18,21 @@
package com.tencent.cloud.metadata.config;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import com.netflix.zuul.ZuulFilter;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataReactiveFilter;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataServletFilter;
-import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignInterceptor;
-import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateInterceptor;
-import com.tencent.cloud.metadata.core.EncodeTransferMedataScgFilter;
-import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientFilter;
-import com.tencent.cloud.metadata.core.EncodeTransferMetadataZuulFilter;
-
-import org.springframework.beans.factory.SmartInitializingSingleton;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignEnhancedPlugin;
+import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateEnhancedPlugin;
+import com.tencent.cloud.metadata.core.EncodeTransferMedataScgEnhancedPlugin;
+import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientEnhancedPlugin;
+import com.tencent.cloud.metadata.core.EncodeTransferMetadataZuulEnhancedPlugin;
+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.reactive.function.client.WebClient;
import static javax.servlet.DispatcherType.ASYNC;
import static javax.servlet.DispatcherType.ERROR;
@@ -100,11 +90,12 @@ public class MetadataTransferAutoConfiguration {
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "com.netflix.zuul.http.ZuulServlet")
+ @ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferZuulFilterConfig {
@Bean
- public ZuulFilter encodeTransferMetadataZuulFilter() {
- return new EncodeTransferMetadataZuulFilter();
+ public EncodeTransferMetadataZuulEnhancedPlugin encodeTransferMedataZuulEnhancedPlugin() {
+ return new EncodeTransferMetadataZuulEnhancedPlugin();
}
}
@@ -114,11 +105,12 @@ public class MetadataTransferAutoConfiguration {
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "org.springframework.cloud.gateway.filter.GlobalFilter")
+ @ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferScgFilterConfig {
@Bean
- public GlobalFilter encodeTransferMedataScgFilter() {
- return new EncodeTransferMedataScgFilter();
+ public EncodeTransferMedataScgEnhancedPlugin encodeTransferMedataScgEnhancedPlugin() {
+ return new EncodeTransferMedataScgEnhancedPlugin();
}
}
@@ -127,11 +119,12 @@ public class MetadataTransferAutoConfiguration {
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "feign.Feign")
+ @ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferFeignInterceptorConfig {
@Bean
- public EncodeTransferMedataFeignInterceptor encodeTransferMedataFeignInterceptor() {
- return new EncodeTransferMedataFeignInterceptor();
+ public EncodeTransferMedataFeignEnhancedPlugin encodeTransferMedataFeignEnhancedPlugin() {
+ return new EncodeTransferMedataFeignEnhancedPlugin();
}
}
@@ -140,23 +133,12 @@ public class MetadataTransferAutoConfiguration {
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
+ @ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferRestTemplateConfig {
- @Autowired(required = false)
- private List restTemplates = Collections.emptyList();
-
@Bean
- public EncodeTransferMedataRestTemplateInterceptor encodeTransferMedataRestTemplateInterceptor() {
- return new EncodeTransferMedataRestTemplateInterceptor();
- }
-
- @Bean
- public SmartInitializingSingleton addEncodeTransferMetadataInterceptorForRestTemplate(EncodeTransferMedataRestTemplateInterceptor interceptor) {
- return () -> restTemplates.forEach(restTemplate -> {
- List list = new ArrayList<>(restTemplate.getInterceptors());
- list.add(interceptor);
- restTemplate.setInterceptors(list);
- });
+ public EncodeTransferMedataRestTemplateEnhancedPlugin encodeTransferMedataRestTemplateEnhancedPlugin() {
+ return new EncodeTransferMedataRestTemplateEnhancedPlugin();
}
}
@@ -165,20 +147,12 @@ public class MetadataTransferAutoConfiguration {
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "org.springframework.web.reactive.function.client.WebClient")
+ @ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferWebClientConfig {
- @Autowired(required = false)
- private List webClientBuilder = Collections.emptyList();
-
- @Bean
- public EncodeTransferMedataWebClientFilter encodeTransferMedataWebClientFilter() {
- return new EncodeTransferMedataWebClientFilter();
- }
@Bean
- public SmartInitializingSingleton addEncodeTransferMetadataFilterForWebClient(EncodeTransferMedataWebClientFilter filter) {
- return () -> webClientBuilder.forEach(webClient -> {
- webClient.filter(filter);
- });
+ public EncodeTransferMedataWebClientEnhancedPlugin encodeTransferMedataWebClientEnhancedPlugin() {
+ return new EncodeTransferMedataWebClientEnhancedPlugin();
}
}
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java
index 4268f6e7..e4fd1a2c 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java
@@ -18,8 +18,6 @@
package com.tencent.cloud.metadata.core;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
@@ -27,6 +25,8 @@ import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.metadata.provider.ReactiveMetadataProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
@@ -34,12 +34,10 @@ import reactor.core.publisher.Mono;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
-import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
@@ -62,19 +60,16 @@ public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered
public Mono filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
// Get metadata string from http header.
ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest();
-
Map internalTransitiveMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_METADATA);
Map customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(serverWebExchange);
Map mergedTransitiveMetadata = new HashMap<>();
mergedTransitiveMetadata.putAll(internalTransitiveMetadata);
mergedTransitiveMetadata.putAll(customTransitiveMetadata);
-
Map internalDisposableMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_DISPOSABLE_METADATA);
Map mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata);
-
- MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata);
-
+ ReactiveMetadataProvider metadataProvider = new ReactiveMetadataProvider(serverHttpRequest);
+ MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, metadataProvider);
// Save to ServerWebExchange.
serverWebExchange.getAttributes().put(
MetadataConstant.HeaderName.METADATA_CONTEXT,
@@ -89,15 +84,7 @@ public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered
private Map getIntervalMetadata(ServerHttpRequest serverHttpRequest, String headerName) {
HttpHeaders httpHeaders = serverHttpRequest.getHeaders();
- String customMetadataStr = httpHeaders.getFirst(headerName);
- try {
- if (StringUtils.hasText(customMetadataStr)) {
- customMetadataStr = URLDecoder.decode(customMetadataStr, UTF_8);
- }
- }
- catch (UnsupportedEncodingException e) {
- LOG.error("Runtime system does not support utf-8 coding.", e);
- }
+ String customMetadataStr = UrlUtils.decode(httpHeaders.getFirst(headerName));
LOG.debug("Get upstream metadata string: {}", customMetadataStr);
return JacksonUtils.deserialize2Map(customMetadataStr);
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java
index e1d26efc..d74ddcd7 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java
@@ -19,8 +19,6 @@
package com.tencent.cloud.metadata.core;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
@@ -32,15 +30,15 @@ import javax.servlet.http.HttpServletResponse;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.metadata.provider.ServletMetadataProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.lang.NonNull;
-import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
-import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
@@ -65,11 +63,10 @@ public class DecodeTransferMetadataServletFilter extends OncePerRequestFilter {
Map mergedTransitiveMetadata = new HashMap<>();
mergedTransitiveMetadata.putAll(internalTransitiveMetadata);
mergedTransitiveMetadata.putAll(customTransitiveMetadata);
-
Map internalDisposableMetadata = getInternalMetadata(httpServletRequest, CUSTOM_DISPOSABLE_METADATA);
Map mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata);
-
- MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata);
+ ServletMetadataProvider metadataProvider = new ServletMetadataProvider(httpServletRequest);
+ MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, metadataProvider);
TransHeadersTransfer.transfer(httpServletRequest);
try {
@@ -83,15 +80,7 @@ public class DecodeTransferMetadataServletFilter extends OncePerRequestFilter {
private Map getInternalMetadata(HttpServletRequest httpServletRequest, String headerName) {
// Get custom metadata string from http header.
- String customMetadataStr = httpServletRequest.getHeader(headerName);
- try {
- if (StringUtils.hasText(customMetadataStr)) {
- customMetadataStr = URLDecoder.decode(customMetadataStr, UTF_8);
- }
- }
- catch (UnsupportedEncodingException e) {
- LOG.error("Runtime system does not support utf-8 coding.", e);
- }
+ String customMetadataStr = UrlUtils.decode(httpServletRequest.getHeader(headerName));
LOG.debug("Get upstream metadata string: {}", customMetadataStr);
// create custom metadata.
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java
new file mode 100644
index 00000000..ff722edc
--- /dev/null
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java
@@ -0,0 +1,140 @@
+/*
+ * 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.metadata.core;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.common.util.ReflectionUtils;
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
+import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
+import com.tencent.polaris.metadata.core.MetadataType;
+import feign.Request;
+
+import org.springframework.util.CollectionUtils;
+
+import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
+import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
+
+/**
+ * Pre EnhancedPlugin for feign to encode transfer metadata.
+ *
+ * @author Shedfree Wu
+ */
+public class EncodeTransferMedataFeignEnhancedPlugin implements EnhancedPlugin {
+ @Override
+ public EnhancedPluginType getType() {
+ return EnhancedPluginType.Client.PRE;
+ }
+
+ @Override
+ public void run(EnhancedPluginContext context) throws Throwable {
+ if (!(context.getOriginRequest() instanceof Request)) {
+ return;
+ }
+ Request request = (Request) context.getOriginRequest();
+
+ // get metadata of current thread
+ MetadataContext metadataContext = MetadataContextHolder.get();
+ Map customMetadata = metadataContext.getCustomMetadata();
+ Map disposableMetadata = metadataContext.getDisposableMetadata();
+ Map transHeaders = metadataContext.getTransHeadersKV();
+
+ MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
+ Map calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders();
+ // currently only support transitive header from calleeMessageMetadataContainer
+ this.buildHeaderMap(request, calleeTransitiveHeaders);
+
+ // build custom disposable metadata request header
+ this.buildMetadataHeader(request, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
+
+ // process custom metadata
+ this.buildMetadataHeader(request, customMetadata, CUSTOM_METADATA);
+
+ // set headers that need to be transmitted from the upstream
+ this.buildTransmittedHeader(request, transHeaders);
+ }
+
+ private void buildTransmittedHeader(Request request, Map transHeaders) {
+ if (!CollectionUtils.isEmpty(transHeaders)) {
+ Map> headers = getModifiableHeaders(request);
+ transHeaders.entrySet().stream().forEach(entry -> {
+ headers.remove(entry.getKey());
+ headers.put(entry.getKey(), Arrays.asList(entry.getValue()));
+ });
+ }
+ }
+
+ /**
+ * Set metadata into the request header for {@link Request} .
+ * @param request instance of {@link Request}
+ * @param metadata metadata map .
+ * @param headerName target metadata http header name .
+ */
+ private void buildMetadataHeader(Request request, Map metadata, String headerName) {
+ if (!CollectionUtils.isEmpty(metadata)) {
+ buildHeaderMap(request, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
+ }
+ }
+
+
+ /**
+ * Set headerMap into the request header for {@link Request} .
+ * @param request instance of {@link Request}
+ * @param headerMap header map .
+ */
+ private void buildHeaderMap(Request request, Map headerMap) {
+ if (!CollectionUtils.isEmpty(headerMap)) {
+ Map> headers = getModifiableHeaders(request);
+ headerMap.forEach((key, value) -> headers.put(key, Arrays.asList(UrlUtils.encode(value))));
+ }
+ }
+
+ /**
+ * The value obtained directly from the headers method is an unmodifiable map.
+ * If the Feign client uses the URL, the original headers are unmodifiable.
+ * @param request feign request
+ * @return modifiable headers
+ */
+ private Map> getModifiableHeaders(Request request) {
+ Map> headers;
+ headers = (Map>) ReflectionUtils.getFieldValue(request, "headers");
+
+ if (!(headers instanceof LinkedHashMap)) {
+ headers = new LinkedHashMap<>(headers);
+ ReflectionUtils.setFieldValue(request, "headers", headers);
+ }
+ return headers;
+ }
+
+ @Override
+ public int getOrder() {
+ return PluginOrderConstant.ClientPluginOrder.CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER;
+ }
+}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptor.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptor.java
deleted file mode 100644
index edbf5f0b..00000000
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptor.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.metadata.core;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Map;
-
-import com.tencent.cloud.common.constant.OrderConstant;
-import com.tencent.cloud.common.metadata.MetadataContext;
-import com.tencent.cloud.common.metadata.MetadataContextHolder;
-import com.tencent.cloud.common.util.JacksonUtils;
-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 org.springframework.web.client.RestTemplate;
-
-import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
-import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
-import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
-import static java.net.URLEncoder.encode;
-
-/**
- * Interceptor used for adding the metadata in http headers from context when web client
- * is Feign.
- *
- * @author Haotian Zhang
- */
-public class EncodeTransferMedataFeignInterceptor implements RequestInterceptor, Ordered {
-
- private static final Logger LOG = LoggerFactory.getLogger(EncodeTransferMedataFeignInterceptor.class);
-
- @Override
- public int getOrder() {
- return OrderConstant.Client.Feign.ENCODE_TRANSFER_METADATA_INTERCEPTOR_ORDER;
- }
-
- @Override
- public void apply(RequestTemplate requestTemplate) {
- // get metadata of current thread
- MetadataContext metadataContext = MetadataContextHolder.get();
- Map customMetadata = metadataContext.getCustomMetadata();
- Map disposableMetadata = metadataContext.getDisposableMetadata();
- Map transHeaders = metadataContext.getTransHeadersKV();
-
- this.buildMetadataHeader(requestTemplate, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
-
- // process custom metadata
- this.buildMetadataHeader(requestTemplate, customMetadata, CUSTOM_METADATA);
-
- // set headers that need to be transmitted from the upstream
- this.buildTransmittedHeader(requestTemplate, transHeaders);
- }
-
- private void buildTransmittedHeader(RequestTemplate requestTemplate, Map transHeaders) {
- if (!CollectionUtils.isEmpty(transHeaders)) {
- transHeaders.entrySet().stream().forEach(entry -> {
- requestTemplate.removeHeader(entry.getKey());
- requestTemplate.header(entry.getKey(), entry.getValue());
- });
- }
- }
-
- /**
- * Set metadata into the request header for {@link RestTemplate} .
- * @param requestTemplate instance of {@link RestTemplate}
- * @param metadata metadata map .
- * @param headerName target metadata http header name .
- */
- private void buildMetadataHeader(RequestTemplate requestTemplate, Map metadata, String headerName) {
- if (!CollectionUtils.isEmpty(metadata)) {
- String encodedMetadata = JacksonUtils.serialize2Json(metadata);
- requestTemplate.removeHeader(headerName);
- try {
- requestTemplate.header(headerName, encode(encodedMetadata, UTF_8));
- }
- catch (UnsupportedEncodingException e) {
- LOG.error("Set header failed.", e);
- requestTemplate.header(headerName, encodedMetadata);
- }
- }
- }
-}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java
similarity index 60%
rename from spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java
rename to spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java
index cbf4901b..50e42885 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java
@@ -18,49 +18,53 @@
package com.tencent.cloud.metadata.core;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
import java.util.Map;
-import com.tencent.cloud.common.constant.OrderConstant;
+import com.google.common.collect.ImmutableMap;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
+import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
+import com.tencent.polaris.metadata.core.MetadataType;
-import org.springframework.core.Ordered;
import org.springframework.http.HttpRequest;
-import org.springframework.http.client.ClientHttpRequestExecution;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
-import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
/**
- * Interceptor used for adding the metadata in http headers from context when web client
- * is RestTemplate.
+ * Pre EnhancedPlugin for rest template to encode transfer metadata.
*
- * @author Haotian Zhang
+ * @author Shedfree Wu
*/
-public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered {
-
+public class EncodeTransferMedataRestTemplateEnhancedPlugin implements EnhancedPlugin {
@Override
- public int getOrder() {
- return OrderConstant.Client.RestTemplate.ENCODE_TRANSFER_METADATA_INTERCEPTOR_ORDER;
+ public EnhancedPluginType getType() {
+ return EnhancedPluginType.Client.PRE;
}
@Override
- public ClientHttpResponse intercept(@NonNull HttpRequest httpRequest, @NonNull byte[] bytes,
- @NonNull ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
+ public void run(EnhancedPluginContext context) throws Throwable {
+ if (!(context.getOriginRequest() instanceof HttpRequest)) {
+ return;
+ }
+ HttpRequest httpRequest = (HttpRequest) context.getOriginRequest();
+
// get metadata of current thread
MetadataContext metadataContext = MetadataContextHolder.get();
Map customMetadata = metadataContext.getCustomMetadata();
Map disposableMetadata = metadataContext.getDisposableMetadata();
Map transHeaders = metadataContext.getTransHeadersKV();
+ MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
+ Map calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders();
+ // currently only support transitive header from calleeMessageMetadataContainer
+ this.buildHeaderMap(httpRequest, calleeTransitiveHeaders);
// build custom disposable metadata request header
this.buildMetadataHeader(httpRequest, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
@@ -70,8 +74,6 @@ public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRe
// set headers that need to be transmitted from the upstream
this.buildTransmittedHeader(httpRequest, transHeaders);
-
- return clientHttpRequestExecution.execute(httpRequest, bytes);
}
private void buildTransmittedHeader(HttpRequest request, Map transHeaders) {
@@ -82,6 +84,12 @@ public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRe
}
}
+ private void buildHeaderMap(HttpRequest request, Map headerMap) {
+ if (!CollectionUtils.isEmpty(headerMap)) {
+ headerMap.forEach((key, value) -> request.getHeaders().set(key, UrlUtils.encode(value)));
+ }
+ }
+
/**
* Set metadata into the request header for {@link HttpRequest} .
*
@@ -91,13 +99,12 @@ public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRe
*/
private void buildMetadataHeader(HttpRequest request, Map metadata, String headerName) {
if (!CollectionUtils.isEmpty(metadata)) {
- String encodedMetadata = JacksonUtils.serialize2Json(metadata);
- try {
- request.getHeaders().set(headerName, URLEncoder.encode(encodedMetadata, UTF_8));
- }
- catch (UnsupportedEncodingException e) {
- request.getHeaders().set(headerName, encodedMetadata);
- }
+ buildHeaderMap(request, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
}
}
+
+ @Override
+ public int getOrder() {
+ return PluginOrderConstant.ClientPluginOrder.CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER;
+ }
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgEnhancedPlugin.java
similarity index 58%
rename from spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilter.java
rename to spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgEnhancedPlugin.java
index 2eacd21a..8c996bbf 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgEnhancedPlugin.java
@@ -18,42 +18,46 @@
package com.tencent.cloud.metadata.core;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
import java.util.Map;
+import com.google.common.collect.ImmutableMap;
import com.tencent.cloud.common.constant.MetadataConstant;
-import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
-import reactor.core.publisher.Mono;
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
+import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
+import com.tencent.polaris.metadata.core.MetadataType;
-import org.springframework.cloud.gateway.filter.GatewayFilterChain;
-import org.springframework.cloud.gateway.filter.GlobalFilter;
-import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
-import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
/**
- * Scg filter used for writing metadata in HTTP request header.
+ * Pre EnhancedPlugin for scg to encode transfer metadata.
*
- * @author Haotian Zhang
+ * @author Shedfree Wu
*/
-public class EncodeTransferMedataScgFilter implements GlobalFilter, Ordered {
-
+public class EncodeTransferMedataScgEnhancedPlugin implements EnhancedPlugin {
@Override
- public int getOrder() {
- return OrderConstant.Client.Scg.ENCODE_TRANSFER_METADATA_FILTER_ORDER;
+ public EnhancedPluginType getType() {
+ return EnhancedPluginType.Client.PRE;
}
@Override
- public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ public void run(EnhancedPluginContext context) throws Throwable {
+ if (!(context.getOriginRequest() instanceof ServerWebExchange)) {
+ return;
+ }
+ ServerWebExchange exchange = (ServerWebExchange) context.getOriginRequest();
+
// get request builder
ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
@@ -66,11 +70,22 @@ public class EncodeTransferMedataScgFilter implements GlobalFilter, Ordered {
Map customMetadata = metadataContext.getCustomMetadata();
Map disposableMetadata = metadataContext.getDisposableMetadata();
+ MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
+ Map calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders();
+ // currently only support transitive header from calleeMessageMetadataContainer
+ this.buildHeaderMap(builder, calleeTransitiveHeaders);
+
this.buildMetadataHeader(builder, customMetadata, CUSTOM_METADATA);
this.buildMetadataHeader(builder, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
-
TransHeadersTransfer.transfer(exchange.getRequest());
- return chain.filter(exchange.mutate().request(builder.build()).build());
+
+ context.setOriginRequest(exchange.mutate().request(builder.build()).build());
+ }
+
+ private void buildHeaderMap(ServerHttpRequest.Builder builder, Map headerMap) {
+ if (!CollectionUtils.isEmpty(headerMap)) {
+ headerMap.forEach((key, value) -> builder.header(key, UrlUtils.encode(value)));
+ }
}
/**
@@ -81,13 +96,12 @@ public class EncodeTransferMedataScgFilter implements GlobalFilter, Ordered {
*/
private void buildMetadataHeader(ServerHttpRequest.Builder builder, Map metadata, String headerName) {
if (!CollectionUtils.isEmpty(metadata)) {
- String encodedMetadata = JacksonUtils.serialize2Json(metadata);
- try {
- builder.header(headerName, URLEncoder.encode(encodedMetadata, UTF_8));
- }
- catch (UnsupportedEncodingException e) {
- builder.header(headerName, encodedMetadata);
- }
+ buildHeaderMap(builder, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
}
}
+
+ @Override
+ public int getOrder() {
+ return PluginOrderConstant.ClientPluginOrder.CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER;
+ }
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientEnhancedPlugin.java
similarity index 57%
rename from spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientFilter.java
rename to spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientEnhancedPlugin.java
index 3547add0..2967a2b4 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientEnhancedPlugin.java
@@ -18,48 +18,61 @@
package com.tencent.cloud.metadata.core;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
import java.util.Map;
+import com.google.common.collect.ImmutableMap;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
-import reactor.core.publisher.Mono;
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
+import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
+import com.tencent.polaris.metadata.core.MetadataType;
import org.springframework.util.CollectionUtils;
import org.springframework.web.reactive.function.client.ClientRequest;
-import org.springframework.web.reactive.function.client.ClientResponse;
-import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
-import org.springframework.web.reactive.function.client.ExchangeFunction;
-import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
/**
- * web client filter used for writing metadata in HTTP request header.
+ * Pre EnhancedPlugin for web client to encode transfer metadata.
*
- * @author sean yu
+ * @author Shedfree Wu
*/
-public class EncodeTransferMedataWebClientFilter implements ExchangeFilterFunction {
+public class EncodeTransferMedataWebClientEnhancedPlugin implements EnhancedPlugin {
+ @Override
+ public EnhancedPluginType getType() {
+ return EnhancedPluginType.Client.PRE;
+ }
@Override
- public Mono filter(ClientRequest clientRequest, ExchangeFunction next) {
+ public void run(EnhancedPluginContext context) throws Throwable {
+ if (!(context.getOriginRequest() instanceof ClientRequest)) {
+ return;
+ }
+ ClientRequest clientRequest = (ClientRequest) context.getOriginRequest();
+
MetadataContext metadataContext = MetadataContextHolder.get();
Map customMetadata = metadataContext.getCustomMetadata();
Map disposableMetadata = metadataContext.getDisposableMetadata();
Map transHeaders = metadataContext.getTransHeadersKV();
+ MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
+ Map calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders();
ClientRequest.Builder requestBuilder = ClientRequest.from(clientRequest);
+ // currently only support transitive header from calleeMessageMetadataContainer
+ this.buildHeaderMap(requestBuilder, calleeTransitiveHeaders);
+
this.buildMetadataHeader(requestBuilder, customMetadata, CUSTOM_METADATA);
this.buildMetadataHeader(requestBuilder, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
this.buildTransmittedHeader(requestBuilder, transHeaders);
- ClientRequest request = requestBuilder.build();
-
- return next.exchange(request);
+ context.setOriginRequest(requestBuilder.build());
}
private void buildTransmittedHeader(ClientRequest.Builder requestBuilder, Map transHeaders) {
@@ -68,6 +81,11 @@ public class EncodeTransferMedataWebClientFilter implements ExchangeFilterFuncti
}
}
+ private void buildHeaderMap(ClientRequest.Builder requestBuilder, Map headerMap) {
+ if (!CollectionUtils.isEmpty(headerMap)) {
+ headerMap.forEach((key, value) -> requestBuilder.header(key, UrlUtils.encode(value)));
+ }
+ }
/**
* Set metadata into the request header for {@link ClientRequest} .
@@ -77,14 +95,12 @@ public class EncodeTransferMedataWebClientFilter implements ExchangeFilterFuncti
*/
private void buildMetadataHeader(ClientRequest.Builder requestBuilder, Map metadata, String headerName) {
if (!CollectionUtils.isEmpty(metadata)) {
- String encodedMetadata = JacksonUtils.serialize2Json(metadata);
- try {
- requestBuilder.header(headerName, URLEncoder.encode(encodedMetadata, UTF_8));
- }
- catch (UnsupportedEncodingException e) {
- requestBuilder.header(headerName, encodedMetadata);
- }
+ buildHeaderMap(requestBuilder, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
}
}
+ @Override
+ public int getOrder() {
+ return PluginOrderConstant.ClientPluginOrder.CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER;
+ }
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulEnhancedPlugin.java
similarity index 56%
rename from spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilter.java
rename to spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulEnhancedPlugin.java
index 6aa2a1e0..c1957bda 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulEnhancedPlugin.java
@@ -18,63 +18,65 @@
package com.tencent.cloud.metadata.core;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
import java.util.Map;
-import com.netflix.zuul.ZuulFilter;
+import com.google.common.collect.ImmutableMap;
import com.netflix.zuul.context.RequestContext;
-import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
+import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
+import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
+import com.tencent.polaris.metadata.core.MetadataType;
import org.springframework.util.CollectionUtils;
-import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
-import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ROUTE_TYPE;
/**
- * Zuul filter used for writing metadata in HTTP request header.
+ * Pre EnhancedPlugin for zuul to encode transfer metadata.
*
- * @author Haotian Zhang
+ * @author Shedfree Wu
*/
-public class EncodeTransferMetadataZuulFilter extends ZuulFilter {
-
- @Override
- public String filterType() {
- return ROUTE_TYPE;
- }
-
- @Override
- public int filterOrder() {
- return OrderConstant.Client.Zuul.ENCODE_TRANSFER_METADATA_FILTER_ORDER;
- }
-
+public class EncodeTransferMetadataZuulEnhancedPlugin implements EnhancedPlugin {
@Override
- public boolean shouldFilter() {
- return true;
+ public EnhancedPluginType getType() {
+ return EnhancedPluginType.Client.PRE;
}
@Override
- public Object run() {
- // get request context
- RequestContext requestContext = RequestContext.getCurrentContext();
+ public void run(EnhancedPluginContext context) throws Throwable {
+ if (!(context.getOriginRequest() instanceof RequestContext)) {
+ return;
+ }
+ RequestContext requestContext = (RequestContext) context.getOriginRequest();
// get metadata of current thread
MetadataContext metadataContext = MetadataContextHolder.get();
Map customMetadata = metadataContext.getCustomMetadata();
Map disposableMetadata = metadataContext.getDisposableMetadata();
+ MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
+ Map calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders();
+ // currently only support transitive header from calleeMessageMetadataContainer
+ this.buildHeaderMap(requestContext, calleeTransitiveHeaders);
// Rebuild Metadata Header
this.buildMetadataHeader(requestContext, customMetadata, CUSTOM_METADATA);
this.buildMetadataHeader(requestContext, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
TransHeadersTransfer.transfer(requestContext.getRequest());
- return null;
+ }
+
+ private void buildHeaderMap(RequestContext context, Map headerMap) {
+ if (!CollectionUtils.isEmpty(headerMap)) {
+ headerMap.forEach((key, value) -> context.addZuulRequestHeader(key, UrlUtils.encode(value)));
+ }
}
/**
@@ -86,13 +88,12 @@ public class EncodeTransferMetadataZuulFilter extends ZuulFilter {
*/
private void buildMetadataHeader(RequestContext context, Map metadata, String headerName) {
if (!CollectionUtils.isEmpty(metadata)) {
- String encodedMetadata = JacksonUtils.serialize2Json(metadata);
- try {
- context.addZuulRequestHeader(headerName, URLEncoder.encode(encodedMetadata, UTF_8));
- }
- catch (UnsupportedEncodingException e) {
- context.addZuulRequestHeader(headerName, encodedMetadata);
- }
+ buildHeaderMap(context, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
}
}
+
+ @Override
+ public int getOrder() {
+ return PluginOrderConstant.ClientPluginOrder.CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER;
+ }
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ReactiveMetadataProvider.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ReactiveMetadataProvider.java
new file mode 100644
index 00000000..7eb2dc1c
--- /dev/null
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ReactiveMetadataProvider.java
@@ -0,0 +1,66 @@
+/*
+ * 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.metadata.provider;
+
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
+import com.tencent.polaris.metadata.core.MetadataProvider;
+
+import org.springframework.http.server.reactive.ServerHttpRequest;
+
+/**
+ * MetadataProvider used for Reactive.
+ *
+ * @author Shedfree Wu
+ */
+public class ReactiveMetadataProvider implements MetadataProvider {
+
+ private ServerHttpRequest serverHttpRequest;
+
+ public ReactiveMetadataProvider(ServerHttpRequest serverHttpRequest) {
+ this.serverHttpRequest = serverHttpRequest;
+ }
+
+ @Override
+ public String getRawMetadataStringValue(String key) {
+ switch (key) {
+ case MessageMetadataContainer.LABEL_KEY_METHOD:
+ return serverHttpRequest.getMethodValue();
+ case MessageMetadataContainer.LABEL_KEY_PATH:
+ return UrlUtils.decode(serverHttpRequest.getPath().toString());
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public String getRawMetadataMapValue(String key, String mapKey) {
+ switch (key) {
+ case MessageMetadataContainer.LABEL_MAP_KEY_HEADER:
+ return UrlUtils.decode(SpringWebExpressionLabelUtils.getHeaderValue(serverHttpRequest, mapKey, null));
+ case MessageMetadataContainer.LABEL_MAP_KEY_COOKIE:
+ return UrlUtils.decode(SpringWebExpressionLabelUtils.getCookieValue(serverHttpRequest, mapKey, null));
+ case MessageMetadataContainer.LABEL_MAP_KEY_QUERY:
+ return UrlUtils.decode(SpringWebExpressionLabelUtils.getQueryValue(serverHttpRequest, mapKey, null));
+ default:
+ return null;
+ }
+ }
+}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ServletMetadataProvider.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ServletMetadataProvider.java
new file mode 100644
index 00000000..f06df5e1
--- /dev/null
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ServletMetadataProvider.java
@@ -0,0 +1,67 @@
+/*
+ * 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.metadata.provider;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils;
+import com.tencent.cloud.common.util.expresstion.ServletExpressionLabelUtils;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
+import com.tencent.polaris.metadata.core.MetadataProvider;
+
+/**
+ * MetadataProvider used for Servlet.
+ *
+ * @author Shedfree Wu
+ */
+public class ServletMetadataProvider implements MetadataProvider {
+
+ private HttpServletRequest httpServletRequest;
+
+ public ServletMetadataProvider(HttpServletRequest httpServletRequest) {
+ this.httpServletRequest = httpServletRequest;
+ }
+
+ @Override
+ public String getRawMetadataStringValue(String key) {
+ switch (key) {
+ case MessageMetadataContainer.LABEL_KEY_METHOD:
+ return httpServletRequest.getMethod();
+ case MessageMetadataContainer.LABEL_KEY_PATH:
+ return UrlUtils.decode(httpServletRequest.getRequestURI());
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public String getRawMetadataMapValue(String key, String mapKey) {
+ switch (key) {
+ case MessageMetadataContainer.LABEL_MAP_KEY_HEADER:
+ return UrlUtils.decode(httpServletRequest.getHeader(mapKey));
+ case MessageMetadataContainer.LABEL_MAP_KEY_COOKIE:
+ return UrlUtils.decode(ServletExpressionLabelUtils.getCookieValue(httpServletRequest.getCookies(), mapKey, null));
+ case MessageMetadataContainer.LABEL_MAP_KEY_QUERY:
+ return UrlUtils.decode(ExpressionLabelUtils.getQueryValue(httpServletRequest.getQueryString(), mapKey, null));
+ default:
+ return null;
+ }
+ }
+}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfigurationTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfigurationTest.java
index cd23e761..c6111119 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfigurationTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfigurationTest.java
@@ -18,25 +18,17 @@
package com.tencent.cloud.metadata.config;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignInterceptor;
-import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateInterceptor;
-import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientFilter;
+import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignEnhancedPlugin;
+import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateEnhancedPlugin;
+import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientEnhancedPlugin;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
-import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
@@ -59,35 +51,10 @@ public class MetadataTransferAutoConfigurationTest {
this.applicationContextRunner.withConfiguration(AutoConfigurations.of(MetadataTransferAutoConfiguration.class))
.run(context -> {
assertThat(context).hasSingleBean(MetadataTransferAutoConfiguration.MetadataTransferFeignInterceptorConfig.class);
- assertThat(context).hasSingleBean(EncodeTransferMedataFeignInterceptor.class);
+ assertThat(context).hasSingleBean(EncodeTransferMedataFeignEnhancedPlugin.class);
+ assertThat(context).hasSingleBean(EncodeTransferMedataRestTemplateEnhancedPlugin.class);
assertThat(context).hasSingleBean(MetadataTransferAutoConfiguration.MetadataTransferRestTemplateConfig.class);
- assertThat(context).hasSingleBean(EncodeTransferMedataRestTemplateInterceptor.class);
assertThat(context).hasSingleBean(MetadataTransferAutoConfiguration.MetadataTransferScgFilterConfig.class);
- assertThat(context).hasSingleBean(GlobalFilter.class);
- });
- }
-
-
- @Test
- public void test2() {
- this.applicationContextRunner
- .withConfiguration(
- AutoConfigurations.of(MetadataTransferAutoConfiguration.class, RestTemplateConfiguration.class))
- .run(context -> {
- assertThat(context).hasSingleBean(EncodeTransferMedataFeignInterceptor.class);
- EncodeTransferMedataRestTemplateInterceptor encodeTransferMedataRestTemplateInterceptor = context.getBean(EncodeTransferMedataRestTemplateInterceptor.class);
- Map restTemplateMap = context.getBeansOfType(RestTemplate.class);
- assertThat(restTemplateMap.size()).isEqualTo(2);
- for (String beanName : Arrays.asList("restTemplate", "loadBalancedRestTemplate")) {
- RestTemplate restTemplate = restTemplateMap.get(beanName);
- assertThat(restTemplate).isNotNull();
- List encodeTransferMedataFeignInterceptorList = restTemplate.getInterceptors()
- .stream()
- .filter(interceptor -> Objects.equals(interceptor, encodeTransferMedataRestTemplateInterceptor))
- .collect(Collectors.toList());
- //EncodeTransferMetadataFeignInterceptor is not added repeatedly
- assertThat(encodeTransferMedataFeignInterceptorList.size()).isEqualTo(1);
- }
});
}
@@ -95,16 +62,15 @@ public class MetadataTransferAutoConfigurationTest {
* Reactive web application.
*/
@Test
- public void test3() {
+ public void test2() {
this.reactiveWebApplicationContextRunner.withConfiguration(AutoConfigurations.of(MetadataTransferAutoConfiguration.class))
.run(context -> {
assertThat(context).hasSingleBean(MetadataTransferAutoConfiguration.MetadataTransferFeignInterceptorConfig.class);
- assertThat(context).hasSingleBean(EncodeTransferMedataFeignInterceptor.class);
+ assertThat(context).hasSingleBean(EncodeTransferMedataFeignEnhancedPlugin.class);
assertThat(context).hasSingleBean(MetadataTransferAutoConfiguration.MetadataTransferRestTemplateConfig.class);
- assertThat(context).hasSingleBean(EncodeTransferMedataRestTemplateInterceptor.class);
+ assertThat(context).hasSingleBean(EncodeTransferMedataRestTemplateEnhancedPlugin.class);
assertThat(context).hasSingleBean(MetadataTransferAutoConfiguration.MetadataTransferScgFilterConfig.class);
- assertThat(context).hasSingleBean(GlobalFilter.class);
- assertThat(context).hasSingleBean(EncodeTransferMedataWebClientFilter.class);
+ assertThat(context).hasSingleBean(EncodeTransferMedataWebClientEnhancedPlugin.class);
});
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptorTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptorTest.java
index df3e883f..e34f4e9a 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptorTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptorTest.java
@@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
/**
- * Test for {@link EncodeTransferMedataFeignInterceptor}.
+ * Test for {@link EncodeTransferMedataFeignEnhancedPlugin}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptorTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptorTest.java
index 275784bb..b0ce9217 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptorTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptorTest.java
@@ -17,8 +17,14 @@
package com.tencent.cloud.metadata.core;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Map;
+
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner;
+import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -26,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
@@ -39,7 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
- * Test for {@link EncodeTransferMedataRestTemplateInterceptor}.
+ * Test for {@link EncodeTransferMedataRestTemplateEnhancedPlugin}.
*
* @author Haotian Zhang
*/
@@ -72,7 +79,13 @@ public class EncodeTransferMedataRestTemplateInterceptorTest {
@Bean
public RestTemplate restTemplate() {
- return new RestTemplate();
+
+ EncodeTransferMedataRestTemplateEnhancedPlugin plugin = new EncodeTransferMedataRestTemplateEnhancedPlugin();
+ EnhancedRestTemplateInterceptor interceptor = new EnhancedRestTemplateInterceptor(
+ new DefaultEnhancedPluginRunner(Arrays.asList(plugin), new MockRegistration(), null));
+ RestTemplate template = new RestTemplate();
+ template.setInterceptors(Arrays.asList(interceptor));
+ return template;
}
@RequestMapping("/test")
@@ -80,4 +93,37 @@ public class EncodeTransferMedataRestTemplateInterceptorTest {
return MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "b");
}
}
+
+ static class MockRegistration implements Registration {
+
+ @Override
+ public String getServiceId() {
+ return "test";
+ }
+
+ @Override
+ public String getHost() {
+ return "localhost";
+ }
+
+ @Override
+ public int getPort() {
+ return 0;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public URI getUri() {
+ return null;
+ }
+
+ @Override
+ public Map getMetadata() {
+ return null;
+ }
+ }
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilterTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilterTest.java
index 97f55f73..cbc1116b 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilterTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilterTest.java
@@ -18,59 +18,129 @@
package com.tencent.cloud.metadata.core;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.Map;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
import com.tencent.cloud.common.constant.MetadataConstant;
-import com.tencent.cloud.common.util.JacksonUtils;
+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.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
+import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner;
+import com.tencent.cloud.rpc.enhancement.scg.EnhancedGatewayGlobalFilter;
+import org.assertj.core.util.Maps;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import reactor.core.publisher.Mono;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.route.Route;
import org.springframework.context.ApplicationContext;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.server.ServerWebExchange;
-import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
+import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
+import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
+import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
+import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
/**
- * @author quan
+ * Test for {@link EncodeTransferMedataScgEnhancedPlugin}.
+ * @author quan, Shedfree Wu
*/
-@ExtendWith(SpringExtension.class)
-@SpringBootTest(webEnvironment = RANDOM_PORT, classes = EncodeTransferMedataScgFilterTest.TestApplication.class,
- properties = {"spring.config.location = classpath:application-test.yml",
- "spring.main.web-application-type = reactive"})
+@ExtendWith(MockitoExtension.class)
public class EncodeTransferMedataScgFilterTest {
- @Autowired
- private ApplicationContext applicationContext;
-
+ private static MockedStatic mockedApplicationContextAwareUtils;
+ @Mock
+ Registration registration;
@Mock
- private GatewayFilterChain chain;
+ GatewayFilterChain chain;
- @Test
- public void testTransitiveMetadataFromApplicationConfig() throws UnsupportedEncodingException {
- EncodeTransferMedataScgFilter filter = applicationContext.getBean(EncodeTransferMedataScgFilter.class);
- MockServerHttpRequest.BaseBuilder> builder = MockServerHttpRequest.get("");
- MockServerWebExchange exchange = MockServerWebExchange.from(builder);
- filter.filter(exchange, chain);
- String metadataStr = exchange.getRequest().getHeaders().getFirst(MetadataConstant.HeaderName.CUSTOM_METADATA);
- String decode = URLDecoder.decode(metadataStr, UTF_8);
- Map transitiveMap = JacksonUtils.deserialize2Map(decode);
- assertThat(transitiveMap.size()).isEqualTo(1);
- assertThat(transitiveMap.get("b")).isEqualTo("2");
+ @BeforeAll
+ static void beforeAll() {
+ mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
+ mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
+ .thenReturn("unit-test");
+ ApplicationContext applicationContext = mock(ApplicationContext.class);
+ MetadataLocalProperties metadataLocalProperties = mock(MetadataLocalProperties.class);
+ StaticMetadataManager staticMetadataManager = mock(StaticMetadataManager.class);
+ doReturn(metadataLocalProperties).when(applicationContext).getBean(MetadataLocalProperties.class);
+ doReturn(staticMetadataManager).when(applicationContext).getBean(StaticMetadataManager.class);
+ mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
+ .thenReturn(applicationContext);
+ }
+
+ @AfterAll
+ static void afterAll() {
+ mockedApplicationContextAwareUtils.close();
}
- @SpringBootApplication
- protected static class TestApplication {
+ @BeforeEach
+ void setUp() {
+ MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
+ MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
+ }
+
+ @Test
+ public void testRun() throws URISyntaxException {
+
+ Route route = mock(Route.class);
+ URI uri = new URI("http://TEST/");
+ doReturn(uri).when(route).getUri();
+
+ MetadataContext metadataContext = MetadataContextHolder.get();
+ metadataContext.setTransitiveMetadata(Maps.newHashMap("t-key", "t-value"));
+ metadataContext.setDisposableMetadata(Maps.newHashMap("d-key", "d-value"));
+
+ MockServerHttpRequest mockServerHttpRequest = MockServerHttpRequest.get("/test").build();
+
+ EncodeTransferMedataScgEnhancedPlugin plugin = new EncodeTransferMedataScgEnhancedPlugin();
+ plugin.getOrder();
+ EnhancedGatewayGlobalFilter filter = new EnhancedGatewayGlobalFilter(new DefaultEnhancedPluginRunner(Arrays.asList(plugin), registration, null));
+ filter.getOrder();
+
+ MockServerWebExchange mockServerWebExchange = MockServerWebExchange.builder(mockServerHttpRequest).build();
+ mockServerWebExchange.getAttributes().put(GATEWAY_ROUTE_ATTR, route);
+ mockServerWebExchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, new URI("http://0.0.0.0/"));
+ mockServerWebExchange.getAttributes().put(MetadataConstant.HeaderName.METADATA_CONTEXT, metadataContext);
+ doReturn(Mono.empty()).when(chain).filter(any());
+
+
+ filter.filter(mockServerWebExchange, chain).block();
+
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ServerWebExchange.class);
+ // capture the result exchange
+ Mockito.verify(chain).filter(captor.capture());
+ ServerWebExchange filteredExchange = captor.getValue();
+
+ assertThat(filteredExchange.getRequest().getHeaders().get(CUSTOM_METADATA)).isNotNull();
+ assertThat(filteredExchange.getRequest().getHeaders().get(CUSTOM_DISPOSABLE_METADATA)).isNotNull();
+
+ // test metadataContext init in EnhancedPlugin
+ mockServerWebExchange.getAttributes().remove(MetadataConstant.HeaderName.METADATA_CONTEXT);
+ assertThatCode(() -> filter.filter(mockServerWebExchange, chain).block()).doesNotThrowAnyException();
}
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientFilterTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientFilterTest.java
index 85c8b2d3..fe7c30d2 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientFilterTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientFilterTest.java
@@ -37,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
- * Test for {@link EncodeTransferMedataWebClientFilter}.
+ * Test for {@link EncodeTransferMedataWebClientEnhancedPlugin}.
*
* @author sean yu
*/
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilterTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilterTest.java
index 56895ee2..1c72c5d5 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilterTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilterTest.java
@@ -23,9 +23,13 @@ import java.net.URLDecoder;
import java.util.Map;
import com.netflix.zuul.context.RequestContext;
-import com.tencent.cloud.common.constant.MetadataConstant;
+import com.netflix.zuul.exception.ZuulException;
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.rpc.enhancement.zuul.EnhancedPreZuulFilter;
import org.assertj.core.api.Assertions;
+import org.assertj.core.util.Maps;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -38,12 +42,16 @@ import org.springframework.mock.web.MockMultipartHttpServletRequest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
+import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
+import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY;
/**
- * Test for {@link EncodeTransferMetadataZuulFilter}.
+ * Test for {@link EncodeTransferMetadataZuulEnhancedPlugin}.
*
- * @author quan
+ * @author quan, Shedfree Wu
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = RANDOM_PORT,
@@ -64,17 +72,30 @@ public class EncodeTransferMetadataZuulFilterTest {
}
@Test
- public void multiplePartNamesWithMultipleParts() throws UnsupportedEncodingException {
- EncodeTransferMetadataZuulFilter filter = applicationContext.getBean(EncodeTransferMetadataZuulFilter.class);
+ public void testRun() throws ZuulException, UnsupportedEncodingException {
+ EnhancedPreZuulFilter filter = applicationContext.getBean(EnhancedPreZuulFilter.class);
+ RequestContext context = RequestContext.getCurrentContext();
+ context.set(SERVICE_ID_KEY, "test-service");
+
+ MetadataContext metadataContext = MetadataContextHolder.get();
+ metadataContext.setTransitiveMetadata(Maps.newHashMap("t-key", "t-value"));
+ metadataContext.setDisposableMetadata(Maps.newHashMap("d-key", "d-value"));
filter.run();
+
final RequestContext ctx = RequestContext.getCurrentContext();
Map zuulRequestHeaders = ctx.getZuulRequestHeaders();
- String metadata = zuulRequestHeaders.get(MetadataConstant.HeaderName.CUSTOM_METADATA.toLowerCase());
+ // convert header to lower case in com.netflix.zuul.context.RequestContext.addZuulRequestHeader
+ assertThat(zuulRequestHeaders.get(CUSTOM_METADATA.toLowerCase())).isNotNull();
+ assertThat(zuulRequestHeaders.get(CUSTOM_DISPOSABLE_METADATA.toLowerCase())).isNotNull();
+
+ String metadata = zuulRequestHeaders.get(CUSTOM_METADATA.toLowerCase());
+
Assertions.assertThat(metadata).isNotNull();
String decode = URLDecoder.decode(metadata, UTF_8);
Map transitiveMap = JacksonUtils.deserialize2Map(decode);
- Assertions.assertThat(transitiveMap.size()).isEqualTo(1);
+ // expect {"b":"2","t-key":"t-value"}
+ Assertions.assertThat(transitiveMap.size()).isEqualTo(2);
Assertions.assertThat(transitiveMap.get("b")).isEqualTo("2");
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/provider/MetadataProviderTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/provider/MetadataProviderTest.java
new file mode 100644
index 00000000..ff7aedc5
--- /dev/null
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/provider/MetadataProviderTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.metadata.provider;
+
+import com.tencent.cloud.common.util.UrlUtils;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
+import org.junit.Test;
+
+import org.springframework.http.HttpCookie;
+import org.springframework.http.HttpMethod;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.MockCookie;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test for {@link ReactiveMetadataProvider} and {@link ServletMetadataProvider}.
+ *
+ * @author quan, Shedfree Wu
+ */
+public class MetadataProviderTest {
+
+ private static final String notExistKey = "empty";
+
+ @Test
+ public void testReactiveMetadataProvider() {
+ String headerKey1 = "header1";
+ String headerKey2 = "header2";
+ String headerValue1 = "value1";
+ String headerValue2 = "value2/test";
+ String queryKey1 = "qk1";
+ String queryKey2 = "qk2";
+ String queryValue1 = "qv1";
+ String queryValue2 = "qv2/test";
+ String cookieKey1 = "ck1";
+ String cookieKey2 = "ck2";
+ String cookieValue1 = "cv1";
+ String cookieValue2 = "cv2/test";
+ String path = "/echo/test";
+ MockServerHttpRequest request = MockServerHttpRequest.get(path)
+ .header(headerKey1, headerValue1)
+ .header(headerKey2, UrlUtils.encode(headerValue2))
+ .queryParam(queryKey1, queryValue1)
+ .queryParam(queryKey2, UrlUtils.encode(queryValue2))
+ .cookie(new HttpCookie(cookieKey1, cookieValue1))
+ .cookie(new HttpCookie(cookieKey2, UrlUtils.encode(cookieValue2)))
+ .build();
+
+ ReactiveMetadataProvider reactiveMetadataProvider = new ReactiveMetadataProvider(request);
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, headerKey1)).isEqualTo(headerValue1);
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, headerKey2)).isEqualTo(headerValue2);
+ // com.tencent.polaris.metadata.core.manager.ComposeMetadataProvider.getRawMetadataMapValue need return null when key don't exist
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, notExistKey)).isNull();
+
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, cookieKey1)).isEqualTo(cookieValue1);
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, cookieKey2)).isEqualTo(cookieValue2);
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, notExistKey)).isNull();
+
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, queryKey1)).isEqualTo(queryValue1);
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, queryKey2)).isEqualTo(queryValue2);
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, notExistKey)).isNull();
+ assertThat(reactiveMetadataProvider.getRawMetadataMapValue(notExistKey, queryKey1)).isNull();
+
+ assertThat(reactiveMetadataProvider.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_METHOD)).isEqualTo("GET");
+ assertThat(reactiveMetadataProvider.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_PATH)).isEqualTo(path);
+ assertThat(reactiveMetadataProvider.getRawMetadataStringValue(notExistKey)).isNull();
+
+ request = MockServerHttpRequest.get("/echo/" + UrlUtils.decode("a@b")).build();
+ reactiveMetadataProvider = new ReactiveMetadataProvider(request);
+ assertThat(reactiveMetadataProvider.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_PATH)).isEqualTo("/echo/a@b");
+ }
+
+ @Test
+ public void testServletMetadataProvider() {
+ String headerKey1 = "header1";
+ String headerKey2 = "header2";
+ String headerValue1 = "value1";
+ String headerValue2 = "value2/test";
+ String queryKey1 = "qk1";
+ String queryKey2 = "qk2";
+ String queryValue1 = "qv1";
+ String queryValue2 = "qv2/test";
+ String cookieKey1 = "ck1";
+ String cookieKey2 = "ck2";
+ String cookieValue1 = "cv1";
+ String cookieValue2 = "cv2/test";
+ String path = "/echo/test";
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addHeader(headerKey1, headerValue1);
+ request.addHeader(headerKey2, UrlUtils.encode(headerValue2));
+ request.setCookies(new MockCookie(cookieKey1, cookieValue1), new MockCookie(cookieKey2, UrlUtils.encode(cookieValue2)));
+ request.setMethod(HttpMethod.GET.name());
+ request.setRequestURI(path);
+ request.setQueryString(queryKey1 + "=" + queryValue1 + "&" + queryKey2 + "=" + UrlUtils.encode(queryValue2));
+
+ ServletMetadataProvider servletMetadataProvider = new ServletMetadataProvider(request);
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, headerKey1)).isEqualTo(headerValue1);
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, headerKey2)).isEqualTo(headerValue2);
+ // com.tencent.polaris.metadata.core.manager.ComposeMetadataProvider.getRawMetadataMapValue need return null when key don't exist
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, notExistKey)).isNull();
+
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, cookieKey1)).isEqualTo(cookieValue1);
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, cookieKey2)).isEqualTo(cookieValue2);
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, notExistKey)).isNull();
+
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, queryKey1)).isEqualTo(queryValue1);
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, queryKey2)).isEqualTo(queryValue2);
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, notExistKey)).isNull();
+ assertThat(servletMetadataProvider.getRawMetadataMapValue(notExistKey, queryKey1)).isNull();
+
+ assertThat(servletMetadataProvider.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_METHOD)).isEqualTo("GET");
+ assertThat(servletMetadataProvider.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_PATH)).isEqualTo(path);
+ assertThat(servletMetadataProvider.getRawMetadataStringValue(notExistKey)).isNull();
+
+ request.setRequestURI("/echo/" + UrlUtils.decode("a@b"));
+ assertThat(servletMetadataProvider.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_PATH)).isEqualTo("/echo/a@b");
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/pom.xml b/spring-cloud-starter-tencent-polaris-router/pom.xml
index 56ac0fe5..98ab742b 100644
--- a/spring-cloud-starter-tencent-polaris-router/pom.xml
+++ b/spring-cloud-starter-tencent-polaris-router/pom.xml
@@ -48,6 +48,10 @@
com.tencent.polaris
router-nearby
+
+ com.tencent.polaris
+ router-lane
+
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
index be2a3705..2ad9dbb2 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
@@ -36,10 +36,6 @@ public class OrderConstant {
* Order constant for Feign.
*/
public static class Feign {
- /**
- * Order of encode transfer metadata interceptor.
- */
- public static final int ENCODE_TRANSFER_METADATA_INTERCEPTOR_ORDER = Ordered.LOWEST_PRECEDENCE - 1;
/**
* Order of encode router label interceptor.
@@ -51,10 +47,6 @@ public class OrderConstant {
* Order constant for RestTemplate.
*/
public static class RestTemplate {
- /**
- * Order of encode transfer metadata interceptor.
- */
- public static final int ENCODE_TRANSFER_METADATA_INTERCEPTOR_ORDER = Ordered.LOWEST_PRECEDENCE - 1;
/**
* Order of encode router label interceptor.
@@ -67,12 +59,6 @@ public class OrderConstant {
*/
public static class Scg {
- /**
- * Order of encode transfer metadata filter.
- * {@link ReactiveLoadBalancerClientFilter}.LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150.
- */
- public static final int ENCODE_TRANSFER_METADATA_FILTER_ORDER = 10150 + 1;
-
/**
* Order of enhanced filter.
* {@link ReactiveLoadBalancerClientFilter}.LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150.
@@ -85,11 +71,6 @@ public class OrderConstant {
*/
public static class Zuul {
- /**
- * Order of encode transfer metadata filter.
- */
- public static final int ENCODE_TRANSFER_METADATA_FILTER_ORDER = RIBBON_ROUTING_FILTER_ORDER - 1;
-
/**
* Order of enhanced ROUTE filter.
*/
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
index 90e59921..37329ea6 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
@@ -24,7 +24,9 @@ import java.util.Optional;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
+import com.tencent.polaris.metadata.core.MessageMetadataContainer;
import com.tencent.polaris.metadata.core.MetadataContainer;
+import com.tencent.polaris.metadata.core.MetadataProvider;
import com.tencent.polaris.metadata.core.MetadataType;
import com.tencent.polaris.metadata.core.TransitiveType;
@@ -129,8 +131,10 @@ public final class MetadataContextHolder {
*
* @param dynamicTransitiveMetadata custom metadata collection
* @param dynamicDisposableMetadata custom disposable metadata connection
+ * @param callerMetadataProvider caller metadata provider
*/
- public static void init(Map dynamicTransitiveMetadata, Map dynamicDisposableMetadata) {
+ public static void init(Map dynamicTransitiveMetadata, Map dynamicDisposableMetadata,
+ MetadataProvider callerMetadataProvider) {
com.tencent.polaris.metadata.core.manager.MetadataContextHolder.refresh(MetadataContextHolder::createMetadataManager, metadataManager -> {
MetadataContainer metadataContainerUpstream = metadataManager.getMetadataContainer(MetadataType.CUSTOM, false);
if (!CollectionUtils.isEmpty(dynamicTransitiveMetadata)) {
@@ -144,6 +148,10 @@ public final class MetadataContextHolder {
metadataContainerDownstream.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE);
}
}
+ if (callerMetadataProvider != null) {
+ MessageMetadataContainer callerMessageContainer = metadataManager.getMetadataContainer(MetadataType.MESSAGE, true);
+ callerMessageContainer.setMetadataProvider(callerMetadataProvider);
+ }
});
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ReflectionUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ReflectionUtils.java
index b9f75b94..d822b194 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ReflectionUtils.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ReflectionUtils.java
@@ -68,4 +68,20 @@ public final class ReflectionUtils extends org.springframework.util.ReflectionUt
}
return null;
}
+
+ public static void setFieldValue(Object instance, String fieldName, Object value) {
+ Field field = org.springframework.util.ReflectionUtils.findField(instance.getClass(), fieldName);
+ if (field == null) {
+ return;
+ }
+
+ field.setAccessible(true);
+
+ try {
+ setField(field, instance, value);
+ }
+ finally {
+ field.setAccessible(false);
+ }
+ }
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/UrlUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/UrlUtils.java
new file mode 100644
index 00000000..6190f33c
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/UrlUtils.java
@@ -0,0 +1,78 @@
+/*
+ * 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 java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.util.StringUtils;
+
+import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
+
+/**
+ * Utils for URLDecoder/URLEncoder.
+ *
+ * @author Shedfree Wu
+ */
+public final class UrlUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(UrlUtils.class);
+
+ private UrlUtils() {
+ }
+
+ public static String decode(String s) {
+ return decode(s, UTF_8);
+ }
+
+ public static String decode(String s, String enc) {
+ if (!StringUtils.hasText(s)) {
+ return s;
+ }
+ try {
+ return URLDecoder.decode(s, enc);
+ }
+ catch (UnsupportedEncodingException e) {
+ LOG.warn("Runtime system does not support {} coding. s:{}, msg:{}", enc, s, e.getMessage());
+ // return original string
+ return s;
+ }
+ }
+
+ public static String encode(String s) {
+ return encode(s, UTF_8);
+ }
+
+ public static String encode(String s, String enc) {
+ if (!StringUtils.hasText(s)) {
+ return s;
+ }
+ try {
+ return URLEncoder.encode(s, enc);
+ }
+ catch (UnsupportedEncodingException e) {
+ LOG.warn("Runtime system does not support {} coding. s:{}, msg:{}", enc, s, e.getMessage());
+ // return original string
+ return s;
+ }
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java
index c7029def..9c5e73b9 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java
@@ -138,12 +138,16 @@ public final class ExpressionLabelUtils {
}
public static String getQueryValue(String queryString, String queryKey) {
+ return getQueryValue(queryString, queryKey, StringUtils.EMPTY);
+ }
+
+ public static String getQueryValue(String queryString, String queryKey, String defaultValue) {
if (StringUtils.isBlank(queryString)) {
- return StringUtils.EMPTY;
+ return defaultValue;
}
String[] queries = StringUtils.split(queryString, "&");
if (queries == null || queries.length == 0) {
- return StringUtils.EMPTY;
+ return defaultValue;
}
for (String query : queries) {
String[] queryKV = StringUtils.split(query, "=");
@@ -151,7 +155,7 @@ public final class ExpressionLabelUtils {
return queryKV[1];
}
}
- return StringUtils.EMPTY;
+ return defaultValue;
}
public static String getFirstValue(Map> valueMaps, String key) {
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ServletExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ServletExpressionLabelUtils.java
index a054c8f6..45ad670b 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ServletExpressionLabelUtils.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ServletExpressionLabelUtils.java
@@ -83,14 +83,18 @@ public final class ServletExpressionLabelUtils {
}
public static String getCookieValue(Cookie[] cookies, String key) {
+ return getCookieValue(cookies, key, StringUtils.EMPTY);
+ }
+
+ public static String getCookieValue(Cookie[] cookies, String key, String defaultValue) {
if (cookies == null || cookies.length == 0) {
- return StringUtils.EMPTY;
+ return defaultValue;
}
for (Cookie cookie : cookies) {
if (StringUtils.equals(cookie.getName(), key)) {
return cookie.getValue();
}
}
- return StringUtils.EMPTY;
+ return defaultValue;
}
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java
index b8b1a59a..476aeeec 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java
@@ -129,29 +129,41 @@ public final class SpringWebExpressionLabelUtils {
}
public static String getHeaderValue(ServerHttpRequest request, String key) {
+ return getHeaderValue(request, key, StringUtils.EMPTY);
+ }
+
+ public static String getHeaderValue(ServerHttpRequest request, String key, String defaultValue) {
String value = request.getHeaders().getFirst(key);
if (value == null) {
- return StringUtils.EMPTY;
+ return defaultValue;
}
return value;
}
public static String getQueryValue(ServerHttpRequest request, String key) {
+ return getQueryValue(request, key, StringUtils.EMPTY);
+ }
+
+ public static String getQueryValue(ServerHttpRequest request, String key, String defaultValue) {
MultiValueMap queries = request.getQueryParams();
if (CollectionUtils.isEmpty(queries)) {
- return StringUtils.EMPTY;
+ return defaultValue;
}
String value = queries.getFirst(key);
if (value == null) {
- return StringUtils.EMPTY;
+ return defaultValue;
}
return value;
}
public static String getCookieValue(ServerHttpRequest request, String key) {
+ return getCookieValue(request, key, StringUtils.EMPTY);
+ }
+
+ public static String getCookieValue(ServerHttpRequest request, String key, String defaultValue) {
HttpCookie cookie = request.getCookies().getFirst(key);
if (cookie == null) {
- return StringUtils.EMPTY;
+ return defaultValue;
}
return cookie.getValue();
}
diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java
index cc992ce1..c2cd05b8 100644
--- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java
+++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java
@@ -63,7 +63,7 @@ public class MetadataContextHolderTest {
customMetadata.put("a", "1");
customMetadata.put("b", "22");
customMetadata.put("c", "3");
- MetadataContextHolder.init(customMetadata, new HashMap<>());
+ MetadataContextHolder.init(customMetadata, new HashMap<>(), null);
metadataContext = MetadataContextHolder.get();
customMetadata = metadataContext.getTransitiveMetadata();
Assertions.assertThat(customMetadata.get("a")).isEqualTo("1");
diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/UrlUtilsTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/UrlUtilsTest.java
new file mode 100644
index 00000000..3d77d047
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/UrlUtilsTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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 org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Utils for {@link UrlUtils}.
+ *
+ * @author Shedfree Wu
+ */
+public class UrlUtilsTest {
+
+ @Test
+ public void testEncodeDecode1() {
+ String expectEncodeValue = "a%2Fb";
+ String origin = "a/b";
+ String encode1 = UrlUtils.encode(origin);
+ assertThat(expectEncodeValue).isEqualTo(encode1);
+ // encode twice is different
+ String encode2 = UrlUtils.encode(encode1);
+ assertThat(encode1).isNotEqualTo(encode2);
+ // test decode
+ assertThat(origin).isEqualTo(UrlUtils.decode(encode1));
+ }
+
+ @Test
+ public void testEncodeDecode2() {
+
+ String origin = null;
+ String encode1 = UrlUtils.encode(origin);
+ assertThat(encode1).isNull();
+
+ origin = "";
+ encode1 = UrlUtils.encode(origin);
+ assertThat(encode1).isEqualTo(origin);
+ }
+
+ @Test
+ public void testError() {
+ String origin = "a/b";
+ String encode = UrlUtils.encode(origin, "error-enc");
+ assertThat(encode).isEqualTo(origin);
+
+ encode = "a%2Fb";
+ String decode = UrlUtils.decode(encode, "error-enc");
+ assertThat(decode).isEqualTo(encode);
+ }
+
+}
diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java
index 072255d8..ce586e97 100644
--- a/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java
+++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java
@@ -28,6 +28,8 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -80,6 +82,26 @@ public class QuickstartCalleeController {
return String.format("Quickstart [%s] Service [%s:%s] is called. datasource = [%s].", appName, ip, port, dataSourceProperties);
}
+ /**
+ * Mock post save value.
+ * @return true
+ */
+ @PostMapping("/saveValue")
+ public Boolean saveValue(@RequestParam int value) {
+ LOG.info("Quickstart [{}] Service [{}:{}] is called. Mock save value = [{}].", appName, ip, port, value);
+ return true;
+ }
+
+ /**
+ * Get path echo of callee.
+ * @return information of callee
+ */
+ @GetMapping("/path/echo/{param}")
+ public String pathEcho(@PathVariable String param) {
+ LOG.info("Quickstart [{}] Service [{}:{}] is called. param = [{}].", appName, ip, port, param);
+ return String.format("Quickstart [%s] Service [%s:%s] is called. datasource = [%s].", appName, ip, port, param);
+ }
+
/**
* Get metadata in HTTP header.
*
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java
index 07335adf..d9b13834 100644
--- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java
+++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java
@@ -76,8 +76,8 @@ public class PolarisLoadBalancer extends DynamicServerListLoadBalancer {
@Override
public List getReachableServers() {
- // Get servers first from the thread context
- if (!CollectionUtils.isEmpty(THREAD_CACHE_SERVERS.get())) {
+ // Get servers first from the thread context. When routers filter all instances, getReachableServersWithoutCache function cannot be executed.
+ if (THREAD_CACHE_SERVERS.get() != null) {
return THREAD_CACHE_SERVERS.get();
}
return getReachableServersWithoutCache();
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java
index f50e5df5..ec0e2397 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java
@@ -67,6 +67,7 @@ public class EnhancedFeignClient implements Client {
.url(url)
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
+ enhancedPluginContext.setOriginRequest(request);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(request.requestTemplate().feignTarget()
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContext.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContext.java
index 7eb14ae8..e9ef0cc6 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContext.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContext.java
@@ -36,6 +36,8 @@ public class EnhancedPluginContext {
private static final Logger LOGGER = LoggerFactory.getLogger(EnhancedPluginContext.class);
+ private Object originRequest;
+
private EnhancedRequestContext request;
private EnhancedResponseContext response;
@@ -51,6 +53,14 @@ public class EnhancedPluginContext {
*/
private ServiceInstance targetServiceInstance;
+ public Object getOriginRequest() {
+ return originRequest;
+ }
+
+ public void setOriginRequest(Object originRequest) {
+ this.originRequest = originRequest;
+ }
+
public EnhancedRequestContext getRequest() {
return request;
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java
index 6677dac0..eff88f13 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java
@@ -44,5 +44,19 @@ public class PluginOrderConstant {
* {@link com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter}.
*/
public static final int CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 2;
+
+ /**
+ * order for
+ * {@link com.tencent.cloud.metadata.core.EncodeTransferMedataFeignEnhancedPlugin}
+ * and
+ * {@link com.tencent.cloud.metadata.core.EncodeTransferMedataScgEnhancedPlugin}
+ * and
+ * {@link com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientEnhancedPlugin}
+ * and
+ * {@link com.tencent.cloud.metadata.core.EncodeTransferMedataZuulEnhancedPlugin}
+ * and
+ * {@link com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateEnhancedPlugin}.
+ */
+ public static final int CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 10;
}
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptor.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptor.java
index c50cbb90..6241ac59 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptor.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptor.java
@@ -58,6 +58,7 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce
.url(request.getURI())
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
+ enhancedPluginContext.setOriginRequest(request);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance((ServiceInstance) MetadataContextHolder.get()
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java
index f42aff2b..7b65f2e8 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java
@@ -51,19 +51,21 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
}
@Override
- public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ public Mono filter(ServerWebExchange originExchange, GatewayFilterChain chain) {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
- .httpHeaders(exchange.getRequest().getHeaders())
- .httpMethod(exchange.getRequest().getMethod())
- .url(exchange.getRequest().getURI())
+ .httpHeaders(originExchange.getRequest().getHeaders())
+ .httpMethod(originExchange.getRequest().getMethod())
+ .url(originExchange.getRequest().getURI())
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
+ enhancedPluginContext.setOriginRequest(originExchange);
// Run pre enhanced plugins.
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
-
+ // Exchange may be changed in plugin
+ ServerWebExchange exchange = (ServerWebExchange) enhancedPluginContext.getOriginRequest();
long startTime = System.currentTimeMillis();
return chain.filter(exchange)
.doOnSubscribe(v -> {
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java
index 673cac3d..a215cfe8 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java
@@ -46,23 +46,25 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
}
@Override
- public Mono filter(ClientRequest request, ExchangeFunction next) {
+ public Mono filter(ClientRequest originRequest, ExchangeFunction next) {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
- .httpHeaders(request.headers())
- .httpMethod(request.method())
- .url(request.url())
+ .httpHeaders(originRequest.headers())
+ .httpMethod(originRequest.method())
+ .url(originRequest.url())
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
+ enhancedPluginContext.setOriginRequest(originRequest);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance((ServiceInstance) MetadataContextHolder.get()
- .getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE), request.url());
+ .getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE), originRequest.url());
// Run post enhanced plugins.
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
-
+ // request may be changed by plugin
+ ClientRequest request = (ClientRequest) enhancedPluginContext.getOriginRequest();
long startTime = System.currentTimeMillis();
return next.exchange(request)
.doOnSuccess(response -> {
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedPreZuulFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedPreZuulFilter.java
index 1254209c..094f24f7 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedPreZuulFilter.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedPreZuulFilter.java
@@ -99,6 +99,7 @@ public class EnhancedPreZuulFilter extends ZuulFilter {
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
+ enhancedPluginContext.setOriginRequest(context);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
// Run pre enhanced plugins.