feat:support service contract reporting. (#1141)

pull/1150/head
Haotian Zhang 1 year ago committed by GitHub
parent e40ea737af
commit e4e5f5a4c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -16,7 +16,7 @@ header:
CONDITIONS OF ANY KIND, either express or implied. See the License for the CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License. specific language governing permissions and limitations under the License.
paths: paths:
- "**/java/**" - "**/tencent/**"
language: language:
Java: Java:
extensions: extensions:

@ -5,4 +5,5 @@
- [Refactoring:remove invalid @AutoConfigureAfter and @AutoConfigureBefore from discovery client automatic configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1116) - [Refactoring:remove invalid @AutoConfigureAfter and @AutoConfigureBefore from discovery client automatic configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1116)
- [fix:fix feign url bug when using sleuth.](https://github.com/Tencent/spring-cloud-tencent/pull/1120) - [fix:fix feign url bug when using sleuth.](https://github.com/Tencent/spring-cloud-tencent/pull/1120)
- [refactor:optimize the order and condition matching of service registration automatic configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1131) - [refactor:optimize the order and condition matching of service registration automatic configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1131)
- [feat:support service contract reporting.](https://github.com/Tencent/spring-cloud-tencent/pull/1141)
- [feat: support log path configuration parameters,](https://github.com/Tencent/spring-cloud-tencent/pull/1142) - [feat: support log path configuration parameters,](https://github.com/Tencent/spring-cloud-tencent/pull/1142)

@ -47,6 +47,7 @@
<module>spring-cloud-starter-tencent-polaris-ratelimit</module> <module>spring-cloud-starter-tencent-polaris-ratelimit</module>
<module>spring-cloud-starter-tencent-polaris-circuitbreaker</module> <module>spring-cloud-starter-tencent-polaris-circuitbreaker</module>
<module>spring-cloud-starter-tencent-polaris-router</module> <module>spring-cloud-starter-tencent-polaris-router</module>
<module>spring-cloud-starter-tencent-polaris-contract</module>
<module>spring-cloud-tencent-plugin-starters</module> <module>spring-cloud-tencent-plugin-starters</module>
<module>spring-cloud-tencent-dependencies</module> <module>spring-cloud-tencent-dependencies</module>
<module>spring-cloud-starter-tencent-all</module> <module>spring-cloud-starter-tencent-all</module>

@ -45,6 +45,11 @@
<artifactId>spring-cloud-starter-tencent-metadata-transfer</artifactId> <artifactId>spring-cloud-starter-tencent-metadata-transfer</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-contract</artifactId>
</dependency>
<!-- Spring Cloud --> <!-- Spring Cloud -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
@ -88,12 +93,19 @@
<configuration> <configuration>
<createSourcesJar>true</createSourcesJar> <createSourcesJar>true</createSourcesJar>
<transformers> <transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <transformer
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<resource>META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports</resource> <transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>
META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports
</resource>
</transformer> </transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <transformer
<resource>META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports</resource> implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
</resource>
</transformer> </transformer>
</transformers> </transformers>
</configuration> </configuration>

@ -101,7 +101,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
private void initCustomPolarisConfigExtensionFiles(CompositePropertySource compositePropertySource) { private void initCustomPolarisConfigExtensionFiles(CompositePropertySource compositePropertySource) {
if (polarisConfigCustomExtensionLayer == null) { if (polarisConfigCustomExtensionLayer == null) {
LOGGER.debug("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps"); LOGGER.debug("[SCT Config] PolarisConfigCustomExtensionLayer is not init, ignore the following execution steps");
return; return;
} }
polarisConfigCustomExtensionLayer.initConfigFiles(environment, compositePropertySource, polarisPropertySourceManager, configFileService); polarisConfigCustomExtensionLayer.initConfigFiles(environment, compositePropertySource, polarisPropertySourceManager, configFileService);
@ -109,7 +109,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
private void afterLocatePolarisConfigExtension(CompositePropertySource compositePropertySource) { private void afterLocatePolarisConfigExtension(CompositePropertySource compositePropertySource) {
if (polarisConfigCustomExtensionLayer == null) { if (polarisConfigCustomExtensionLayer == null) {
LOGGER.debug("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps"); LOGGER.debug("[SCT Config] PolarisConfigCustomExtensionLayer is not init, ignore the following execution steps");
return; return;
} }
polarisConfigCustomExtensionLayer.executeAfterLocateConfigReturning(compositePropertySource); polarisConfigCustomExtensionLayer.executeAfterLocateConfigReturning(compositePropertySource);

@ -89,7 +89,7 @@ public abstract class PolarisConfigPropertyAutoRefresher implements ApplicationL
private void customInitRegisterPolarisConfig(PolarisConfigPropertyAutoRefresher polarisConfigPropertyAutoRefresher) { private void customInitRegisterPolarisConfig(PolarisConfigPropertyAutoRefresher polarisConfigPropertyAutoRefresher) {
if (polarisConfigCustomExtensionLayer == null) { if (polarisConfigCustomExtensionLayer == null) {
LOGGER.debug("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps"); LOGGER.debug("[SCT Config] PolarisConfigCustomExtensionLayer is not init, ignore the following execution steps");
return; return;
} }
polarisConfigCustomExtensionLayer.initRegisterConfig(polarisConfigPropertyAutoRefresher); polarisConfigCustomExtensionLayer.initRegisterConfig(polarisConfigPropertyAutoRefresher);
@ -139,7 +139,7 @@ public abstract class PolarisConfigPropertyAutoRefresher implements ApplicationL
private void customRegisterPolarisConfigPublishChangeListener(PolarisPropertySource polarisPropertySource) { private void customRegisterPolarisConfigPublishChangeListener(PolarisPropertySource polarisPropertySource) {
if (polarisConfigCustomExtensionLayer == null) { if (polarisConfigCustomExtensionLayer == null) {
LOGGER.debug("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps"); LOGGER.debug("[SCT Config] PolarisConfigCustomExtensionLayer is not init, ignore the following execution steps");
return; return;
} }
polarisConfigCustomExtensionLayer.executeRegisterPublishChangeListener(polarisPropertySource); polarisConfigCustomExtensionLayer.executeRegisterPublishChangeListener(polarisPropertySource);

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-starter-tencent-polaris-contract</artifactId>
<name>Spring Cloud Starter Tencent Polaris Contract</name>
<dependencies>
<!-- Spring Cloud Tencent dependencies start -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
</dependency>
<!-- Spring Cloud Tencent dependencies end -->
<!-- Spring cloud dependencies start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring cloud dependencies start -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,163 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.plugin.server.InterfaceDescriptor;
import com.tencent.polaris.api.plugin.server.ReportServiceContractRequest;
import com.tencent.polaris.api.plugin.server.ReportServiceContractResponse;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.api.AbstractOpenApiResource;
import org.springdoc.api.AbstractOpenApiResourceUtil;
import org.springdoc.webflux.api.OpenApiWebFluxUtil;
import org.springdoc.webmvc.api.OpenApiWebMvcUtil;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
/**
* Polaris contract reporter.
*
* @author Haotian Zhang
*/
public class PolarisContractReporter implements ApplicationListener<ApplicationReadyEvent> {
private final Logger LOG = LoggerFactory.getLogger(PolarisContractReporter.class);
private final org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource;
private final org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource;
private final String groupName;
private final ProviderAPI providerAPI;
private final PolarisDiscoveryProperties polarisDiscoveryProperties;
public PolarisContractReporter(org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource,
org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource,
String groupName, ProviderAPI providerAPI,
PolarisDiscoveryProperties polarisDiscoveryProperties) {
this.multipleOpenApiWebMvcResource = multipleOpenApiWebMvcResource;
this.multipleOpenApiWebFluxResource = multipleOpenApiWebFluxResource;
this.groupName = groupName;
this.providerAPI = providerAPI;
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
}
@Override
public void onApplicationEvent(@NonNull ApplicationReadyEvent applicationReadyEvent) {
try {
AbstractOpenApiResource openApiResource = null;
if (multipleOpenApiWebMvcResource != null) {
openApiResource = OpenApiWebMvcUtil.getOpenApiResourceOrThrow(multipleOpenApiWebMvcResource, groupName);
}
else if (multipleOpenApiWebFluxResource != null) {
openApiResource = OpenApiWebFluxUtil.getOpenApiResourceOrThrow(multipleOpenApiWebFluxResource, groupName);
}
OpenAPI openAPI = null;
if (openApiResource != null) {
openAPI = AbstractOpenApiResourceUtil.getOpenApi(openApiResource);
}
if (openAPI != null) {
ReportServiceContractRequest request = new ReportServiceContractRequest();
request.setName(polarisDiscoveryProperties.getService());
request.setNamespace(polarisDiscoveryProperties.getNamespace());
request.setService(polarisDiscoveryProperties.getService());
request.setProtocol("http");
request.setVersion(polarisDiscoveryProperties.getVersion());
List<InterfaceDescriptor> interfaceDescriptorList = getInterfaceDescriptorFromSwagger(openAPI);
request.setInterfaceDescriptors(interfaceDescriptorList);
ReportServiceContractResponse response = providerAPI.reportServiceContract(request);
LOG.info("Service contract [Namespace: {}. Name: {}. Service: {}. Protocol:{}. Version: {}. API counter: {}] is reported.",
request.getNamespace(), request.getName(), request.getService(), request.getProtocol(),
request.getVersion(), request.getInterfaceDescriptors().size());
if (LOG.isDebugEnabled()) {
String jsonValue = JacksonUtils.serialize2Json(openAPI);
LOG.debug("OpenApi json data: {}", jsonValue);
}
}
else {
LOG.warn("OpenAPI or json is null, group:{}", groupName);
}
}
catch (Throwable t) {
LOG.error("Report contract failed.", t);
}
}
private List<InterfaceDescriptor> getInterfaceDescriptorFromSwagger(OpenAPI openAPI) {
List<InterfaceDescriptor> interfaceDescriptorList = new ArrayList<>();
Paths paths = openAPI.getPaths();
for (Map.Entry<String, PathItem> p : paths.entrySet()) {
PathItem path = p.getValue();
Map<String, Operation> operationMap = getOperationMapFromPath(path);
if (CollectionUtils.isEmpty(operationMap)) {
continue;
}
for (Map.Entry<String, Operation> o : operationMap.entrySet()) {
InterfaceDescriptor interfaceDescriptor = new InterfaceDescriptor();
interfaceDescriptor.setPath(p.getKey());
interfaceDescriptor.setMethod(o.getKey());
interfaceDescriptor.setContent(JacksonUtils.serialize2Json(p.getValue()));
interfaceDescriptorList.add(interfaceDescriptor);
}
}
return interfaceDescriptorList;
}
private Map<String, Operation> getOperationMapFromPath(PathItem path) {
Map<String, Operation> operationMap = new HashMap<>();
if (path.getGet() != null) {
operationMap.put(PathItem.HttpMethod.GET.name(), path.getGet());
}
if (path.getPut() != null) {
operationMap.put(PathItem.HttpMethod.PUT.name(), path.getPut());
}
if (path.getPost() != null) {
operationMap.put(PathItem.HttpMethod.POST.name(), path.getPost());
}
if (path.getHead() != null) {
operationMap.put(PathItem.HttpMethod.HEAD.name(), path.getHead());
}
if (path.getDelete() != null) {
operationMap.put(PathItem.HttpMethod.DELETE.name(), path.getDelete());
}
if (path.getPatch() != null) {
operationMap.put(PathItem.HttpMethod.PATCH.name(), path.getPatch());
}
if (path.getOptions() != null) {
operationMap.put(PathItem.HttpMethod.OPTIONS.name(), path.getOptions());
}
return operationMap;
}
}

@ -0,0 +1,35 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
public class PolarisSwaggerApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent startingEvent) {
SpringApplication application = startingEvent.getSpringApplication();
Class<?> mainClass = application.getMainApplicationClass();
if (mainClass == null) {
return;
}
SwaggerContext.setAttribute(String.format("$%s", "MainClass"), mainClass);
}
}

@ -0,0 +1,36 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract;
import java.util.concurrent.ConcurrentHashMap;
public final class SwaggerContext {
private static final ConcurrentHashMap<String, Object> attribute = new ConcurrentHashMap<>();
private SwaggerContext() {
}
public static void setAttribute(String key, Object value) {
attribute.put(key, value);
}
public static Object getAttribute(String key) {
return attribute.get(key);
}
}

@ -0,0 +1,50 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.config;
/**
* Interface for contract properties.
*
* @author Haotian Zhang
*/
public interface ContractProperties {
boolean isEnabled();
void setEnabled(boolean enabled);
String getBasePackage();
void setBasePackage(String basePackage);
String getExcludePath();
void setExcludePath(String excludePath);
String getGroup();
void setGroup(String group);
String getBasePath();
void setBasePath(String basePath);
boolean isExposure();
void setExposure(boolean exposure);
}

@ -0,0 +1,26 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.config;
/**
* Extend contract properties.
*
* @author Haotian Zhang
*/
public interface ExtendedContractProperties extends ContractProperties {
}

@ -0,0 +1,52 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.config;
import java.util.List;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.factory.config.provider.RegisterConfigImpl;
/**
* Modifier of service contract.
*
* @author Haotian Zhang
*/
public class PolarisContractModifier implements PolarisConfigModifier {
private final PolarisContractProperties polarisContractProperties;
public PolarisContractModifier(PolarisContractProperties polarisContractProperties) {
this.polarisContractProperties = polarisContractProperties;
}
@Override
public void modify(ConfigurationImpl configuration) {
List<RegisterConfigImpl> registerConfigs = configuration.getProvider().getRegisters();
for (RegisterConfigImpl registerConfig : registerConfigs) {
registerConfig.setReportServiceContractEnable(polarisContractProperties.isEnabled());
}
}
@Override
public int getOrder() {
return OrderConstant.Modifier.SERVICE_CONTRACT_ORDER;
}
}

@ -0,0 +1,137 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.config;
import java.util.Objects;
import javax.annotation.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Properties for Polaris contract.
*
* @author Haotian Zhang
*/
@ConfigurationProperties("spring.cloud.polaris.contract")
public class PolarisContractProperties implements ContractProperties {
private final ExtendedContractProperties extendContractProperties;
private boolean enabled = true;
/**
* Packages to be scanned. Split by ",".
*/
private String basePackage;
/**
* Paths to be excluded. Split by ",".
*/
private String excludePath;
/**
* Group to create swagger docket.
*/
private String group = "default";
/**
* Base paths to be scanned. Split by ",".
*/
private String basePath = "/**";
private boolean exposure = true;
public PolarisContractProperties(@Nullable ExtendedContractProperties extendContractProperties) {
this.extendContractProperties = extendContractProperties;
}
@Override
public boolean isEnabled() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.isEnabled();
}
return enabled;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String getBasePackage() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getBasePackage();
}
return basePackage;
}
@Override
public void setBasePackage(String basePackage) {
this.basePackage = basePackage;
}
@Override
public String getExcludePath() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getExcludePath();
}
return excludePath;
}
@Override
public void setExcludePath(String excludePath) {
this.excludePath = excludePath;
}
@Override
public String getGroup() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getGroup();
}
return group;
}
@Override
public void setGroup(String group) {
this.group = group;
}
@Override
public String getBasePath() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getBasePath();
}
return basePath;
}
@Override
public void setBasePath(String basePath) {
this.basePath = basePath;
}
@Override
public boolean isExposure() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.isExposure();
}
return exposure;
}
@Override
public void setExposure(boolean exposure) {
this.exposure = exposure;
}
}

@ -0,0 +1,47 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.config;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
/**
* Auto configuration for Polaris contract properties.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisEnabled
public class PolarisContractPropertiesAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public PolarisContractProperties polarisContractProperties(@Nullable ExtendedContractProperties extendedContractProperties) {
return new PolarisContractProperties(extendedContractProperties);
}
@Bean
@ConditionalOnMissingBean
public PolarisContractModifier polarisContractModifier(PolarisContractProperties polarisContractProperties) {
return new PolarisContractModifier(polarisContractProperties);
}
}

@ -0,0 +1,34 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Bootstrap configuration for Polaris contract properties.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty("spring.cloud.polaris.enabled")
@Import(PolarisContractPropertiesAutoConfiguration.class)
public class PolarisContractPropertiesBootstrapConfiguration {
}

@ -0,0 +1,136 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.config;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.contract.PolarisContractReporter;
import com.tencent.cloud.polaris.contract.PolarisSwaggerApplicationListener;
import com.tencent.cloud.polaris.contract.filter.ApiDocServletFilter;
import com.tencent.cloud.polaris.contract.filter.ApiDocWebFluxFilter;
import com.tencent.cloud.polaris.contract.utils.PackageUtil;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.configuration.SpringDocConfiguration;
import org.springdoc.core.models.GroupedOpenApi;
import org.springdoc.webflux.api.MultipleOpenApiWebFluxResource;
import org.springdoc.webmvc.api.MultipleOpenApiWebMvcResource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import static com.tencent.cloud.polaris.contract.utils.PackageUtil.SPLITTER;
/**
* Auto configuration for Polaris swagger.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisEnabled
@ConditionalOnProperty(name = "spring.cloud.polaris.contract.enabled", havingValue = "true", matchIfMissing = true)
@Import(SpringDocConfiguration.class)
public class PolarisSwaggerAutoConfiguration {
static {
// After springboot2.6.x, the default path matching strategy of spring MVC is changed from ANT_PATH_MATCHER
// mode to PATH_PATTERN_PARSER mode, causing an error. The solution is to switch to the original ANT_PATH_MATCHER mode.
System.setProperty("spring.mvc.pathmatch.matching-strategy", "ant-path-matcher");
}
@Bean
public GroupedOpenApi polarisGroupedOpenApi(PolarisContractProperties polarisContractProperties) {
String basePackage = PackageUtil.scanPackage(polarisContractProperties.getBasePackage());
String[] basePaths = {};
if (StringUtils.hasText(polarisContractProperties.getBasePath())) {
basePaths = polarisContractProperties.getBasePath().split(SPLITTER);
}
String[] excludePaths = {};
if (StringUtils.hasText(polarisContractProperties.getExcludePath())) {
excludePaths = polarisContractProperties.getExcludePath().split(SPLITTER);
}
return GroupedOpenApi.builder()
.packagesToScan(basePackage)
.pathsToMatch(basePaths)
.pathsToExclude(excludePaths)
.group(polarisContractProperties.getGroup())
.build();
}
@Bean
public OpenAPI polarisOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Polaris Swagger API")
.description("This is to show polaris api description.")
.license(new License().name("BSD-3-Clause").url("https://opensource.org/licenses/BSD-3-Clause"))
.version("1.0.0"));
}
@Bean
@ConditionalOnBean(OpenAPI.class)
@ConditionalOnMissingBean
public PolarisContractReporter polarisContractReporter(
@Nullable MultipleOpenApiWebMvcResource multipleOpenApiWebMvcResource,
@Nullable MultipleOpenApiWebFluxResource multipleOpenApiWebFluxResource,
PolarisContractProperties polarisContractProperties, PolarisSDKContextManager polarisSDKContextManager,
PolarisDiscoveryProperties polarisDiscoveryProperties) {
return new PolarisContractReporter(multipleOpenApiWebMvcResource, multipleOpenApiWebFluxResource,
polarisContractProperties.getGroup(), polarisSDKContextManager.getProviderAPI(), polarisDiscoveryProperties);
}
@Bean
@ConditionalOnMissingBean
public PolarisSwaggerApplicationListener polarisSwaggerApplicationListener() {
return new PolarisSwaggerApplicationListener();
}
/**
* Create when web application type is SERVLET.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
protected static class SwaggerServletConfig {
@Bean
public ApiDocServletFilter apiDocServletFilter(PolarisContractProperties polarisContractProperties) {
return new ApiDocServletFilter(polarisContractProperties);
}
}
/**
* Create when web application type is REACTIVE.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
protected static class SwaggerReactiveConfig {
@Bean
public ApiDocWebFluxFilter apiDocWebFluxFilter(PolarisContractProperties polarisContractProperties) {
return new ApiDocWebFluxFilter(polarisContractProperties);
}
}
}

@ -0,0 +1,72 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.filter;
import java.io.IOException;
import com.tencent.cloud.polaris.contract.config.PolarisContractProperties;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.lang.NonNull;
import org.springframework.web.filter.OncePerRequestFilter;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_RESOURCE_PREFIX;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_UI_V2_URL;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_UI_V3_URL;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_V2_API_DOC_URL;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_V3_API_DOC_URL;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_WEBJARS_V2_PREFIX;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_WEBJARS_V3_PREFIX;
/**
* Filter to disable api doc controller.
*
* @author Haotian Zhang
*/
public class ApiDocServletFilter extends OncePerRequestFilter {
private final PolarisContractProperties polarisContractProperties;
public ApiDocServletFilter(PolarisContractProperties polarisContractProperties) {
this.polarisContractProperties = polarisContractProperties;
}
@Override
public void doFilterInternal(@NonNull HttpServletRequest httpServletRequest,
@NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain)
throws ServletException, IOException {
if (!polarisContractProperties.isExposure()) {
String path = httpServletRequest.getServletPath();
if (path.startsWith(SWAGGER_V2_API_DOC_URL) ||
path.startsWith(SWAGGER_V3_API_DOC_URL) ||
path.startsWith(SWAGGER_UI_V2_URL) ||
path.startsWith(SWAGGER_UI_V3_URL) ||
path.startsWith(SWAGGER_RESOURCE_PREFIX) ||
path.startsWith(SWAGGER_WEBJARS_V2_PREFIX) ||
path.startsWith(SWAGGER_WEBJARS_V3_PREFIX)) {
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
}
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}

@ -0,0 +1,72 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.filter;
import com.tencent.cloud.polaris.contract.config.PolarisContractProperties;
import reactor.core.publisher.Mono;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.NonNull;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_RESOURCE_PREFIX;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_UI_V2_URL;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_UI_V3_URL;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_V2_API_DOC_URL;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_V3_API_DOC_URL;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_WEBJARS_V2_PREFIX;
import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_WEBJARS_V3_PREFIX;
/**
* Filter to disable api doc controller.
*
* @author Haotian Zhang
*/
public class ApiDocWebFluxFilter implements WebFilter {
private final PolarisContractProperties polarisContractProperties;
public ApiDocWebFluxFilter(PolarisContractProperties polarisContractProperties) {
this.polarisContractProperties = polarisContractProperties;
}
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, @NonNull WebFilterChain webFilterChain) {
if (!polarisContractProperties.isExposure()) {
String path = serverWebExchange.getRequest().getURI().getPath();
if (path.startsWith(SWAGGER_V2_API_DOC_URL) ||
path.startsWith(SWAGGER_V3_API_DOC_URL) ||
path.startsWith(SWAGGER_UI_V2_URL) ||
path.startsWith(SWAGGER_UI_V3_URL) ||
path.startsWith(SWAGGER_RESOURCE_PREFIX) ||
path.startsWith(SWAGGER_WEBJARS_V2_PREFIX) ||
path.startsWith(SWAGGER_WEBJARS_V3_PREFIX)) {
ServerHttpResponse response = serverWebExchange.getResponse();
response.setRawStatusCode(HttpStatus.FORBIDDEN.value());
DataBuffer dataBuffer = response.bufferFactory().allocateBuffer();
return response.writeWith(Mono.just(dataBuffer));
}
}
return webFilterChain.filter(serverWebExchange);
}
}

@ -0,0 +1,64 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.filter;
/**
* Constant for filter.
*
* @author Haotian Zhang
*/
public final class FilterConstant {
/**
* Swagger api doc V2 url.
*/
public static final String SWAGGER_V2_API_DOC_URL = "/v2/api-docs";
/**
* Swagger api doc V3 url.
*/
public static final String SWAGGER_V3_API_DOC_URL = "/v3/api-docs";
/**
* Swagger UI V2 url.
*/
public static final String SWAGGER_UI_V2_URL = "/swagger-ui.html";
/**
* Swagger UI V3 url.
*/
public static final String SWAGGER_UI_V3_URL = "/swagger-ui/index.html";
/**
* Swagger resource url prefix.
*/
public static final String SWAGGER_RESOURCE_PREFIX = "/swagger-resource/";
/**
* Swagger webjars V2 url prefix.
*/
public static final String SWAGGER_WEBJARS_V2_PREFIX = "/webjars/springfox-swagger-ui/";
/**
* Swagger webjars V3 url prefix.
*/
public static final String SWAGGER_WEBJARS_V3_PREFIX = "/webjars/swagger-ui/";
private FilterConstant() {
}
}

@ -0,0 +1,132 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.contract.utils;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import com.tencent.cloud.polaris.contract.SwaggerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.util.StringUtils;
/**
* Util for package processing.
*
* @author Haotian Zhang
*/
public final class PackageUtil {
/**
* splitter for property.
*/
public static final String SPLITTER = ",";
private static final Logger LOG = LoggerFactory.getLogger(PackageUtil.class);
private PackageUtil() {
}
public static String scanPackage(String configBasePackage) {
String validScanPackage;
// Externally configured scan package
Set<String> configPackageSet = new HashSet<>();
if (!StringUtils.isEmpty(configBasePackage)) {
configPackageSet.addAll(Arrays.asList(configBasePackage.split(SPLITTER)));
}
Object mainClz = SwaggerContext.getAttribute(String.format("$%s", "MainClass"));
// Verification of the valid path of MainClass
if (mainClz != null) {
Set<String> autoDetectPackageSet = parseDefaultScanPackage((Class<?>) mainClz);
if (LOG.isInfoEnabled() && !autoDetectPackageSet.isEmpty()) {
LOG.info("Auto detect default swagger scan packages: {}",
String.join(SPLITTER, autoDetectPackageSet).trim());
}
Set<String> validScanPackageSet = merge(configPackageSet, autoDetectPackageSet);
validScanPackage = String.join(SPLITTER, validScanPackageSet).trim();
if (LOG.isInfoEnabled() && !StringUtils.isEmpty(validScanPackage)) {
LOG.info("Swagger scan valid packages: {}", validScanPackage);
}
}
else {
// If there is no MainClass, the configured path is used for scanning
validScanPackage = String.join(SPLITTER, configPackageSet);
if (LOG.isWarnEnabled()) {
LOG.warn("Cannot detect main class, swagger scanning packages is set to: {}",
validScanPackage);
}
}
return validScanPackage;
}
public static Set<String> merge(Set<String> configPackageSet, Set<String> autoDetectPackageSet) {
if (configPackageSet == null || configPackageSet.size() == 0) {
return autoDetectPackageSet;
}
return configPackageSet;
}
public static Set<String> parseDefaultScanPackage(Class<?> mainClass) {
Set<String> packageSets = new HashSet<>();
String defaultPackage = mainClass.getPackage().getName();
try {
boolean springBootEnv = true;
try {
Class.forName("org.springframework.boot.autoconfigure.SpringBootApplication");
}
catch (Throwable t) {
LOG.info("Can not load annotation @SpringBootApplication, " +
"current environment is not in spring boot framework. ");
springBootEnv = false;
}
if (!springBootEnv) {
packageSets.add(defaultPackage);
return packageSets;
}
SpringBootApplication bootAnnotation = mainClass.getAnnotation(SpringBootApplication.class);
Class<?>[] baseClassPackages;
String[] basePackages;
if (bootAnnotation == null) {
packageSets.add(defaultPackage);
}
else {
// baseClassPackages annotation
baseClassPackages = bootAnnotation.scanBasePackageClasses();
for (Class<?> clz : baseClassPackages) {
packageSets.add(clz.getPackage().getName());
}
// basePackage annotation
basePackages = bootAnnotation.scanBasePackages();
packageSets.addAll(Arrays.asList(basePackages));
// When basePackage and baseClassPackages are both empty, the package path where the MainClass class is located is used by default.
if (packageSets.isEmpty()) {
packageSets.add(defaultPackage);
}
}
}
catch (Throwable t) {
LOG.warn("Swagger scan package is empty and auto detect main class occur exception: {}",
t.getMessage());
}
return packageSets;
}
}

@ -0,0 +1,37 @@
/*
* 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 org.springdoc.api;
import java.util.Locale;
import io.swagger.v3.oas.models.OpenAPI;
/**
* Util for {@link AbstractOpenApiResource}.
*
* @author Haotian Zhang
*/
public final class AbstractOpenApiResourceUtil {
private AbstractOpenApiResourceUtil() {
}
public static OpenAPI getOpenApi(AbstractOpenApiResource openApiResource) {
return openApiResource.getOpenApi(Locale.getDefault());
}
}

@ -0,0 +1,36 @@
/*
* 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 org.springdoc.webflux.api;
import org.springdoc.api.AbstractOpenApiResource;
/**
* Util for {@link MultipleOpenApiResource}.
*
* @author Haotian Zhang
*/
public final class OpenApiWebFluxUtil {
private OpenApiWebFluxUtil() {
}
public static AbstractOpenApiResource getOpenApiResourceOrThrow(
org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource, String groupName) {
return multipleOpenApiWebFluxResource.getOpenApiResourceOrThrow(groupName);
}
}

@ -0,0 +1,35 @@
/*
* 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 org.springdoc.webmvc.api;
import org.springdoc.api.AbstractOpenApiResource;
/**
* Util for {@link MultipleOpenApiResource}.
*
* @author Haotian Zhang
*/
public final class OpenApiWebMvcUtil {
private OpenApiWebMvcUtil() {
}
public static AbstractOpenApiResource getOpenApiResourceOrThrow(
org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource, String groupName) {
return multipleOpenApiWebMvcResource.getOpenApiResourceOrThrow(groupName);
}
}

@ -0,0 +1,40 @@
{
"properties": [
{
"name": "spring.cloud.polaris.contract.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "Enable polaris record contract or not."
},
{
"name": "spring.cloud.polaris.contract.basePackage",
"type": "java.lang.String",
"defaultValue": "",
"description": "Packages to be scanned. Split by \",\"."
},
{
"name": "spring.cloud.polaris.contract.excludePath",
"type": "java.lang.String",
"defaultValue": "",
"description": "Paths to be excluded. Split by \",\"."
},
{
"name": "spring.cloud.polaris.contract.group",
"type": "java.lang.String",
"defaultValue": "default",
"description": "Group to create swagger docket."
},
{
"name": "spring.cloud.polaris.contract.basePath",
"type": "java.lang.String",
"defaultValue": "/**",
"description": "Base paths to be scanned. Split by \",\"."
},
{
"name": "spring.cloud.polaris.contract.exposure",
"type": "java.lang.Boolean",
"defaultValue": "true",
"description": "Enable polaris contract exposure or not."
}
]
}

@ -0,0 +1,4 @@
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.contract.config.PolarisContractPropertiesAutoConfiguration
org.springframework.context.ApplicationListener=\
com.tencent.cloud.polaris.contract.PolarisSwaggerApplicationListener

@ -0,0 +1,2 @@
com.tencent.cloud.polaris.contract.config.PolarisSwaggerAutoConfiguration
com.tencent.cloud.polaris.contract.config.PolarisContractProperties

@ -64,7 +64,7 @@ public class PolarisDiscoveryProperties {
/** /**
* Version number. * Version number.
*/ */
private String version; private String version = "1.0.0";
/** /**
* Protocol name such as http, https. * Protocol name such as http, https.

@ -171,5 +171,10 @@ public class OrderConstant {
* Order of stat reporter configuration modifier. * Order of stat reporter configuration modifier.
*/ */
public static Integer STAT_REPORTER_ORDER = 1; public static Integer STAT_REPORTER_ORDER = 1;
/**
* Order of service contract configuration modifier.
*/
public static Integer SERVICE_CONTRACT_ORDER = Integer.MAX_VALUE - 9;
} }
} }

@ -64,10 +64,14 @@
<artifactId>spring-cloud-starter-tencent-polaris-config</artifactId> <artifactId>spring-cloud-starter-tencent-polaris-config</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-contract</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-discovery-adapter-plugin</artifactId> <artifactId>spring-cloud-starter-tencent-discovery-adapter-plugin</artifactId>
<version>${revision}</version>
</dependency> </dependency>
<dependency> <dependency>

@ -75,6 +75,7 @@
<!-- Dependencies --> <!-- Dependencies -->
<polaris.version>1.15.0-SNAPSHOT</polaris.version> <polaris.version>1.15.0-SNAPSHOT</polaris.version>
<guava.version>32.0.1-jre</guava.version> <guava.version>32.0.1-jre</guava.version>
<springdoc.version>2.2.0</springdoc.version>
<mocktio.version>4.9.0</mocktio.version> <mocktio.version>4.9.0</mocktio.version>
<byte-buddy.version>1.12.19</byte-buddy.version> <byte-buddy.version>1.12.19</byte-buddy.version>
<protobuf-java.version>3.21.7</protobuf-java.version> <protobuf-java.version>3.21.7</protobuf-java.version>
@ -151,6 +152,12 @@
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-contract</artifactId>
<version>${revision}</version>
</dependency>
<dependency> <dependency>
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-all</artifactId> <artifactId>spring-cloud-starter-tencent-all</artifactId>
@ -197,6 +204,18 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId> <artifactId>protobuf-java</artifactId>

@ -19,10 +19,10 @@
<artifactId>spring-boot-starter-webflux</artifactId> <artifactId>spring-boot-starter-webflux</artifactId>
</dependency> </dependency>
<!-- <dependency>--> <dependency>
<!-- <groupId>org.springframework.boot</groupId>--> <groupId>com.tencent.cloud</groupId>
<!-- <artifactId>spring-boot-starter-web</artifactId>--> <artifactId>spring-cloud-starter-tencent-polaris-contract</artifactId>
<!-- </dependency>--> </dependency>
<dependency> <dependency>
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>

@ -11,6 +11,8 @@ spring:
discovery: discovery:
enabled: true enabled: true
register: true register: true
contract:
exposure: true
stat: stat:
enabled: true enabled: true
port: 28082 port: 28082

@ -24,6 +24,11 @@
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId> <artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-contract</artifactId>
</dependency>
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>com.tencent.polaris</groupId>--> <!-- <groupId>com.tencent.polaris</groupId>-->
<!-- <artifactId>connector-consul</artifactId>--> <!-- <artifactId>connector-consul</artifactId>-->

@ -45,7 +45,7 @@ public class DiscoveryCallerController {
* @param value2 value 2 * @param value2 value 2
* @return sum * @return sum
*/ */
@GetMapping("/feign") @RequestMapping("/feign")
public int feign(@RequestParam int value1, @RequestParam int value2) { public int feign(@RequestParam int value1, @RequestParam int value2) {
return discoveryCalleeService.sum(value1, value2); return discoveryCalleeService.sum(value1, value2);
} }

@ -22,6 +22,8 @@ spring:
heartbeat: heartbeat:
enabled: true enabled: true
health-check-url: /discovery/service/caller/healthCheck health-check-url: /discovery/service/caller/healthCheck
contract:
exposure: true
stat: stat:
enabled: true enabled: true
port: 28081 port: 28081

@ -30,12 +30,6 @@ import com.tencent.cloud.rpc.enhancement.filter.EnhancedServletFilter;
import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter; import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor; import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor;
@ -115,36 +109,6 @@ public class RpcEnhancementAutoConfiguration {
return new ExceptionPolarisReporter(properties, polarisSDKContextManager.getConsumerAPI()); return new ExceptionPolarisReporter(properties, polarisSDKContextManager.getConsumerAPI());
} }
@Bean
public AssemblyClientExceptionHook assemblyClientExceptionHook(PolarisSDKContextManager polarisSDKContextManager, InstanceTransformer instanceTransformer) {
return new AssemblyClientExceptionHook(polarisSDKContextManager.getAssemblyAPI(), instanceTransformer);
}
@Bean
public AssemblyClientPostHook assemblyClientPostHook(PolarisSDKContextManager polarisSDKContextManager, InstanceTransformer instanceTransformer) {
return new AssemblyClientPostHook(polarisSDKContextManager.getAssemblyAPI(), instanceTransformer);
}
@Bean
public AssemblyClientPreHook assemblyClientPreHook(PolarisSDKContextManager polarisSDKContextManager) {
return new AssemblyClientPreHook(polarisSDKContextManager.getAssemblyAPI());
}
@Bean
public AssemblyServerExceptionHook assemblyServerExceptionHook(PolarisSDKContextManager polarisSDKContextManager) {
return new AssemblyServerExceptionHook(polarisSDKContextManager.getAssemblyAPI());
}
@Bean
public AssemblyServerPostHook assemblyServerPostHook(PolarisSDKContextManager polarisSDKContextManager) {
return new AssemblyServerPostHook(polarisSDKContextManager.getAssemblyAPI());
}
@Bean
public AssemblyServerPreHook assemblyServerPreHook(PolarisSDKContextManager polarisSDKContextManager) {
return new AssemblyServerPreHook(polarisSDKContextManager.getAssemblyAPI());
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
protected static class RpcEnhancementServletFilterConfig { protected static class RpcEnhancementServletFilterConfig {

@ -44,27 +44,5 @@ public class PluginOrderConstant {
* {@link com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter}. * {@link com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter}.
*/ */
public static final int CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 2; public static final int CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 2;
/**
* order for
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook}.
*/
public static final int ASSEMBLY_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 3;
}
public static class ServerPluginOrder {
/**
* order for
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook}.
*/
public static final int ASSEMBLY_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 1;
} }
} }

@ -1,56 +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.rpc.enhancement.plugin.assembly;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.MetadataProvider;
import org.springframework.cloud.client.ServiceInstance;
/**
* AssemblyMetadataProvider.
*
* @author sean yu
*/
public class AssemblyMetadataProvider implements MetadataProvider {
private final ServiceInstance serviceInstance;
private final String namespace;
public AssemblyMetadataProvider(ServiceInstance localServiceInstance, String namespace) {
this.serviceInstance = localServiceInstance;
this.namespace = namespace;
}
@Override
public String getMetadata(String key) {
return serviceInstance.getMetadata().get(key);
}
@Override
public ServiceKey getLocalService() {
return new ServiceKey(namespace, serviceInstance.getServiceId());
}
@Override
public String getLocalIp() {
return serviceInstance.getHost();
}
}

@ -1,125 +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.rpc.enhancement.plugin.assembly;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.google.common.net.HttpHeaders;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.RequestContext;
import org.springframework.http.HttpMethod;
/**
* AssemblyRequestContext.
*
* @author sean yu
*/
public class AssemblyRequestContext implements RequestContext {
private final EnhancedRequestContext requestContext;
private final ServiceKey callerService;
private final String callerIp;
private final Map<String, String> cookies;
public AssemblyRequestContext(EnhancedRequestContext requestContext, ServiceKey callerService, String callerIp) {
this.requestContext = requestContext;
this.callerService = callerService;
this.callerIp = callerIp;
this.cookies = new HashMap<>();
List<String> allCookies =
Optional.ofNullable(requestContext.getHttpHeaders().get(HttpHeaders.COOKIE))
.orElse(new ArrayList<>())
.stream()
.flatMap(it -> Arrays.stream(it.split(";")))
.toList();
allCookies.forEach(cookie -> {
String[] cookieKV = cookie.split("=");
if (cookieKV.length == 2) {
cookies.put(cookieKV[0], cookieKV[1]);
}
});
}
@Override
public String getMethod() {
return requestContext.getHttpMethod().name();
}
@Override
public void setMethod(String method) {
requestContext.setHttpMethod(HttpMethod.valueOf(method));
}
@Override
public String getHeader(String key) {
return requestContext.getHttpHeaders().getFirst(key);
}
@Override
public void setHeader(String key, String value) {
requestContext.getHttpHeaders().set(key, value);
}
@Override
public Collection<String> listHeaderKeys() {
return requestContext.getHttpHeaders().keySet();
}
@Override
public String getCookie(String key) {
return this.cookies.get(key);
}
@Override
public void setCookie(String key, String value) {
this.cookies.put(key, value);
}
@Override
public Collection<String> listCookieKeys() {
return this.cookies.keySet();
}
@Override
public String getCallerIp() {
return callerIp;
}
@Override
public ServiceKey getCallerService() {
return callerService;
}
@Override
public URI getURI() {
return requestContext.getUrl();
}
}

@ -1,87 +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.rpc.enhancement.plugin.assembly;
import java.util.Collection;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.rpc.ResponseContext;
import org.springframework.lang.Nullable;
/**
* AssemblyResponseContext.
*
* @author sean yu
*/
public class AssemblyResponseContext implements ResponseContext {
private final EnhancedResponseContext responseContext;
private final Throwable throwable;
private final RetStatus retStatus;
public AssemblyResponseContext(@Nullable EnhancedResponseContext responseContext, @Nullable Throwable throwable) {
this.responseContext = responseContext;
this.throwable = throwable;
if (responseContext == null) {
this.retStatus = PolarisEnhancedPluginUtils.getRetStatusFromRequest(null, null, throwable);
}
else {
this.retStatus = PolarisEnhancedPluginUtils.getRetStatusFromRequest(responseContext.getHttpHeaders(), responseContext.getHttpStatus(), throwable);
}
}
@Override
public Object getRetCode() {
if (responseContext == null) {
return null;
}
return this.responseContext.getHttpStatus();
}
@Override
public String getHeader(String key) {
if (responseContext == null) {
return null;
}
return this.responseContext.getHttpHeaders().getFirst(key);
}
@Override
public Collection<String> listHeaders() {
if (responseContext == null) {
return null;
}
return this.responseContext.getHttpHeaders().keySet();
}
@Override
public Throwable getThrowable() {
return this.throwable;
}
@Override
public RetStatus getRetStatus() {
return this.retStatus;
}
}

@ -1,82 +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.rpc.enhancement.plugin.assembly.client;
import com.tencent.cloud.common.metadata.MetadataContext;
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.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.AfterRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyClientExceptionHook.
*
* @author sean yu
*/
public class AssemblyClientExceptionHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
private final InstanceTransformer instanceTransformer;
public AssemblyClientExceptionHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) {
this.assemblyAPI = assemblyAPI;
this.instanceTransformer = instanceTransformer;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Client.EXCEPTION;
}
@Override
public void run(EnhancedPluginContext context) {
AfterRequest afterRequest = new AfterRequest();
afterRequest.setCapabilities(new Capability[]{Capability.ALL});
afterRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
afterRequest.setResponseContext(new AssemblyResponseContext(null, context.getThrowable()));
afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
afterRequest.setDelay(context.getDelay());
afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders()));
// TargetService and TargetInstance only exist in client side
afterRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId()));
afterRequest.setTargetInstance(instanceTransformer.transform(context.getTargetServiceInstance()));
assemblyAPI.afterCallService(afterRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -1,83 +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.rpc.enhancement.plugin.assembly.client;
import com.tencent.cloud.common.metadata.MetadataContext;
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.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.AfterRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyClientPostHook.
*
* @author sean yu
*/
public class AssemblyClientPostHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
private final InstanceTransformer instanceTransformer;
public AssemblyClientPostHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) {
this.assemblyAPI = assemblyAPI;
this.instanceTransformer = instanceTransformer;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Client.POST;
}
@Override
public void run(EnhancedPluginContext context) {
AfterRequest afterRequest = new AfterRequest();
afterRequest.setCapabilities(new Capability[]{Capability.ALL});
afterRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
afterRequest.setResponseContext(new AssemblyResponseContext(context.getResponse(), null));
afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
afterRequest.setDelay(context.getDelay());
afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders()));
// TargetService and TargetInstance only exist in client side
afterRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId()));
afterRequest.setTargetInstance(instanceTransformer.transform(context.getTargetServiceInstance()));
assemblyAPI.afterCallService(afterRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -1,73 +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.rpc.enhancement.plugin.assembly.client;
import com.tencent.cloud.common.metadata.MetadataContext;
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.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.BeforeRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyClientPreHook.
*
* @author sean yu
*/
public class AssemblyClientPreHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
public AssemblyClientPreHook(AssemblyAPI assemblyAPI) {
this.assemblyAPI = assemblyAPI;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Client.PRE;
}
@Override
public void run(EnhancedPluginContext context) {
BeforeRequest beforeRequest = new BeforeRequest();
beforeRequest.setCapabilities(new Capability[]{Capability.ALL});
beforeRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
beforeRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
// TargetService only exist in client side
beforeRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId()));
assemblyAPI.beforeCallService(beforeRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -1,76 +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.rpc.enhancement.plugin.assembly.server;
import com.tencent.cloud.common.metadata.MetadataContext;
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.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.AfterRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyServerExceptionHook.
*
* @author sean yu
*/
public class AssemblyServerExceptionHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
public AssemblyServerExceptionHook(AssemblyAPI assemblyAPI) {
this.assemblyAPI = assemblyAPI;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Server.EXCEPTION;
}
@Override
public void run(EnhancedPluginContext context) {
AfterRequest afterRequest = new AfterRequest();
afterRequest.setCapabilities(new Capability[]{Capability.ALL});
afterRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
afterRequest.setResponseContext(new AssemblyResponseContext(null, context.getThrowable()));
afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
afterRequest.setDelay(context.getDelay());
afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders()));
assemblyAPI.afterProcess(afterRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -1,75 +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.rpc.enhancement.plugin.assembly.server;
import com.tencent.cloud.common.metadata.MetadataContext;
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.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.AfterRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyServerPostHook.
*
* @author sean yu
*/
public class AssemblyServerPostHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
public AssemblyServerPostHook(AssemblyAPI assemblyAPI) {
this.assemblyAPI = assemblyAPI;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Server.POST;
}
@Override
public void run(EnhancedPluginContext context) {
AfterRequest afterRequest = new AfterRequest();
afterRequest.setCapabilities(new Capability[]{Capability.ALL});
afterRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
afterRequest.setResponseContext(new AssemblyResponseContext(context.getResponse(), null));
afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
afterRequest.setDelay(context.getDelay());
afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders()));
assemblyAPI.afterProcess(afterRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -1,70 +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.rpc.enhancement.plugin.assembly.server;
import com.tencent.cloud.common.metadata.MetadataContext;
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.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.BeforeRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyServerPreHook.
*
* @author sean yu
*/
public class AssemblyServerPreHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
public AssemblyServerPreHook(AssemblyAPI assemblyAPI) {
this.assemblyAPI = assemblyAPI;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Server.PRE;
}
@Override
public void run(EnhancedPluginContext context) {
BeforeRequest beforeRequest = new BeforeRequest();
beforeRequest.setCapabilities(new Capability[]{Capability.ALL});
beforeRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
beforeRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
assemblyAPI.beforeProcess(beforeRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -1,146 +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.rpc.enhancement.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.assembly.api.AssemblyAPI;
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.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyClientExceptionHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyClientExceptionHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyClientExceptionHook assemblyClientExceptionHook;
@Mock
private AssemblyAPI assemblyAPI;
@Mock
private InstanceTransformer instanceTransformer;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyClientExceptionHook.getName()).isEqualTo(AssemblyClientExceptionHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyClientExceptionHook.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance, null);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyClientExceptionHook.run(pluginContext);
assemblyClientExceptionHook.getOrder();
assemblyClientExceptionHook.getName();
assemblyClientExceptionHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyClientExceptionHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -1,146 +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.rpc.enhancement.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.assembly.api.AssemblyAPI;
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.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyClientPostHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyClientPostHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyClientPostHook assemblyClientPostHook;
@Mock
private AssemblyAPI assemblyAPI;
@Mock
private InstanceTransformer instanceTransformer;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyClientPostHook.getName()).isEqualTo(AssemblyClientPostHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyClientPostHook.getType()).isEqualTo(EnhancedPluginType.Client.POST);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance, null);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyClientPostHook.run(pluginContext);
assemblyClientPostHook.getOrder();
assemblyClientPostHook.getName();
assemblyClientPostHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyClientPostHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -1,143 +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.rpc.enhancement.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook;
import com.tencent.polaris.assembly.api.AssemblyAPI;
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.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyClientPreHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyClientPreHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyClientPreHook assemblyClientPreHook;
@Mock
private AssemblyAPI assemblyAPI;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyClientPreHook.getName()).isEqualTo(AssemblyClientPreHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyClientPreHook.getType()).isEqualTo(EnhancedPluginType.Client.PRE);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance, null);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyClientPreHook.run(pluginContext);
assemblyClientPreHook.getOrder();
assemblyClientPreHook.getName();
assemblyClientPreHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyClientPreHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -1,57 +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.rpc.enhancement.plugin;
import java.util.HashMap;
import java.util.Map;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.polaris.api.pojo.ServiceKey;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.ServiceInstance;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
/**
* AssemblyMetadataProviderTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyMetadataProviderTest {
@Test
public void testAssemblyMetadataProvider() {
ServiceInstance serviceInstance = Mockito.mock(ServiceInstance.class);
Map<String, String> metadata = new HashMap<>() {{
put("k", "v");
}};
doReturn(metadata).when(serviceInstance).getMetadata();
doReturn("0.0.0.0").when(serviceInstance).getHost();
doReturn("test").when(serviceInstance).getServiceId();
AssemblyMetadataProvider assemblyMetadataProvider = new AssemblyMetadataProvider(serviceInstance, "test");
assertThat(assemblyMetadataProvider.getMetadata("k")).isEqualTo("v");
assertThat(assemblyMetadataProvider.getLocalIp()).isEqualTo("0.0.0.0");
assertThat(assemblyMetadataProvider.getLocalService()).isEqualTo(new ServiceKey("test", "test"));
}
}

@ -1,83 +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.rpc.enhancement.plugin;
import java.net.URI;
import java.util.Arrays;
import java.util.HashSet;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import static org.assertj.core.api.Assertions.assertThat;
/**
* AssemblyRequestContextTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyRequestContextTest {
@Test
public void testAssemblyRequestContext() {
URI uri = URI.create("http://0.0.0.0/");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("a", "a");
httpHeaders.add(HttpHeaders.COOKIE, "cookies-k1=cookies-v1;cookies-k2=cookies-v2");
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(uri)
.httpHeaders(httpHeaders)
.build();
ServiceKey callerService = new ServiceKey("test", "test");
AssemblyRequestContext assemblyRequestContext = new AssemblyRequestContext(
enhancedRequestContext,
callerService,
"0.0.0.0"
);
assertThat(assemblyRequestContext.getURI()).isEqualTo(uri);
assertThat(assemblyRequestContext.getHeader("a")).isEqualTo("a");
assemblyRequestContext.setHeader("b", "b");
assertThat(assemblyRequestContext.listHeaderKeys()).isEqualTo(new HashSet<>(Arrays.asList(HttpHeaders.COOKIE, "a", "b")));
assertThat(assemblyRequestContext.getMethod()).isEqualTo(HttpMethod.GET.toString());
assemblyRequestContext.setMethod(HttpMethod.OPTIONS.name());
assertThat(assemblyRequestContext.getMethod()).isEqualTo(HttpMethod.OPTIONS.toString());
assertThat(assemblyRequestContext.getCookie("cookies-k1")).isEqualTo("cookies-v1");
assertThat(assemblyRequestContext.getCookie("cookies-k2")).isEqualTo("cookies-v2");
assemblyRequestContext.setCookie("cookies-k3", "cookies-v3");
assertThat(assemblyRequestContext.listCookieKeys()).isEqualTo(new HashSet<>(Arrays.asList("cookies-k1", "cookies-k2", "cookies-k3")));
assertThat(assemblyRequestContext.getCallerService()).isEqualTo(callerService);
assertThat(assemblyRequestContext.getCallerIp()).isEqualTo("0.0.0.0");
}
}

@ -1,101 +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.rpc.enhancement.plugin;
import java.net.SocketTimeoutException;
import java.util.HashSet;
import java.util.List;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.polaris.api.pojo.RetStatus;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyResponseContextTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyResponseContextTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@Test
public void testAssemblyResponseContext() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("a", "a");
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpHeaders(httpHeaders)
.httpStatus(HttpStatus.OK.value())
.build();
AssemblyResponseContext assemblyResponseContext = new AssemblyResponseContext(enhancedResponseContext, null);
assertThat(assemblyResponseContext.getHeader("a")).isEqualTo("a");
assertThat(assemblyResponseContext.getRetCode()).isEqualTo(HttpStatus.OK.value());
assertThat(assemblyResponseContext.getThrowable()).isEqualTo(null);
assertThat(assemblyResponseContext.getRetStatus()).isEqualTo(RetStatus.RetSuccess);
assertThat(assemblyResponseContext.listHeaders()).isEqualTo(new HashSet<>(List.of("a")));
Throwable e = new SocketTimeoutException();
assemblyResponseContext = new AssemblyResponseContext(null, e);
assertThat(assemblyResponseContext.getHeader("a")).isEqualTo(null);
assertThat(assemblyResponseContext.getRetCode()).isEqualTo(null);
assertThat(assemblyResponseContext.getThrowable()).isEqualTo(e);
assertThat(assemblyResponseContext.getRetStatus()).isEqualTo(RetStatus.RetTimeout);
assertThat(assemblyResponseContext.listHeaders()).isEqualTo(null);
}
}

@ -1,143 +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.rpc.enhancement.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook;
import com.tencent.polaris.assembly.api.AssemblyAPI;
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.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyServerExceptionHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyServerExceptionHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyServerExceptionHook assemblyServerExceptionHook;
@Mock
private AssemblyAPI assemblyAPI;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyServerExceptionHook.getName()).isEqualTo(AssemblyServerExceptionHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyServerExceptionHook.getType()).isEqualTo(EnhancedPluginType.Server.EXCEPTION);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance, null);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyServerExceptionHook.run(pluginContext);
assemblyServerExceptionHook.getOrder();
assemblyServerExceptionHook.getName();
assemblyServerExceptionHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyServerExceptionHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -1,143 +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.rpc.enhancement.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook;
import com.tencent.polaris.assembly.api.AssemblyAPI;
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.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyServerPostHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyServerPostHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyServerPostHook assemblyServerPostHook;
@Mock
private AssemblyAPI assemblyAPI;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyServerPostHook.getName()).isEqualTo(AssemblyServerPostHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyServerPostHook.getType()).isEqualTo(EnhancedPluginType.Server.POST);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance, null);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyServerPostHook.run(pluginContext);
assemblyServerPostHook.getOrder();
assemblyServerPostHook.getName();
assemblyServerPostHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyServerPostHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -1,143 +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.rpc.enhancement.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook;
import com.tencent.polaris.assembly.api.AssemblyAPI;
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.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyServerPreHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyServerPreHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyServerPreHook assemblyServerPreHook;
@Mock
private AssemblyAPI assemblyAPI;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyServerPreHook.getName()).isEqualTo(AssemblyServerPreHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyServerPreHook.getType()).isEqualTo(EnhancedPluginType.Server.PRE);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance, null);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyServerPreHook.run(pluginContext);
assemblyServerPreHook.getOrder();
assemblyServerPreHook.getName();
assemblyServerPreHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyServerPreHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}
Loading…
Cancel
Save