diff --git a/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/config/WebServletConfig.java b/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/config/WebServletConfig.java index 8d779550..f6bcd222 100755 --- a/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/config/WebServletConfig.java +++ b/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/config/WebServletConfig.java @@ -18,8 +18,10 @@ package com.alibaba.csp.sentinel.adapter.servlet.config; import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; import com.alibaba.csp.sentinel.adapter.servlet.CommonTotalFilter; import com.alibaba.csp.sentinel.config.SentinelConfig; +import com.alibaba.csp.sentinel.util.StringUtil; /** + * @author zhaoyuguang * @author leyou */ public class WebServletConfig { @@ -28,6 +30,10 @@ public class WebServletConfig { public static final String BLOCK_PAGE = "csp.sentinel.web.servlet.block.page"; + public static final String BLOCK_PAGE_HTTP_STATUS = "csp.sentinel.web.servlet.block.page.http.status"; + + private static final int HTTP_STATUS_TOO_MANY_REQUESTS = 429; + /** * Get redirecting page when Sentinel blocking for {@link CommonFilter} or * {@link CommonTotalFilter} occurs. @@ -41,4 +47,31 @@ public class WebServletConfig { public static void setBlockPage(String blockPage) { SentinelConfig.setConfig(BLOCK_PAGE, blockPage); } + + /** + * Return status 429 in the default block page, + * you can use -Dcsp.sentinel.web.servlet.block.page.http.status=200 or other http status, + * to set http status which you want of the default block page. + * When csp.sentinel.web.servlet.block.page.http.status is empty or not number, + * the block page http status will be automatically set to 429(Too Many Requests). + * + * @return block page http status + */ + public static int getBlockPageHttpStatus() { + String value = SentinelConfig.getConfig(BLOCK_PAGE_HTTP_STATUS); + if (StringUtil.isEmpty(value)) { + setBlockPageHttpStatus(HTTP_STATUS_TOO_MANY_REQUESTS); + return HTTP_STATUS_TOO_MANY_REQUESTS; + } + try { + return Integer.parseInt(SentinelConfig.getConfig(BLOCK_PAGE_HTTP_STATUS)); + } catch (NumberFormatException e) { + setBlockPageHttpStatus(HTTP_STATUS_TOO_MANY_REQUESTS); + } + return HTTP_STATUS_TOO_MANY_REQUESTS; + } + + public static void setBlockPageHttpStatus(int httpStatus) { + SentinelConfig.setConfig(BLOCK_PAGE_HTTP_STATUS, String.valueOf(httpStatus)); + } } diff --git a/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/util/FilterUtil.java b/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/util/FilterUtil.java index 626aecf1..a4781bea 100755 --- a/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/util/FilterUtil.java +++ b/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/util/FilterUtil.java @@ -27,6 +27,7 @@ import com.alibaba.csp.sentinel.util.StringUtil; /** * Util class for web servlet filter. * + * @author zhaoyuguang * @author youji.zj * @author Eric Zhao */ @@ -65,7 +66,7 @@ public final class FilterUtil { } if (StringUtil.isBlank(WebServletConfig.getBlockPage())) { - writeDefaultBlockedPage(response); + writeDefaultBlockedPage(response, WebServletConfig.getBlockPageHttpStatus()); } else { String redirectUrl = WebServletConfig.getBlockPage() + "?http_referer=" + url.toString(); // Redirect to the customized block page. @@ -73,7 +74,8 @@ public final class FilterUtil { } } - private static void writeDefaultBlockedPage(HttpServletResponse response) throws IOException { + private static void writeDefaultBlockedPage(HttpServletResponse response, int httpStatus) throws IOException { + response.setStatus(httpStatus); PrintWriter out = response.getWriter(); out.print(DEFAULT_BLOCK_MSG); out.flush(); diff --git a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilterTest.java b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilterTest.java index 58574caa..a505ebf8 100644 --- a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilterTest.java +++ b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilterTest.java @@ -41,6 +41,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; @@ -50,6 +51,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** + * @author zhaoyuguang * @author Eric Zhao */ @RunWith(SpringRunner.class) @@ -111,11 +113,17 @@ public class CommonFilterTest { private void testCommonBlockAndRedirectBlockPage(String url, ClusterNode cn) throws Exception { configureRulesFor(url, 0); // The request will be blocked and response is default block message. + WebServletConfig.setBlockPageHttpStatus(HttpStatus.OK.value()); this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()) .andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG)); assertEquals(1, cn.blockQps(), 0.01); + WebServletConfig.setBlockPageHttpStatus(HttpStatus.TOO_MANY_REQUESTS.value()); + this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN)) + .andExpect(status().isTooManyRequests()) + .andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG)); + // Test for redirect. String redirectUrl = "http://some-location.com"; WebServletConfig.setBlockPage(redirectUrl); @@ -192,7 +200,7 @@ public class CommonFilterTest { .andExpect(content().string(HELLO_STR)); // This will be blocked. this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN).header(headerName, limitOrigin)) - .andExpect(status().isOk()) + .andExpect(status().isTooManyRequests()) .andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG)); this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()) diff --git a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletmethod/CommonFilterMethodTest.java b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletmethod/CommonFilterMethodTest.java index 5d9a006a..b2209610 100644 --- a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletmethod/CommonFilterMethodTest.java +++ b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletmethod/CommonFilterMethodTest.java @@ -41,6 +41,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** + * @author zhaoyuguang * @author Roger Law */ @RunWith(SpringRunner.class) @@ -107,7 +108,7 @@ public class CommonFilterMethodTest { configureRulesFor(GET + ":" + url, 0); // The request will be blocked and response is default block message. this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN)) - .andExpect(status().isOk()) + .andExpect(status().isTooManyRequests()) .andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG)); assertEquals(1, cnGet.blockQps(), 0.01);