fix: fix the bugs about http-method-specify in spring-webmvc-v6x and incorrect time unit in dashboard (#3569)

* Fix the bugs mentioned in issue #3562 and #3563.
Fix the issue in the spring-webmvc-v6x-adapter where, after configuring http-method-specify:true, the prefixes for different request methods were not concatenated.
Fix incorrect time unit in the tooltip when adding a new circuit breaker rule with statistical window duration.

* Fix the bugs mentioned in issue #3562 and #3563.
Fix the issue in the spring-webmvc-v6x-adapter where, after configuring http-method-specify:true, the prefixes for different request methods were not concatenated.
Fix incorrect time unit in the tooltip when adding a new circuit breaker rule with statistical window duration.

* Fixed the issue where the original test class was affected by the concatenation of resource names after adding the logic for the HTTP prefix concatenation.

* remove mseHttpMethodSpecify field and update the unit test as suggested.

* retrigger CI
This commit is contained in:
ylnxwlp 2025-11-03 18:01:05 +08:00 committed by GitHub
parent e60f0d0eee
commit a08dc695ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 138 additions and 14 deletions

View File

@ -18,6 +18,7 @@ package com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x;
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.config.SentinelWebMvcConfig;
import com.alibaba.csp.sentinel.adapter.web.common.UrlCleaner;
import com.alibaba.csp.sentinel.util.StringUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;
@ -62,6 +63,9 @@ public class SentinelWebInterceptor extends AbstractSentinelInterceptor {
if (config.isContextPathSpecify() && request.getContextPath() != null) {
resourceName = request.getContextPath() + resourceName;
}
if (StringUtil.isNotEmpty(resourceName) && config.isHttpMethodSpecify()) {
resourceName = request.getMethod().toUpperCase() + ":" + resourceName;
}
return resourceName;
}

View File

@ -34,11 +34,6 @@ public class SentinelWebMvcConfig extends BaseWebMvcConfig {
*/
private boolean httpMethodSpecify;
/**
* Specify whether the URL resource name should contain the HTTP method prefix in MSE (e.g. {@code GET:}).
*/
private static boolean mseHttpMethodSpecify;
/**
* Specify whether unify web context(i.e. use the default context name), and is true by default.
@ -56,10 +51,6 @@ public class SentinelWebMvcConfig extends BaseWebMvcConfig {
super();
setRequestAttributeName(DEFAULT_REQUEST_ATTRIBUTE_NAME);
try {
String enable = System.getProperty("spring.cloud.mse.sentinel.web.http-method-prefix","true");
if(enable != null){
mseHttpMethodSpecify = Boolean.parseBoolean(enable);
}
String enableContextPath = System.getProperty("spring.cloud.ahas.sentinel.web.context-path", "true");
if (enableContextPath != null) {
contextPathSpecify = Boolean.parseBoolean(enableContextPath);
@ -86,10 +77,6 @@ public class SentinelWebMvcConfig extends BaseWebMvcConfig {
return this;
}
public static boolean isMseHttpMethodSpecify() {
return mseHttpMethodSpecify;
}
public boolean isWebContextUnify() {
return webContextUnify;
}

View File

@ -33,6 +33,7 @@ import com.alibaba.csp.sentinel.util.StringUtil;
import java.util.Collections;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -54,6 +55,11 @@ public class SentinelSpringMvcIntegrationTest {
@Autowired
private MockMvc mvc;
@BeforeClass
public static void disableMseHttpMethodPrefix() {
System.setProperty("spring.cloud.mse.sentinel.web.http-method-prefix", "false");
}
@Test
public void testBase() throws Exception {
String url = "/hello";

View File

@ -0,0 +1,127 @@
package com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x;
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.config.SentinelWebMvcConfig;
import com.alibaba.csp.sentinel.adapter.web.common.UrlCleaner;
import jakarta.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.web.servlet.HandlerMapping;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
/**
* The test for the resource request prefix concatenation in spring-webmvc-v6x.
*
* @author ylnxwlp
*/
public class SentinelWebInterceptorHttpMethodPrefixTest {
private SentinelWebInterceptor interceptor;
private HttpServletRequest mockRequest;
@Before
public void setUp() {
mockRequest = Mockito.mock(HttpServletRequest.class);
}
@Test
public void testGetResourceNameWithHttpMethodSpecifyEnabled() {
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
config.setHttpMethodSpecify(true);
interceptor = new SentinelWebInterceptor(config);
when(mockRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE))
.thenReturn("/test/path");
when(mockRequest.getMethod()).thenReturn("POST");
when(mockRequest.getContextPath()).thenReturn("");
String resourceName = interceptor.getResourceName(mockRequest);
assertEquals("POST:/test/path", resourceName);
}
@Test
public void testGetResourceNameWithHttpMethodSpecifyDisabled() {
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
config.setHttpMethodSpecify(false);
interceptor = new SentinelWebInterceptor(config);
when(mockRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE))
.thenReturn("/no/prefix");
when(mockRequest.getMethod()).thenReturn("DELETE");
when(mockRequest.getContextPath()).thenReturn("");
String resourceName = interceptor.getResourceName(mockRequest);
assertEquals("/no/prefix", resourceName);
}
@Test
public void testGetResourceNameEmptyResourceNameShouldReturnEmptyString() {
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
config.setHttpMethodSpecify(true);
interceptor = new SentinelWebInterceptor(config);
when(mockRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE))
.thenReturn("");
when(mockRequest.getMethod()).thenReturn("PUT");
when(mockRequest.getContextPath()).thenReturn("");
String resourceName = interceptor.getResourceName(mockRequest);
assertEquals("", resourceName);
}
@Test
public void testGetResourceNameNullResourceNameShouldReturnNull() {
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
config.setHttpMethodSpecify(true);
interceptor = new SentinelWebInterceptor(config);
when(mockRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE))
.thenReturn(null);
when(mockRequest.getMethod()).thenReturn("PATCH");
String resourceName = interceptor.getResourceName(mockRequest);
assertNull(resourceName);
}
@Test
public void testGetResourceNameWithUrlCleaner() {
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
config.setHttpMethodSpecify(true);
config.setUrlCleaner(new UrlCleaner() {
@Override
public String clean(String originUrl) {
return "/cleaned";
}
});
interceptor = new SentinelWebInterceptor(config);
when(mockRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE))
.thenReturn("/dirty/path");
when(mockRequest.getMethod()).thenReturn("GET");
when(mockRequest.getContextPath()).thenReturn("");
String resourceName = interceptor.getResourceName(mockRequest);
assertEquals("GET:/cleaned", resourceName);
}
@Test
public void testGetResourceNameWithContextPath() {
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
config.setHttpMethodSpecify(true);
config.setContextPathSpecify(true);
interceptor = new SentinelWebInterceptor(config);
when(mockRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE))
.thenReturn("/api/user");
when(mockRequest.getMethod()).thenReturn("GET");
when(mockRequest.getContextPath()).thenReturn("/myapp");
String resourceName = interceptor.getResourceName(mockRequest);
assertEquals("GET:/myapp/api/user", resourceName);
}
@Test
public void testGetResourceNameWithContextPathDisabled() {
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
config.setHttpMethodSpecify(true);
config.setContextPathSpecify(false);
interceptor = new SentinelWebInterceptor(config);
when(mockRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE))
.thenReturn("/api/user");
when(mockRequest.getMethod()).thenReturn("GET");
when(mockRequest.getContextPath()).thenReturn("/myapp");
String resourceName = interceptor.getResourceName(mockRequest);
assertEquals("GET:/api/user", resourceName);
}
}

File diff suppressed because one or more lines are too long