浏览代码

Update Sentinel Web Servlet integration

- Add RequestOriginParser interface to extract request origin from the HTTP request
- Some code refinement

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao 6 年前
父节点
当前提交
90d5611b23
共有 4 个文件被更改,包括 98 次插入6 次删除
  1. +17
    -2
      sentinel-adapter/sentinel-web-servlet/README.md
  2. +30
    -2
      sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java
  3. +35
    -0
      sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/callback/RequestOriginParser.java
  4. +16
    -2
      sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/callback/WebCallbackManager.java

+ 17
- 2
sentinel-adapter/sentinel-web-servlet/README.md 查看文件

@@ -1,7 +1,16 @@
# Sentinel Web Servlet Filter # Sentinel Web Servlet Filter


Sentinel provides Servlet filter integration. To use the filter,
you can simply configure your `web.xml` with:
Sentinel provides Servlet filter integration to enable flow control for web requests. Add the following dependency in `pom.xml` (if you are using Maven):

```xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
<version>x.y.z</version>
</dependency>
```

To use the filter, you can simply configure your `web.xml` with:


```xml ```xml
<filter> <filter>
@@ -20,3 +29,9 @@ If customized block page is set (via `WebServletConfig.setBlockPage(blockPage)`
the filter will redirect the request to provided URL. You can also implement your own the filter will redirect the request to provided URL. You can also implement your own
block handler (the `UrlBlockHandler` interface) and register to `WebCallbackManager`. block handler (the `UrlBlockHandler` interface) and register to `WebCallbackManager`.


The `UrlCleaner` interface is designed for clean and unify the URL resource.
For REST APIs, you have to clean the URL resource (e.g. `/foo/1` and `/foo/2` -> `/foo/:id`), or
the amount of context and resources will exceed the threshold.

`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`.

+ 30
- 2
sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java 查看文件

@@ -30,15 +30,19 @@ import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType; import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU; import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer; import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner;
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager; import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil; import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil;
import com.alibaba.csp.sentinel.context.ContextUtil; import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.util.StringUtil;


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


@@ -55,14 +59,24 @@ public class CommonFilter implements Filter {


try { try {
String target = FilterUtil.filterTarget(sRequest); String target = FilterUtil.filterTarget(sRequest);
target = WebCallbackManager.getUrlCleaner().clean(target);
// Clean and unify the URL.
// For REST APIs, you have to clean the URL (e.g. `/foo/1` and `/foo/2` -> `/foo/:id`), or
// the amount of context and resources will exceed the threshold.
UrlCleaner urlCleaner = WebCallbackManager.getUrlCleaner();
if (urlCleaner != null) {
target = urlCleaner.clean(target);
}

// Parse the request origin using registered origin parser.
String origin = parseOrigin(sRequest);


ContextUtil.enter(target);
ContextUtil.enter(target, origin);
entry = SphU.entry(target, EntryType.IN); entry = SphU.entry(target, EntryType.IN);


chain.doFilter(request, response); chain.doFilter(request, response);
} catch (BlockException e) { } catch (BlockException e) {
HttpServletResponse sResponse = (HttpServletResponse)response; HttpServletResponse sResponse = (HttpServletResponse)response;
// Return the block page, or redirect to another URL.
WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse); WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse);
} catch (IOException e2) { } catch (IOException e2) {
Tracer.trace(e2); Tracer.trace(e2);
@@ -81,8 +95,22 @@ public class CommonFilter implements Filter {
} }
} }


private String parseOrigin(HttpServletRequest request) {
RequestOriginParser originParser = WebCallbackManager.getRequestOriginParser();
String origin = EMPTY_ORIGIN;
if (originParser != null) {
origin = originParser.parseOrigin(request);
if (StringUtil.isEmpty(origin)) {
return EMPTY_ORIGIN;
}
}
return origin;
}

@Override @Override
public void destroy() { public void destroy() {


} }

private static final String EMPTY_ORIGIN = "";
} }

+ 35
- 0
sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/callback/RequestOriginParser.java 查看文件

@@ -0,0 +1,35 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.alibaba.csp.sentinel.adapter.servlet.callback;

import javax.servlet.http.HttpServletRequest;

/**
* The origin parser parses request origin (e.g. IP, user, appName) from HTTP request.
*
* @author Eric Zhao
* @since 0.2.0
*/
public interface RequestOriginParser {

/**
* Parse the origin from given HTTP request.
*
* @param request HTTP request
* @return parsed origin
*/
String parseOrigin(HttpServletRequest request);
}

+ 16
- 2
sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/callback/WebCallbackManager.java 查看文件

@@ -15,6 +15,8 @@
*/ */
package com.alibaba.csp.sentinel.adapter.servlet.callback; package com.alibaba.csp.sentinel.adapter.servlet.callback;


import com.alibaba.csp.sentinel.util.AssertUtil;

/** /**
* Registry for URL cleaner and URL block handler. * Registry for URL cleaner and URL block handler.
* *
@@ -23,15 +25,17 @@ package com.alibaba.csp.sentinel.adapter.servlet.callback;
public class WebCallbackManager { public class WebCallbackManager {


/** /**
* URL cleaner
* URL cleaner.
*/ */
private static volatile UrlCleaner urlCleaner = new DefaultUrlCleaner(); private static volatile UrlCleaner urlCleaner = new DefaultUrlCleaner();


/** /**
* URL block handler
* URL block handler.
*/ */
private static volatile UrlBlockHandler urlBlockHandler = new DefaultUrlBlockHandler(); private static volatile UrlBlockHandler urlBlockHandler = new DefaultUrlBlockHandler();


private static volatile RequestOriginParser requestOriginParser = null;

public static UrlCleaner getUrlCleaner() { public static UrlCleaner getUrlCleaner() {
return urlCleaner; return urlCleaner;
} }
@@ -45,6 +49,16 @@ public class WebCallbackManager {
} }


public static void setUrlBlockHandler(UrlBlockHandler urlBlockHandler) { public static void setUrlBlockHandler(UrlBlockHandler urlBlockHandler) {
AssertUtil.isTrue(urlBlockHandler != null, "URL block handler should not be null");
WebCallbackManager.urlBlockHandler = urlBlockHandler; WebCallbackManager.urlBlockHandler = urlBlockHandler;
} }

public static RequestOriginParser getRequestOriginParser() {
return requestOriginParser;
}

public static void setRequestOriginParser(
RequestOriginParser requestOriginParser) {
WebCallbackManager.requestOriginParser = requestOriginParser;
}
} }

正在加载...
取消
保存