diff --git a/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java b/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java index aedf1303..23daf283 100755 --- a/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java +++ b/sentinel-adapter/sentinel-web-servlet/src/main/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java @@ -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) { diff --git a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilterTest.java b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilterTest.java index b271142a..58574caa 100644 --- a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilterTest.java +++ b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servlet/CommonFilterTest.java @@ -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. diff --git a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/CommonFilterContextTest.java b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/CommonFilterContextTest.java new file mode 100644 index 00000000..10c215d9 --- /dev/null +++ b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/CommonFilterContextTest.java @@ -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(); + } +} diff --git a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/FilterContextConfig.java b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/FilterContextConfig.java new file mode 100644 index 00000000..aff3a5db --- /dev/null +++ b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/FilterContextConfig.java @@ -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; + } +} diff --git a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/TestContextApplication.java b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/TestContextApplication.java new file mode 100644 index 00000000..fbf16c6e --- /dev/null +++ b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/TestContextApplication.java @@ -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); + } +} diff --git a/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/TestContextController.java b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/TestContextController.java new file mode 100644 index 00000000..39fc81a1 --- /dev/null +++ b/sentinel-adapter/sentinel-web-servlet/src/test/java/com/alibaba/csp/sentinel/adapter/servletcontext/TestContextController.java @@ -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!"; + } +}