Skip to content

Commit

Permalink
fix:fix swagger not working bug.
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyeBeFreeman committed Jan 19, 2024
1 parent dd56d3c commit a641589
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 492 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
- [feat: support nacos namespace mapping](https://github.com/Tencent/spring-cloud-tencent/pull/1192)
- [fix:fix rule-based router when using RestTemplate.](https://github.com/Tencent/spring-cloud-tencent/pull/1201)
- [fix:fix sct-all wrong spring boot version obtain.](https://github.com/Tencent/spring-cloud-tencent/pull/1205)
- [fix:fix swagger not working bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1125)
23 changes: 4 additions & 19 deletions spring-cloud-starter-tencent-polaris-contract/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,13 @@
<!-- Spring cloud dependencies start -->

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<exclusions>
<exclusion>
<artifactId>swagger-models</artifactId>
<groupId>io.swagger</groupId>
</exclusion>
<exclusion>
<artifactId>swagger-annotations</artifactId>
<groupId>io.swagger</groupId>
</exclusion>
</exclusions>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>

<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</dependency>

<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-ui</artifactId>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@
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.models.HttpMethod;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
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 springfox.documentation.service.Documentation;
import springfox.documentation.spring.web.DocumentationCache;
import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper;
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;
Expand All @@ -52,18 +53,21 @@
public class PolarisContractReporter implements ApplicationListener<ApplicationReadyEvent> {

private final Logger LOG = LoggerFactory.getLogger(PolarisContractReporter.class);
private final ServiceModelToSwagger2Mapper swagger2Mapper;
private final DocumentationCache documentationCache;

private final org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource;
private final org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource;
private final PolarisContractProperties polarisContractProperties;

private final ProviderAPI providerAPI;

private final PolarisDiscoveryProperties polarisDiscoveryProperties;

public PolarisContractReporter(DocumentationCache documentationCache, ServiceModelToSwagger2Mapper swagger2Mapper,
PolarisContractProperties polarisContractProperties, ProviderAPI providerAPI, PolarisDiscoveryProperties polarisDiscoveryProperties) {
this.swagger2Mapper = swagger2Mapper;
this.documentationCache = documentationCache;
public PolarisContractReporter(org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource,
org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource,
PolarisContractProperties polarisContractProperties, ProviderAPI providerAPI,
PolarisDiscoveryProperties polarisDiscoveryProperties) {
this.multipleOpenApiWebMvcResource = multipleOpenApiWebMvcResource;
this.multipleOpenApiWebFluxResource = multipleOpenApiWebFluxResource;
this.polarisContractProperties = polarisContractProperties;
this.providerAPI = providerAPI;
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
Expand All @@ -73,29 +77,37 @@ public PolarisContractReporter(DocumentationCache documentationCache, ServiceMod
public void onApplicationEvent(@NonNull ApplicationReadyEvent applicationReadyEvent) {
if (polarisContractProperties.isReportEnabled()) {
try {
Documentation documentation = documentationCache.documentationByGroup(polarisContractProperties.getGroup());
Swagger swagger = swagger2Mapper.mapDocumentation(documentation);
if (swagger != null) {
AbstractOpenApiResource openApiResource = null;
if (multipleOpenApiWebMvcResource != null) {
openApiResource = OpenApiWebMvcUtil.getOpenApiResourceOrThrow(multipleOpenApiWebMvcResource, polarisContractProperties.getGroup());
}
else if (multipleOpenApiWebFluxResource != null) {
openApiResource = OpenApiWebFluxUtil.getOpenApiResourceOrThrow(multipleOpenApiWebFluxResource, polarisContractProperties.getGroup());
}
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(swagger);
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(swagger);
String jsonValue = JacksonUtils.serialize2Json(openAPI);
LOG.debug("OpenApi json data: {}", jsonValue);
}
}
else {
LOG.warn("Swagger or json is null, documentationCache keys:{}, group:{}", documentationCache.all()
.keySet(), polarisContractProperties.getGroup());
LOG.warn("OpenAPI or json is null, group:{}", polarisContractProperties.getGroup());
}
}
catch (Throwable t) {
Expand All @@ -104,11 +116,11 @@ public void onApplicationEvent(@NonNull ApplicationReadyEvent applicationReadyEv
}
}

private List<InterfaceDescriptor> getInterfaceDescriptorFromSwagger(Swagger swagger) {
private List<InterfaceDescriptor> getInterfaceDescriptorFromSwagger(OpenAPI openAPI) {
List<InterfaceDescriptor> interfaceDescriptorList = new ArrayList<>();
Map<String, Path> paths = swagger.getPaths();
for (Map.Entry<String, Path> p : paths.entrySet()) {
Path path = p.getValue();
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;
Expand All @@ -124,29 +136,29 @@ private List<InterfaceDescriptor> getInterfaceDescriptorFromSwagger(Swagger swag
return interfaceDescriptorList;
}

private Map<String, Operation> getOperationMapFromPath(Path path) {
private Map<String, Operation> getOperationMapFromPath(PathItem path) {
Map<String, Operation> operationMap = new HashMap<>();

if (path.getGet() != null) {
operationMap.put(HttpMethod.GET.name(), path.getGet());
operationMap.put(PathItem.HttpMethod.GET.name(), path.getGet());
}
if (path.getPut() != null) {
operationMap.put(HttpMethod.PUT.name(), path.getPut());
operationMap.put(PathItem.HttpMethod.PUT.name(), path.getPut());
}
if (path.getPost() != null) {
operationMap.put(HttpMethod.POST.name(), path.getPost());
operationMap.put(PathItem.HttpMethod.POST.name(), path.getPost());
}
if (path.getHead() != null) {
operationMap.put(HttpMethod.HEAD.name(), path.getHead());
operationMap.put(PathItem.HttpMethod.HEAD.name(), path.getHead());
}
if (path.getDelete() != null) {
operationMap.put(HttpMethod.DELETE.name(), path.getDelete());
operationMap.put(PathItem.HttpMethod.DELETE.name(), path.getDelete());
}
if (path.getPatch() != null) {
operationMap.put(HttpMethod.PATCH.name(), path.getPatch());
operationMap.put(PathItem.HttpMethod.PATCH.name(), path.getPatch());
}
if (path.getOptions() != null) {
operationMap.put(HttpMethod.OPTIONS.name(), path.getOptions());
operationMap.put(PathItem.HttpMethod.OPTIONS.name(), path.getOptions());
}

return operationMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@

package com.tencent.cloud.polaris.contract.config;

import javax.annotation.Nullable;

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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@

package com.tencent.cloud.polaris.contract.config;

import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.function.Predicate;

import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
Expand All @@ -30,13 +25,13 @@
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 springfox.boot.starter.autoconfigure.OpenApiAutoConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.DocumentationCache;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper;
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.GroupedOpenApi;
import org.springdoc.core.SpringDocConfiguration;
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;
Expand All @@ -45,6 +40,10 @@
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.
Expand All @@ -54,75 +53,48 @@
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisEnabled
@ConditionalOnProperty(name = "spring.cloud.polaris.contract.enabled", havingValue = "true", matchIfMissing = true)
@Import(OpenApiAutoConfiguration.class)
@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 Docket polarisDocket(PolarisContractProperties polarisContractProperties) {
List<Predicate<String>> excludePathList = PackageUtil.getExcludePathPredicates(polarisContractProperties.getExcludePath());
List<Predicate<String>> basePathList = PackageUtil.getBasePathPredicates(polarisContractProperties.getBasePath());
public GroupedOpenApi polarisGroupedOpenApi(PolarisContractProperties polarisContractProperties) {
String basePackage = PackageUtil.scanPackage(polarisContractProperties.getBasePackage());

Predicate<String> basePathListOr = null;
for (Predicate<String> basePathPredicate : basePathList) {
if (basePathListOr == null) {
basePathListOr = basePathPredicate;
}
else {
basePathListOr = basePathListOr.or(basePathPredicate);
}
String[] basePaths = {};
if (StringUtils.hasText(polarisContractProperties.getBasePath())) {
basePaths = polarisContractProperties.getBasePath().split(SPLITTER);
}

Predicate<String> excludePathListOr = null;
for (Predicate<String> excludePathPredicate : excludePathList) {
if (excludePathListOr == null) {
excludePathListOr = excludePathPredicate;
}
else {
excludePathListOr = excludePathListOr.or(excludePathPredicate);
}
}

Predicate<String> pathsPredicate = basePathListOr;

if (excludePathListOr != null) {
excludePathListOr = excludePathListOr.negate();
pathsPredicate = pathsPredicate.and(excludePathListOr);
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();
}

return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(PackageUtil.basePackage(basePackage))
.paths(pathsPredicate)
.build()
.groupName(polarisContractProperties.getGroup())
.enable(polarisContractProperties.isEnabled())
.directModelSubstitute(LocalDate.class, Date.class)
.apiInfo(new ApiInfoBuilder()
@Bean
public OpenAPI polarisOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Polaris Swagger API")
.description("This is to show polaris api description.")
.license("BSD-3-Clause")
.licenseUrl("https://opensource.org/licenses/BSD-3-Clause")
.termsOfServiceUrl("")
.version("1.0.0")
.contact(new Contact("", "", ""))
.build());
.license(new License().name("BSD-3-Clause").url("https://opensource.org/licenses/BSD-3-Clause"))
.version("1.0.0"));
}

@Bean
@ConditionalOnBean(Docket.class)
@ConditionalOnBean(OpenAPI.class)
@ConditionalOnMissingBean
public PolarisContractReporter polarisContractReporter(DocumentationCache documentationCache,
ServiceModelToSwagger2Mapper swagger2Mapper, PolarisContractProperties polarisContractProperties,
PolarisSDKContextManager polarisSDKContextManager, PolarisDiscoveryProperties polarisDiscoveryProperties) {
return new PolarisContractReporter(documentationCache, swagger2Mapper, polarisContractProperties,
polarisSDKContextManager.getProviderAPI(), polarisDiscoveryProperties);
public PolarisContractReporter polarisContractReporter(
@Nullable MultipleOpenApiWebMvcResource multipleOpenApiWebMvcResource,
@Nullable MultipleOpenApiWebFluxResource multipleOpenApiWebFluxResource,
PolarisContractProperties polarisContractProperties, PolarisSDKContextManager polarisSDKContextManager,
PolarisDiscoveryProperties polarisDiscoveryProperties) {
return new PolarisContractReporter(multipleOpenApiWebMvcResource, multipleOpenApiWebFluxResource,
polarisContractProperties, polarisSDKContextManager.getProviderAPI(), polarisDiscoveryProperties);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

import com.tencent.cloud.polaris.contract.config.PolarisContractProperties;

import org.springframework.lang.NonNull;
import org.springframework.web.filter.OncePerRequestFilter;

import static com.tencent.cloud.polaris.contract.filter.FilterConstant.SWAGGER_RESOURCE_PREFIX;
Expand All @@ -51,23 +50,21 @@ public ApiDocServletFilter(PolarisContractProperties polarisContractProperties)
}

@Override
public void doFilterInternal(@NonNull HttpServletRequest httpServletRequest,
@NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain)
throws ServletException, IOException {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (!polarisContractProperties.isExposure()) {
String path = httpServletRequest.getServletPath();
String path = request.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);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
}
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
filterChain.doFilter(request, response);
}
}

Loading

0 comments on commit a641589

Please sign in to comment.