diff --git a/CHANGELOG.md b/CHANGELOG.md
index e2d842a70..3d19c23a4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,5 +9,6 @@
- [Feat: optimize router dependency](https://github.com/Tencent/spring-cloud-tencent/pull/114)
- [Refactor: refactor transfer metadata](https://github.com/Tencent/spring-cloud-tencent/pull/112)
- [feat:add switch of polaris, discovery and register.](https://github.com/Tencent/spring-cloud-tencent/pull/133)
+- [Feature: Support custom rate limit reject response info](https://github.com/Tencent/spring-cloud-tencent/pull/154)
- [Feature: Remove spring-javaformat-maven-plugin](https://github.com/Tencent/spring-cloud-tencent/pull/152)
- [feat:optimize config server address](https://github.com/Tencent/spring-cloud-tencent/pull/150)
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/PolarisRateLimitProperties.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/PolarisRateLimitProperties.java
new file mode 100644
index 000000000..d51d90b9c
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/PolarisRateLimitProperties.java
@@ -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;
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/RateLimitConfiguration.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/RateLimitConfiguration.java
index f45b5cd0f..6eb5451ba 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/RateLimitConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/RateLimitConfiguration.java
@@ -49,6 +49,11 @@ import static javax.servlet.DispatcherType.REQUEST;
@ConditionalOnProperty(name = "spring.cloud.polaris.ratelimit.enabled", matchIfMissing = true)
public class RateLimitConfiguration {
+ @Bean
+ public PolarisRateLimitProperties polarisRateLimitProperties() {
+ return new PolarisRateLimitProperties();
+ }
+
@Bean
@ConditionalOnMissingBean
public LimitAPI limitAPI(SDKContext polarisContext) {
@@ -65,8 +70,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
@@ -91,8 +98,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);
}
}
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
index 0db616f7f..9a0db9a77 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
@@ -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));
}
}
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
index 85706d944..ae1601093 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
@@ -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);
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/utils/RateLimitUtils.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/utils/RateLimitUtils.java
new file mode 100644
index 000000000..2e036909c
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/utils/RateLimitUtils.java
@@ -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;
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index b71a17cc4..19b37aeb5 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -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."
}
]
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ResourceFileUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ResourceFileUtils.java
new file mode 100644
index 000000000..d79bfce8b
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ResourceFileUtils.java
@@ -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();
+ }
+
+}
diff --git a/spring-cloud-tencent-examples/polaris-ratelimit-example/ratelimit-callee-service/pom.xml b/spring-cloud-tencent-examples/polaris-ratelimit-example/ratelimit-callee-service/pom.xml
index 62af83910..dd28040b5 100644
--- a/spring-cloud-tencent-examples/polaris-ratelimit-example/ratelimit-callee-service/pom.xml
+++ b/spring-cloud-tencent-examples/polaris-ratelimit-example/ratelimit-callee-service/pom.xml
@@ -1,27 +1,36 @@