Browse Source

Improve CommonFilter and WebServletConfig in Sentinel Web Servlet adapter

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao 5 years ago
parent
commit
9d514d5036
3 changed files with 56 additions and 26 deletions
  1. +5
    -2
      sentinel-adapter/sentinel-web-servlet/README.md
  2. +16
    -6
      sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java
  3. +35
    -18
      sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/config/WebServletConfig.java

+ 5
- 2
sentinel-adapter/sentinel-web-servlet/README.md View File

@@ -39,7 +39,7 @@ public class FilterConfig {
registration.addUrlPatterns("/*");
registration.setName("sentinelCommonFilter");
registration.setOrder(1);
// Set whether to support the specified HTTP method for the filter.
// Set whether to support the specified HTTP method prefix for the filter.
registration.addInitParameter(CommonFilter.HTTP_METHOD_SPECIFY, "false");
return registration;
}
@@ -47,6 +47,9 @@ public class FilterConfig {
```

When a request is blocked, Sentinel servlet filter will display a default page indicating the request is rejected.
The HTTP status code of the default block page is **429 (Too Many Requests)**. You can customize it
via the `csp.sentinel.web.servlet.block.status` configuration item (since 1.7.0).

If customized block page is set (via `WebServletConfig.setBlockPage(blockPage)` method),
the filter will redirect the request to provided URL. You can also implement your own
block handler (the `UrlBlockHandler` interface) and register to `WebCallbackManager`.
@@ -59,5 +62,5 @@ If you need to exclude some URLs (that should not be recorded as Sentinel resour
leverage the `UrlCleaner` interface. You may unify the unwanted URLs to the empty string `""` or `null`,
then the URLs will be excluded (since Sentinel 1.6.3).

`RequestOriginParser` interface is useful for extracting request origin (e.g. IP or appName from HTTP Header)
The `RequestOriginParser` interface is useful for extracting request origin (e.g. IP or appName from HTTP Header)
from HTTP request. You can implement your own `RequestOriginParser` and register to `WebCallbackManager`.

+ 16
- 6
sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java View File

@@ -39,21 +39,30 @@ import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.util.StringUtil;

/***
/**
* Servlet filter that integrates with Sentinel.
*
* @author zhaoyuguang
* @author youji.zj
* @author Eric Zhao
* @author zhaoyuguang
*/
public class CommonFilter implements Filter {

public final static String HTTP_METHOD_SPECIFY = "HTTP_METHOD_SPECIFY";
/**
* Use the path of the url as the context, if necessary, but pay attention to the number of context EntranceNode
* Specify whether the URL resource name should contain the HTTP method prefix (e.g. {@code POST:}).
*/
public static final String HTTP_METHOD_SPECIFY = "HTTP_METHOD_SPECIFY";
/**
* If enabled, use the URL path as the context name, or else use the default
* {@link WebServletConfig#WEB_SERVLET_CONTEXT_NAME}. Please pay attention to the number of context (EntranceNode),
* which may affect the memory footprint.
*
* @since 1.7.0
*/
public final static String WEB_CONTEXT_UNIFY = "WEB_CONTEXT_UNIFY";
public static final String WEB_CONTEXT_UNIFY = "WEB_CONTEXT_UNIFY";

private final static String COLON = ":";

private boolean httpMethodSpecify = false;
private boolean webContextUnify = true;

@@ -87,7 +96,8 @@ public class CommonFilter implements Filter {
if (!StringUtil.isEmpty(target)) {
// Parse the request origin using registered origin parser.
String origin = parseOrigin(sRequest);
ContextUtil.enter(webContextUnify ? WebServletConfig.WEB_SERVLET_CONTEXT_NAME : target, origin);
String contextName = webContextUnify ? WebServletConfig.WEB_SERVLET_CONTEXT_NAME : target;
ContextUtil.enter(contextName, origin);
urlEntry = SphU.entry(target, EntryType.IN);
// Add method specification if necessary
if (httpMethodSpecify) {


+ 35
- 18
sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/config/WebServletConfig.java View File

@@ -18,19 +18,21 @@ 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.log.RecordLog;
import com.alibaba.csp.sentinel.util.StringUtil;

/**
* @author zhaoyuguang
* The configuration center for Web Servlet adapter.
*
* @author leyou
* @author zhaoyuguang
*/
public class WebServletConfig {
public final class WebServletConfig {

public static final String WEB_SERVLET_CONTEXT_NAME = "sentinel_web_servlet_context";

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";
public static final String BLOCK_PAGE_URL_CONF_KEY = "csp.sentinel.web.servlet.block.page";
public static final String BLOCK_PAGE_HTTP_STATUS_CONF_KEY = "csp.sentinel.web.servlet.block.status";

private static final int HTTP_STATUS_TOO_MANY_REQUESTS = 429;

@@ -41,37 +43,52 @@ public class WebServletConfig {
* @return the block page URL, maybe null if not configured.
*/
public static String getBlockPage() {
return SentinelConfig.getConfig(BLOCK_PAGE);
return SentinelConfig.getConfig(BLOCK_PAGE_URL_CONF_KEY);
}

public static void setBlockPage(String blockPage) {
SentinelConfig.setConfig(BLOCK_PAGE, blockPage);
SentinelConfig.setConfig(BLOCK_PAGE_URL_CONF_KEY, 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).
* <p>Get the HTTP status when using the default block page.</p>
* <p>You can set the status code with the {@code -Dcsp.sentinel.web.servlet.block.status}
* property. When the property is empty or invalid, Sentinel will use 429 (Too Many Requests)
* as the default status code.</p>
*
* @return block page http status
* @return the HTTP status of the default block page
* @since 1.7.0
*/
public static int getBlockPageHttpStatus() {
String value = SentinelConfig.getConfig(BLOCK_PAGE_HTTP_STATUS);
String value = SentinelConfig.getConfig(BLOCK_PAGE_HTTP_STATUS_CONF_KEY);
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) {
int s = Integer.parseInt(value);
if (s <= 0) {
throw new IllegalArgumentException("Invalid status code: " + s);
}
return s;
} catch (Exception e) {
RecordLog.warn("[WebServletConfig] Invalid block HTTP status (" + value + "), using default 429");
setBlockPageHttpStatus(HTTP_STATUS_TOO_MANY_REQUESTS);
}
return HTTP_STATUS_TOO_MANY_REQUESTS;
}

/**
* Set the HTTP status of the default block page.
*
* @param httpStatus the HTTP status of the default block page
* @since 1.7.0
*/
public static void setBlockPageHttpStatus(int httpStatus) {
SentinelConfig.setConfig(BLOCK_PAGE_HTTP_STATUS, String.valueOf(httpStatus));
if (httpStatus <= 0) {
throw new IllegalArgumentException("Invalid HTTP status code: " + httpStatus);
}
SentinelConfig.setConfig(BLOCK_PAGE_HTTP_STATUS_CONF_KEY, String.valueOf(httpStatus));
}

private WebServletConfig() {}
}

Loading…
Cancel
Save