From 7837e2188a2135267e645faa886a9fb8ffd9e272 Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Mon, 16 Oct 2023 11:12:42 +0800 Subject: [PATCH] feat:add metadata transfer for http header via spring.cloud.tencent.metadata.headers. (#1174) Co-authored-by: wenxuan70 --- CHANGELOG.md | 1 + .../metadata/MetadataContextHolder.java | 4 +-- .../metadata/StaticMetadataManager.java | 30 +++++++++++++++++++ .../config/MetadataLocalProperties.java | 16 ++++++++++ ...itional-spring-configuration-metadata.json | 5 ++++ .../metadata/MetadataContextHolderTest.java | 8 +++++ .../metadata/StaticMetadataManagerTest.java | 11 +++++++ .../config/MetadataLocalPropertiesTest.java | 6 ++++ .../src/test/resources/application-test.yml | 3 ++ 9 files changed, 82 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb04f01d1..a39c72bf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,3 +13,4 @@ - [fix:fix retry loadbalancer not working bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1157) - [fix:fix header validation when using Chinese char.](https://github.com/Tencent/spring-cloud-tencent/pull/1167) - [feat: add circuit breaker actuator.](https://github.com/Tencent/spring-cloud-tencent/pull/1172) +- [feat: add metadata transfer for http header via spring.cloud.tencent.metadata.headers.](https://github.com/Tencent/spring-cloud-tencent/pull/1174) 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 90a949d2e..4251b8d3d 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 @@ -68,8 +68,8 @@ public static MetadataContext get() { metadataContext.setTransitiveMetadata(staticMetadataManager.getMergedStaticTransitiveMetadata()); metadataContext.setDisposableMetadata(staticMetadataManager.getMergedStaticDisposableMetadata()); - if (StringUtils.hasText(staticMetadataManager.getTransHeaderFromEnv())) { - metadataContext.setTransHeaders(staticMetadataManager.getTransHeaderFromEnv(), ""); + if (StringUtils.hasText(staticMetadataManager.getTransHeader())) { + metadataContext.setTransHeaders(staticMetadataManager.getTransHeader(), ""); } METADATA_CONTEXT.set(metadataContext); diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java index d37deb006..f0171cebb 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java @@ -17,8 +17,11 @@ package com.tencent.cloud.common.metadata; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -71,6 +74,7 @@ public class StaticMetadataManager { private Map configMetadata; private Map configTransitiveMetadata; private Map configDisposableMetadata; + private String configTransHeaders; private Map customSPIMetadata; private Map customSPITransitiveMetadata; private Map customSPIDisposableMetadata; @@ -162,6 +166,7 @@ private void parseConfigMetadata(MetadataLocalProperties metadataLocalProperties Map allMetadata = metadataLocalProperties.getContent(); List transitiveKeys = metadataLocalProperties.getTransitive(); List disposableKeys = metadataLocalProperties.getDisposable(); + List headers = metadataLocalProperties.getHeaders(); Map transitiveResult = new HashMap<>(); for (String key : transitiveKeys) { @@ -179,6 +184,7 @@ private void parseConfigMetadata(MetadataLocalProperties metadataLocalProperties configTransitiveMetadata = Collections.unmodifiableMap(transitiveResult); configDisposableMetadata = Collections.unmodifiableMap(disposableResult); + configTransHeaders = CollectionUtils.isEmpty(headers) ? null : String.join(",", headers); configMetadata = Collections.unmodifiableMap(allMetadata); } @@ -313,6 +319,29 @@ public String getTransHeaderFromEnv() { return envNotReportMetadata.get(ENV_TRAFFIC_CONTENT_RAW_TRANSHEADERS); } + public String getTransHeaderFromConfig() { + return configTransHeaders; + } + + public String getTransHeader() { + Set transHeaderSet = new HashSet<>(); + + String transHeaderFromEnv = getTransHeaderFromEnv(); + String transHeaderFromConfig = getTransHeaderFromConfig(); + + Set transHeaderFromEnvSet = StringUtils.isNotBlank(transHeaderFromEnv) + ? Arrays.stream(transHeaderFromEnv.split(",")).collect(Collectors.toSet()) + : Collections.emptySet(); + Set transHeaderFromConfigSet = StringUtils.isNotBlank(transHeaderFromConfig) + ? Arrays.stream(transHeaderFromConfig.split(",")).collect(Collectors.toSet()) + : Collections.emptySet(); + + transHeaderSet.addAll(transHeaderFromEnvSet); + transHeaderSet.addAll(transHeaderFromConfigSet); + + return new ArrayList<>(transHeaderSet).stream().sorted().collect(Collectors.joining(",")); + } + public Map getEnvTransitiveMetadata() { return envTransitiveMetadata; } @@ -390,6 +419,7 @@ public String toString() { ", envTransitiveMetadata=" + envTransitiveMetadata + ", configMetadata=" + configMetadata + ", configTransitiveMetadata=" + configTransitiveMetadata + + ", configTransHeaders='" + configTransHeaders + '\'' + ", customSPIMetadata=" + customSPIMetadata + ", customSPITransitiveMetadata=" + customSPITransitiveMetadata + ", mergedStaticMetadata=" + mergedStaticMetadata + diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/config/MetadataLocalProperties.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/config/MetadataLocalProperties.java index 2964e0178..64ba52cb8 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/config/MetadataLocalProperties.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/config/MetadataLocalProperties.java @@ -48,6 +48,11 @@ public class MetadataLocalProperties { */ private List disposable; + /** + * A transitive http header key list. + */ + private List headers; + public Map getContent() { if (CollectionUtils.isEmpty(content)) { content = new HashMap<>(); @@ -80,4 +85,15 @@ public List getDisposable() { public void setDisposable(List disposable) { this.disposable = disposable; } + + public List getHeaders() { + if (CollectionUtils.isEmpty(headers)) { + headers = new ArrayList<>(); + } + return headers; + } + + public void setHeaders(List headers) { + this.headers = headers; + } } diff --git a/spring-cloud-tencent-commons/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-tencent-commons/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 575ca9738..291e26dbe 100644 --- a/spring-cloud-tencent-commons/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-tencent-commons/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -14,6 +14,11 @@ "name": "spring.cloud.tencent.metadata.disposable", "type": "java.util.List", "description": "Custom disposable metadata key list." + }, + { + "name": "spring.cloud.tencent.metadata.headers", + "type": "java.util.List", + "description": "Custom transitive http header key list." } ] } 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 51c5af87d..cc992ce19 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 @@ -53,6 +53,10 @@ public void test1() { Assertions.assertThat(customMetadata.get("a")).isEqualTo("1"); Assertions.assertThat(customMetadata.get("b")).isEqualTo("2"); + Map transHeaders = MetadataContextHolder.get().getTransHeaders(); + Assertions.assertThat(transHeaders.size()).isEqualTo(1); + Assertions.assertThat(transHeaders.keySet().iterator().next()).isEqualTo("c,d"); + MetadataContextHolder.remove(); customMetadata = new HashMap<>(); @@ -66,6 +70,10 @@ public void test1() { Assertions.assertThat(customMetadata.get("b")).isEqualTo("22"); Assertions.assertThat(customMetadata.get("c")).isEqualTo("3"); Assertions.assertThat(MetadataContext.LOCAL_NAMESPACE).isEqualTo("default"); + + transHeaders = MetadataContextHolder.get().getTransHeaders(); + Assertions.assertThat(transHeaders.size()).isEqualTo(1); + Assertions.assertThat(transHeaders.keySet().iterator().next()).isEqualTo("c,d"); } @Test diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/StaticMetadataManagerTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/StaticMetadataManagerTest.java index 784213c57..f6fddcea5 100644 --- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/StaticMetadataManagerTest.java +++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/StaticMetadataManagerTest.java @@ -97,6 +97,7 @@ public void testParseConfigMetadata() { when(metadataLocalProperties.getContent()).thenReturn(content); when(metadataLocalProperties.getTransitive()).thenReturn(Collections.singletonList("k1")); when(metadataLocalProperties.getDisposable()).thenReturn(Collections.singletonList("k1")); + when(metadataLocalProperties.getHeaders()).thenReturn(Arrays.asList("a", "d")); StaticMetadataManager metadataManager = new StaticMetadataManager(metadataLocalProperties, null); @@ -119,6 +120,9 @@ public void testParseConfigMetadata() { Map locationInfo = metadataManager.getLocationMetadata(); assertThat(locationInfo.get("zone")).isEqualTo("zone1"); assertThat(locationInfo.get("region")).isEqualTo("region1"); + + String transHeaderFromConfig = metadataManager.getTransHeaderFromConfig(); + assertThat(transHeaderFromConfig).isEqualTo("a,d"); } @Test @@ -161,6 +165,9 @@ public void testCustomSPIMetadata() { @Test public void testMergedMetadata() { + // set environment variables + environmentVariables.set("SCT_TRAFFIC_CONTENT_RAW_TRANSHEADERS", "a,b,c,e"); + Map content = new HashMap<>(); content.put("k1", "v1"); content.put("k2", "v2"); @@ -170,6 +177,7 @@ public void testMergedMetadata() { when(metadataLocalProperties.getContent()).thenReturn(content); when(metadataLocalProperties.getTransitive()).thenReturn(Collections.singletonList("k1")); + when(metadataLocalProperties.getHeaders()).thenReturn(Arrays.asList("b", "d")); StaticMetadataManager metadataManager = new StaticMetadataManager(metadataLocalProperties, Arrays.asList(new MockedMetadataProvider(), new DefaultInstanceMetadataProvider(null))); @@ -204,6 +212,9 @@ public void testMergedMetadata() { assertThat(locationInfo.get("zone")).isEqualTo("zone2"); assertThat(locationInfo.get("region")).isEqualTo("region1"); assertThat(locationInfo.get("campus")).isEqualTo("campus2"); + + String transHeader = metadataManager.getTransHeader(); + assertThat(transHeader).isEqualTo("a,b,c,d,e"); } @Test diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataLocalPropertiesTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataLocalPropertiesTest.java index 1e5ee769d..a7fcf2725 100644 --- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataLocalPropertiesTest.java +++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataLocalPropertiesTest.java @@ -56,6 +56,12 @@ public void test2() { .isTrue(); } + @Test + public void test3() { + Assertions.assertThat(metadataLocalProperties.getHeaders().contains("c")).isTrue(); + Assertions.assertThat(metadataLocalProperties.getHeaders().contains("d")).isTrue(); + } + @SpringBootApplication protected static class TestApplication { diff --git a/spring-cloud-tencent-commons/src/test/resources/application-test.yml b/spring-cloud-tencent-commons/src/test/resources/application-test.yml index f0b649a0c..bea1a0586 100644 --- a/spring-cloud-tencent-commons/src/test/resources/application-test.yml +++ b/spring-cloud-tencent-commons/src/test/resources/application-test.yml @@ -13,3 +13,6 @@ spring: b: 2 transitive: - b + headers: + - c + - d