diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java index 71b7c8e85..8d4da4995 100644 --- a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java @@ -44,6 +44,11 @@ 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 { private final Logger LOG = LoggerFactory.getLogger(PolarisContractReporter.class); diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ContractProperties.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ContractProperties.java index 32970b067..3e915f5d4 100644 --- a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ContractProperties.java +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ContractProperties.java @@ -43,4 +43,8 @@ public interface ContractProperties { String getBasePath(); void setBasePath(String basePath); + + boolean isExposure(); + + void setExposure(boolean exposure); } diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractProperties.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractProperties.java index edafa77fc..68681ae36 100644 --- a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractProperties.java +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractProperties.java @@ -51,6 +51,8 @@ public class PolarisContractProperties implements ContractProperties { */ private String basePath = "/**"; + private boolean exposure = true; + public PolarisContractProperties(@Nullable ExtendedContractProperties extendContractProperties) { this.extendContractProperties = extendContractProperties; } @@ -119,4 +121,17 @@ public class PolarisContractProperties implements ContractProperties { 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; + } } diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisSwaggerAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisSwaggerAutoConfiguration.java index 3778b792d..c9c05b8fd 100644 --- a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisSwaggerAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisSwaggerAutoConfiguration.java @@ -22,6 +22,8 @@ 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; @@ -43,6 +45,11 @@ 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) @@ -108,7 +115,10 @@ public class PolarisSwaggerAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) protected static class SwaggerServletConfig { - + @Bean + public ApiDocServletFilter apiDocServletFilter(PolarisContractProperties polarisContractProperties) { + return new ApiDocServletFilter(polarisContractProperties); + } } /** @@ -118,6 +128,9 @@ public class PolarisSwaggerAutoConfiguration { @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) protected static class SwaggerReactiveConfig { - + @Bean + public ApiDocWebFluxFilter apiDocWebFluxFilter(PolarisContractProperties polarisContractProperties) { + return new ApiDocWebFluxFilter(polarisContractProperties); + } } } diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/ApiDocServletFilter.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/ApiDocServletFilter.java new file mode 100644 index 000000000..cea49ca44 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/ApiDocServletFilter.java @@ -0,0 +1,55 @@ +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.annotation.WebFilter; +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_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; +import static org.springdoc.core.utils.Constants.SWAGGER_UI_URL; + +/** + * Filter to disable api doc controller. + * + * @author Haotian Zhang + */ +@WebFilter +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.equals(SWAGGER_V2_API_DOC_URL) || + path.startsWith(SWAGGER_V3_API_DOC_URL) || + path.equals(SWAGGER_UI_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); + } +} + diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/ApiDocWebFluxFilter.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/ApiDocWebFluxFilter.java new file mode 100644 index 000000000..a0bb03d0e --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/ApiDocWebFluxFilter.java @@ -0,0 +1,53 @@ +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_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 filter(ServerWebExchange serverWebExchange, @NonNull WebFilterChain webFilterChain) { + if (!polarisContractProperties.isExposure()) { + String path = serverWebExchange.getRequest().getURI().getPath(); + if (path.equals(SWAGGER_V2_API_DOC_URL) || + path.startsWith(SWAGGER_V3_API_DOC_URL) || + path.equals(SWAGGER_UI_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); + } +} + diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/FilterConstant.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/FilterConstant.java new file mode 100644 index 000000000..ef49af57c --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/filter/FilterConstant.java @@ -0,0 +1,59 @@ +/* + * 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 url. + */ + public static final String SWAGGER_UI_URL = "/swagger-ui.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() { + } +} diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/utils/PackageUtil.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/utils/PackageUtil.java index 96529d4c8..1afcb709d 100644 --- a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/utils/PackageUtil.java +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/utils/PackageUtil.java @@ -35,10 +35,12 @@ import org.springframework.util.StringUtils; */ public final class PackageUtil { + /** + * splitter for property. + */ public static final String SPLITTER = ","; private static final Logger LOG = LoggerFactory.getLogger(PackageUtil.class); - private PackageUtil() { } diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-contract/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 000000000..4e5e4b72d --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-contract/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -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." + } + ] +} diff --git a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/pom.xml b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/pom.xml index 2decc0c0e..312b45c1a 100644 --- a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/pom.xml +++ b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/pom.xml @@ -24,11 +24,6 @@ spring-cloud-starter-tencent-polaris-contract - - - - - com.tencent.cloud spring-cloud-starter-tencent-polaris-discovery diff --git a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/src/main/resources/bootstrap.yml index ec34c0c35..1f3a5b9e5 100644 --- a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/src/main/resources/bootstrap.yml @@ -11,6 +11,8 @@ spring: discovery: enabled: true register: true + contract: + exposure: true stat: enabled: true port: 28082 diff --git a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/src/main/resources/bootstrap.yml index 71f388051..0f2594f59 100644 --- a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/src/main/resources/bootstrap.yml @@ -22,6 +22,8 @@ spring: heartbeat: enabled: true health-check-url: /discovery/service/caller/healthCheck + contract: + exposure: false stat: enabled: true port: 28081