Merge branch 'main' of github.com:Tencent/spring-cloud-tencent

pull/136/head
SkyeBeFreeman 3 years ago
commit a48f2344c2

@ -1,4 +1,7 @@
# Change Log
---
- [Feature: Support custom rate limit reject response info](https://github.com/Tencent/spring-cloud-tencent/pull/128)
- [Feature: Remove spring-javaformat-maven-plugin](https://github.com/Tencent/spring-cloud-tencent/pull/131)

@ -2,6 +2,9 @@
[![Build Status](https://github.com/Tencent/spring-cloud-tencent/actions/workflows/junit_test.yml/badge.svg)](https://github.com/Tencent/spring-cloud-tencent/actions/workflows/junit_test.yml)
[![Maven Central](https://img.shields.io/maven-central/v/com.tencent.cloud/spring-cloud-tencent?label=Maven%20Central)](https://search.maven.org/search?q=g:com.tencent.cloud%20AND%20a:spring-cloud-tencent)
[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![Percentage of issues still open](http://isitmaintained.com/badge/open/Tencent/spring-cloud-tencent.svg)](https://github.com/Tencent/spring-cloud-tencent/issues)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/spring-cloud-tencent/wiki/Contributing)
[English](./README.md) | 简体中文
@ -79,3 +82,10 @@ Spring Cloud Tencent 所有组件都已上传到 Maven 中央仓库,只需要
## License
The spring-cloud-tencent is licensed under the BSD 3-Clause License. Copyright and license information can be found in the file [LICENSE](LICENSE)
## Stargazers over time
如果您对 Spring Cloud Tencent 有兴趣,请关注我们的项目~
[![Stargazers over time](https://starchart.cc/Tencent/spring-cloud-tencent.svg)](https://starchart.cc/Tencent/spring-cloud-tencent)

@ -2,6 +2,9 @@
[![Build Status](https://github.com/Tencent/spring-cloud-tencent/actions/workflows/junit_test.yml/badge.svg)](https://github.com/Tencent/spring-cloud-tencent/actions/workflows/junit_test.yml)
[![Maven Central](https://img.shields.io/maven-central/v/com.tencent.cloud/spring-cloud-tencent?label=Maven%20Central)](https://search.maven.org/search?q=g:com.tencent.cloud%20AND%20a:spring-cloud-tencent)
[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![Percentage of issues still open](http://isitmaintained.com/badge/open/Tencent/spring-cloud-tencent.svg)](https://github.com/Tencent/spring-cloud-tencent/issues)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/spring-cloud-tencent/wiki/Contributing)
English | [简体中文](./README-zh.md)
@ -77,3 +80,10 @@ For example:
## License
The spring-cloud-tencent is licensed under the BSD 3-Clause License. Copyright and license information can be found in the file [LICENSE](LICENSE)
## Stargazers over time
If you are interested in Spring Cloud Tencent, please follow our project, thank you very much.
[![Stargazers over time](https://starchart.cc/Tencent/spring-cloud-tencent.svg)](https://starchart.cc/Tencent/spring-cloud-tencent)

@ -98,6 +98,7 @@
<jacoco.version>0.8.3</jacoco.version>
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
<flatten-maven-plugin.version>1.2.7</flatten-maven-plugin.version>
<maven-gpg-plugin.version>3.0.1</maven-gpg-plugin.version>
<!-- Checkstyle -->
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
@ -145,10 +146,6 @@
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>

@ -0,0 +1,71 @@
/*
* 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.ratelimit.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.HttpStatus;
/**
* The properties for rate limit.
*
* @author lepdou 2022-04-20
*/
@ConfigurationProperties("spring.cloud.polaris.ratelimit")
public class PolarisRateLimitProperties {
/**
* custom tips when reject request.
*/
private String rejectRequestTips;
/**
* context file path.
*/
private String rejectRequestTipsFilePath;
/**
* custom http code when reject request.
*/
private int rejectHttpCode = HttpStatus.TOO_MANY_REQUESTS.value();
public String getRejectRequestTips() {
return rejectRequestTips;
}
public void setRejectRequestTips(String rejectRequestTips) {
this.rejectRequestTips = rejectRequestTips;
}
public String getRejectRequestTipsFilePath() {
return rejectRequestTipsFilePath;
}
public void setRejectRequestTipsFilePath(String rejectRequestTipsFilePath) {
this.rejectRequestTipsFilePath = rejectRequestTipsFilePath;
}
public int getRejectHttpCode() {
return rejectHttpCode;
}
public void setRejectHttpCode(int rejectHttpCode) {
this.rejectHttpCode = rejectHttpCode;
}
}

@ -51,6 +51,11 @@ import static javax.servlet.DispatcherType.REQUEST;
matchIfMissing = true)
public class RateLimitConfiguration {
@Bean
public PolarisRateLimitProperties polarisRateLimitProperties() {
return new PolarisRateLimitProperties();
}
@Bean
@ConditionalOnMissingBean
public LimitAPI limitAPI(SDKContext polarisContext) {
@ -67,8 +72,10 @@ public class RateLimitConfiguration {
@Bean
@ConditionalOnMissingBean
public QuotaCheckServletFilter quotaCheckFilter(LimitAPI limitAPI,
@Nullable PolarisRateLimiterLabelServletResolver labelResolver) {
return new QuotaCheckServletFilter(limitAPI, labelResolver);
@Nullable PolarisRateLimiterLabelServletResolver labelResolver,
PolarisRateLimitProperties polarisRateLimitProperties) {
return new QuotaCheckServletFilter(limitAPI, labelResolver,
polarisRateLimitProperties);
}
@Bean
@ -93,8 +100,10 @@ public class RateLimitConfiguration {
@Bean
public QuotaCheckReactiveFilter quotaCheckReactiveFilter(LimitAPI limitAPI,
@Nullable PolarisRateLimiterLabelReactiveResolver labelResolver) {
return new QuotaCheckReactiveFilter(limitAPI, labelResolver);
@Nullable PolarisRateLimiterLabelReactiveResolver labelResolver,
PolarisRateLimitProperties polarisRateLimitProperties) {
return new QuotaCheckReactiveFilter(limitAPI, labelResolver,
polarisRateLimitProperties);
}
}

@ -22,10 +22,14 @@ import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
import com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant;
import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLabelReactiveResolver;
import com.tencent.cloud.polaris.ratelimit.utils.QuotaCheckUtils;
import com.tencent.cloud.polaris.ratelimit.utils.RateLimitUtils;
import com.tencent.polaris.ratelimit.api.core.LimitAPI;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResponse;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResultCode;
@ -36,7 +40,6 @@ import reactor.core.publisher.Mono;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.CollectionUtils;
@ -60,10 +63,21 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
private final PolarisRateLimiterLabelReactiveResolver labelResolver;
private final PolarisRateLimitProperties polarisRateLimitProperties;
private String rejectTips;
public QuotaCheckReactiveFilter(LimitAPI limitAPI,
PolarisRateLimiterLabelReactiveResolver labelResolver) {
PolarisRateLimiterLabelReactiveResolver labelResolver,
PolarisRateLimitProperties polarisRateLimitProperties) {
this.limitAPI = limitAPI;
this.labelResolver = labelResolver;
this.polarisRateLimitProperties = polarisRateLimitProperties;
}
@PostConstruct
public void init() {
rejectTips = RateLimitUtils.getRejectTips(polarisRateLimitProperties);
}
@Override
@ -104,11 +118,10 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
response.setRawStatusCode(polarisRateLimitProperties.getRejectHttpCode());
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
DataBuffer dataBuffer = response.bufferFactory().allocateBuffer()
.write(RateLimitConstant.QUOTA_LIMITED_INFO
.getBytes(StandardCharsets.UTF_8));
.write(rejectTips.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(dataBuffer));
}
}

@ -22,15 +22,18 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
import com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant;
import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLabelServletResolver;
import com.tencent.cloud.polaris.ratelimit.utils.QuotaCheckUtils;
import com.tencent.cloud.polaris.ratelimit.utils.RateLimitUtils;
import com.tencent.polaris.ratelimit.api.core.LimitAPI;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResponse;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResultCode;
@ -43,7 +46,6 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import static com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant.LABEL_METHOD;
import static org.springframework.http.HttpStatus.TOO_MANY_REQUESTS;
/**
* Servlet filter to check quota.
@ -60,10 +62,21 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
private final PolarisRateLimiterLabelServletResolver labelResolver;
private final PolarisRateLimitProperties polarisRateLimitProperties;
private String rejectTips;
public QuotaCheckServletFilter(LimitAPI limitAPI,
PolarisRateLimiterLabelServletResolver labelResolver) {
PolarisRateLimiterLabelServletResolver labelResolver,
PolarisRateLimitProperties polarisRateLimitProperties) {
this.limitAPI = limitAPI;
this.labelResolver = labelResolver;
this.polarisRateLimitProperties = polarisRateLimitProperties;
}
@PostConstruct
public void init() {
rejectTips = RateLimitUtils.getRejectTips(polarisRateLimitProperties);
}
@Override
@ -100,8 +113,8 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(limitAPI,
localNamespace, localService, 1, labels, null);
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
response.setStatus(TOO_MANY_REQUESTS.value());
response.getWriter().write(RateLimitConstant.QUOTA_LIMITED_INFO);
response.setStatus(polarisRateLimitProperties.getRejectHttpCode());
response.getWriter().write(rejectTips);
}
else {
filterChain.doFilter(request, response);

@ -0,0 +1,70 @@
/*
* 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.ratelimit.utils;
import com.tencent.cloud.common.util.ResourceFileUtils;
import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
import com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant;
import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckServletFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
/**
* Rate limit utils.
*
* @author lepdou 2022-04-20
*/
public final class RateLimitUtils {
private static final Logger LOG = LoggerFactory
.getLogger(QuotaCheckServletFilter.class);
private RateLimitUtils() {
}
public static String getRejectTips(
PolarisRateLimitProperties polarisRateLimitProperties) {
String tips = polarisRateLimitProperties.getRejectRequestTips();
if (!StringUtils.isEmpty(tips)) {
return tips;
}
String rejectFilePath = polarisRateLimitProperties.getRejectRequestTipsFilePath();
if (!StringUtils.isEmpty(rejectFilePath)) {
try {
tips = ResourceFileUtils.readFile(rejectFilePath);
}
catch (Exception e) {
LOG.error("[RateLimit] Read custom reject tips file error. path = {}",
rejectFilePath, e);
}
}
if (!StringUtils.isEmpty(tips)) {
return tips;
}
return RateLimitConstant.QUOTA_LIMITED_INFO;
}
}

@ -5,6 +5,24 @@
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "Enable polaris rate limit or not."
},
{
"name": "spring.cloud.polaris.ratelimit.rejectRequestTips",
"type": "java.lang.String",
"defaultValue": "",
"description": "Custom tips when reject request."
},
{
"name": "spring.cloud.polaris.ratelimit.rejectRequestTipsFilePath",
"type": "java.lang.String",
"defaultValue": "",
"description": "Custom tips file path when reject request."
},
{
"name": "spring.cloud.polaris.ratelimit.rejectHttpCode",
"type": "java.lang.Integer",
"defaultValue": "429",
"description": "Custom http code when reject request."
}
]
}

@ -0,0 +1,54 @@
/*
* 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.common.util;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.springframework.core.io.ClassPathResource;
/**
* Read file content from classpath resource.
*
* @author lepdou 2022-04-20
*/
public final class ResourceFileUtils {
private ResourceFileUtils() {
}
public static String readFile(String path) throws IOException {
StringBuilder sb = new StringBuilder();
ClassPathResource classPathResource = new ClassPathResource(path);
if (classPathResource.exists() && classPathResource.isReadable()) {
try (InputStream inputStream = classPathResource.getInputStream()) {
byte[] buffer = new byte[1024 * 10];
int len;
while ((len = inputStream.read(buffer)) != -1) {
sb.append(new String(buffer, 0, len, StandardCharsets.UTF_8));
}
}
}
return sb.toString();
}
}

@ -76,9 +76,8 @@
<!-- Maven Plugin Versions -->
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<flatten-maven-plugin.version>1.2.7</flatten-maven-plugin.version>
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
<maven-gpg-plugin.version>3.0.1</maven-gpg-plugin.version>
</properties>
<dependencyManagement>

@ -24,4 +24,13 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -10,3 +10,4 @@ spring:
enabled: true
ratelimit:
enabled: true
rejectRequestTipsFilePath: reject-tips.html

Loading…
Cancel
Save