From 2433d3aa41f656c720b8153a0ede54d3dbfb90ee Mon Sep 17 00:00:00 2001 From: Haotian Zhang <928016560@qq.com> Date: Thu, 26 Mar 2026 19:14:38 +0800 Subject: [PATCH] fix: prepend context-path to TsfApiMetadataGrapher OpenAPI paths Apply the same context-path fix to TsfApiMetadataGrapher as was done for PolarisContractReporter. When server.servlet.context-path or spring.webflux.base-path is configured, the OpenAPI paths are now prefixed before serialization to the $api_metas system property. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Haotian Zhang <928016560@qq.com> --- .../contract/tsf/TsfApiMetadataGrapher.java | 16 +++++++++++++++- .../tsf/TsfSwaggerAutoConfiguration.java | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/tsf/TsfApiMetadataGrapher.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/tsf/TsfApiMetadataGrapher.java index 9e9f6b5af..bdcb91ae4 100644 --- a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/tsf/TsfApiMetadataGrapher.java +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/tsf/TsfApiMetadataGrapher.java @@ -17,12 +17,15 @@ package com.tencent.cloud.polaris.contract.tsf; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import com.tencent.cloud.common.util.GzipUtil; import io.swagger.v3.oas.models.OpenAPI; +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; @@ -45,15 +48,18 @@ public class TsfApiMetadataGrapher implements SmartLifecycle { private final ObjectMapperProvider springdocObjectMapperProvider; private final ApplicationContext applicationContext; private final String groupName; + private final String contextPath; public TsfApiMetadataGrapher(org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource, org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource, - String groupName, ApplicationContext applicationContext, ObjectMapperProvider springdocObjectMapperProvider) { + String groupName, ApplicationContext applicationContext, ObjectMapperProvider springdocObjectMapperProvider, + String contextPath) { this.applicationContext = applicationContext; this.multipleOpenApiWebMvcResource = multipleOpenApiWebMvcResource; this.multipleOpenApiWebFluxResource = multipleOpenApiWebFluxResource; this.groupName = groupName; this.springdocObjectMapperProvider = springdocObjectMapperProvider; + this.contextPath = contextPath; } @Override @@ -84,6 +90,14 @@ public class TsfApiMetadataGrapher implements SmartLifecycle { if (openApiResource != null) { openAPI = AbstractOpenApiResourceUtil.getOpenApi(openApiResource); } + if (openAPI != null && contextPath != null && !contextPath.isEmpty() + && openAPI.getPaths() != null) { + Paths newPaths = new Paths(); + for (Map.Entry entry : openAPI.getPaths().entrySet()) { + newPaths.addPathItem(contextPath + entry.getKey(), entry.getValue()); + } + openAPI.setPaths(newPaths); + } String jsonValue; if (springdocObjectMapperProvider != null && springdocObjectMapperProvider.jsonMapper() != null) { jsonValue = springdocObjectMapperProvider.jsonMapper().writeValueAsString(openAPI); diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/tsf/TsfSwaggerAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/tsf/TsfSwaggerAutoConfiguration.java index f9fa53fd4..defd3208d 100644 --- a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/tsf/TsfSwaggerAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/tsf/TsfSwaggerAutoConfiguration.java @@ -28,7 +28,9 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; @Configuration @ConditionalOnTsfConsulEnabled @@ -39,8 +41,16 @@ public class TsfSwaggerAutoConfiguration { @ConditionalOnBean(OpenAPI.class) public TsfApiMetadataGrapher tsfApiMetadataGrapher(@Nullable MultipleOpenApiWebMvcResource multipleOpenApiWebMvcResource, @Nullable MultipleOpenApiWebFluxResource multipleOpenApiWebFluxResource, ApplicationContext context, - PolarisContractProperties polarisContractProperties, ObjectMapperProvider springdocObjectMapperProvider) { + PolarisContractProperties polarisContractProperties, ObjectMapperProvider springdocObjectMapperProvider, + Environment environment) { + String contextPath = environment.getProperty("server.servlet.context-path", ""); + if (!StringUtils.hasText(contextPath)) { + contextPath = environment.getProperty("spring.webflux.base-path", ""); + } + if (contextPath.endsWith("/")) { + contextPath = contextPath.substring(0, contextPath.length() - 1); + } return new TsfApiMetadataGrapher(multipleOpenApiWebMvcResource, multipleOpenApiWebFluxResource, - polarisContractProperties.getGroup(), context, springdocObjectMapperProvider); + polarisContractProperties.getGroup(), context, springdocObjectMapperProvider, contextPath); } }