Skip to content

Commit

Permalink
Support customized block page HTTP status in sentinel-web-servlet-ada…
Browse files Browse the repository at this point in the history
…pter (alibaba#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.
  • Loading branch information
zhaoyuguang authored and sczyh30 committed Nov 6, 2019
1 parent cf5b955 commit a451d4b
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
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 {
Expand All @@ -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.
Expand All @@ -41,4 +47,31 @@ public static String getBlockPage() {
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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
/**
* Util class for web servlet filter.
*
* @author zhaoyuguang
* @author youji.zj
* @author Eric Zhao
*/
Expand Down Expand Up @@ -65,15 +66,16 @@ public static void blockRequest(HttpServletRequest request, HttpServletResponse
}

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.
response.sendRedirect(redirectUrl);
}
}

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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
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;
Expand All @@ -50,6 +51,7 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

/**
* @author zhaoyuguang
* @author Eric Zhao
*/
@RunWith(SpringRunner.class)
Expand Down Expand Up @@ -111,11 +113,17 @@ public void testCommonFilterMiscellaneous() throws Exception {
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);
Expand Down Expand Up @@ -192,7 +200,7 @@ public String parseOrigin(HttpServletRequest request) {
.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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

/**
* @author zhaoyuguang
* @author Roger Law
*/
@RunWith(SpringRunner.class)
Expand Down Expand Up @@ -107,7 +108,7 @@ private void testCommonBlockAndRedirectBlockPage(String url, ClusterNode cnGet,
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);

Expand Down

0 comments on commit a451d4b

Please sign in to comment.