Support customized block page HTTP status in sentinel-web-servlet-adapter (#1112)
* Return canonical status 429 in the default block handler of sentinel-web-servlet-adapter. * Add a `csp.sentinel.web.servlet.block.page.http.status` property to support customized block status configuration.
This commit is contained in:
parent
cf5b955f12
commit
a451d4bbac
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue