@@ -42,18 +42,27 @@ import com.alibaba.csp.sentinel.util.StringUtil; | |||
/*** | |||
* Servlet filter that integrates with Sentinel. | |||
* | |||
* @author zhaoyuguang | |||
* @author youji.zj | |||
* @author Eric Zhao | |||
*/ | |||
public class CommonFilter implements Filter { | |||
private 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 | |||
*/ | |||
public final static String WEB_CONTEXT_UNIFY = "WEB_CONTEXT_UNIFY"; | |||
private final static String COLON = ":"; | |||
private boolean httpMethodSpecify = false; | |||
private boolean webContextUnify = true; | |||
@Override | |||
public void init(FilterConfig filterConfig) { | |||
httpMethodSpecify = Boolean.parseBoolean(filterConfig.getInitParameter(HTTP_METHOD_SPECIFY)); | |||
if (filterConfig.getInitParameter(WEB_CONTEXT_UNIFY) != null) { | |||
webContextUnify = Boolean.parseBoolean(filterConfig.getInitParameter(WEB_CONTEXT_UNIFY)); | |||
} | |||
} | |||
@Override | |||
@@ -78,7 +87,7 @@ public class CommonFilter implements Filter { | |||
if (!StringUtil.isEmpty(target)) { | |||
// Parse the request origin using registered origin parser. | |||
String origin = parseOrigin(sRequest); | |||
ContextUtil.enter(WebServletConfig.WEB_SERVLET_CONTEXT_NAME, origin); | |||
ContextUtil.enter(webContextUnify ? WebServletConfig.WEB_SERVLET_CONTEXT_NAME : target, origin); | |||
urlEntry = SphU.entry(target, EntryType.IN); | |||
// Add method specification if necessary | |||
if (httpMethodSpecify) { | |||
@@ -19,6 +19,7 @@ import java.util.Collections; | |||
import javax.servlet.http.HttpServletRequest; | |||
import com.alibaba.csp.sentinel.Constants; | |||
import com.alibaba.csp.sentinel.adapter.servlet.callback.DefaultUrlCleaner; | |||
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser; | |||
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner; | |||
@@ -26,6 +27,8 @@ import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager; | |||
import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig; | |||
import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil; | |||
import com.alibaba.csp.sentinel.node.ClusterNode; | |||
import com.alibaba.csp.sentinel.node.EntranceNode; | |||
import com.alibaba.csp.sentinel.node.Node; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | |||
@@ -43,7 +46,7 @@ import org.springframework.test.context.junit4.SpringRunner; | |||
import org.springframework.test.web.servlet.MockMvc; | |||
import static org.junit.Assert.*; | |||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; | |||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | |||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | |||
/** | |||
@@ -76,6 +79,7 @@ public class CommonFilterTest { | |||
@Test | |||
public void testCommonFilterMiscellaneous() throws Exception { | |||
Constants.ROOT.removeChildList(); | |||
String url = "/hello"; | |||
this.mvc.perform(get(url)) | |||
.andExpect(status().isOk()) | |||
@@ -85,6 +89,17 @@ public class CommonFilterTest { | |||
assertNotNull(cn); | |||
assertEquals(1, cn.passQps(), 0.01); | |||
String context = ""; | |||
for (Node n : Constants.ROOT.getChildList()) { | |||
if (n instanceof EntranceNode) { | |||
String id = ((EntranceNode) n).getId().getName(); | |||
if (url.equals(id)) { | |||
context = ((EntranceNode) n).getId().getName(); | |||
} | |||
} | |||
} | |||
assertEquals("", context); | |||
testCommonBlockAndRedirectBlockPage(url, cn); | |||
// Test for url cleaner. | |||
@@ -0,0 +1,100 @@ | |||
/* | |||
* 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.servletcontext; | |||
import com.alibaba.csp.sentinel.Constants; | |||
import com.alibaba.csp.sentinel.node.ClusterNode; | |||
import com.alibaba.csp.sentinel.node.EntranceNode; | |||
import com.alibaba.csp.sentinel.node.Node; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | |||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; | |||
import com.alibaba.csp.sentinel.util.StringUtil; | |||
import org.junit.After; | |||
import org.junit.Test; | |||
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.test.context.junit4.SpringRunner; | |||
import org.springframework.test.web.servlet.MockMvc; | |||
import java.util.Collections; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | |||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; | |||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@RunWith(SpringRunner.class) | |||
@SpringBootTest(classes = TestContextApplication.class, | |||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | |||
@AutoConfigureMockMvc | |||
public class CommonFilterContextTest { | |||
private static final String HELLO_STR = "Hello!"; | |||
@Autowired | |||
private MockMvc mvc; | |||
private void configureRulesFor(String resource, int count) { | |||
configureRulesFor(resource, count, "default"); | |||
} | |||
private void configureRulesFor(String resource, int count, String limitApp) { | |||
FlowRule rule = new FlowRule() | |||
.setCount(count) | |||
.setGrade(RuleConstant.FLOW_GRADE_QPS); | |||
rule.setResource(resource); | |||
if (StringUtil.isNotBlank(limitApp)) { | |||
rule.setLimitApp(limitApp); | |||
} | |||
FlowRuleManager.loadRules(Collections.singletonList(rule)); | |||
} | |||
@Test | |||
public void testCommonFilterMiscellaneous() throws Exception { | |||
String url = "/hello"; | |||
this.mvc.perform(get(url)) | |||
.andExpect(status().isOk()) | |||
.andExpect(content().string(HELLO_STR)); | |||
ClusterNode cn = ClusterBuilderSlot.getClusterNode(url); | |||
assertNotNull(cn); | |||
assertEquals(1, cn.passQps(), 0.01); | |||
String context = ""; | |||
for (Node n : Constants.ROOT.getChildList()) { | |||
if (n instanceof EntranceNode) { | |||
String id = ((EntranceNode) n).getId().getName(); | |||
if (url.equals(id)) { | |||
context = ((EntranceNode) n).getId().getName(); | |||
} | |||
} | |||
} | |||
assertEquals(url, context); | |||
} | |||
@After | |||
public void cleanUp() { | |||
FlowRuleManager.loadRules(null); | |||
ClusterBuilderSlot.resetClusterNodes(); | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
/* | |||
* 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.servletcontext; | |||
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; | |||
import org.springframework.boot.web.servlet.FilterRegistrationBean; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@Configuration | |||
public class FilterContextConfig { | |||
@Bean | |||
public FilterRegistrationBean sentinelFilterRegistration() { | |||
FilterRegistrationBean registration = new FilterRegistrationBean(); | |||
registration.setFilter(new CommonFilter()); | |||
registration.addUrlPatterns("/*"); | |||
registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false"); | |||
registration.setName("sentinelFilter"); | |||
registration.setOrder(1); | |||
return registration; | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* 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.servletcontext; | |||
import org.springframework.boot.SpringApplication; | |||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@SpringBootApplication | |||
public class TestContextApplication { | |||
public static void main(String[] args) { | |||
SpringApplication.run(TestContextApplication.class, args); | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
/* | |||
* 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.servletcontext; | |||
import org.springframework.web.bind.annotation.GetMapping; | |||
import org.springframework.web.bind.annotation.RestController; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@RestController | |||
public class TestContextController { | |||
@GetMapping("/hello") | |||
public String apiHello() { | |||
return "Hello!"; | |||
} | |||
} |