diff --git a/core/src/main/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptor.java index c0afca1c31..4d033d338d 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptor.java @@ -90,7 +90,8 @@ public String intercept(ActionInvocation invocation) throws Exception { invocation.getProxy().getMethod(), AllowedHttpMethod.class.getSimpleName(), request.getMethod()); return doIntercept(invocation, method); } - } else if (AnnotationUtils.isAnnotatedBy(action.getClass(), HTTP_METHOD_ANNOTATIONS)) { + } + if (AnnotationUtils.isAnnotatedBy(action.getClass(), HTTP_METHOD_ANNOTATIONS)) { LOG.debug("Action: {} annotated with: {}, checking if request: {} meets allowed methods!", action, AllowedHttpMethod.class.getSimpleName(), request.getMethod()); return doIntercept(invocation, action.getClass()); diff --git a/core/src/test/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptorTest.java index f68b01df3f..edbf565542 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptorTest.java @@ -19,13 +19,17 @@ package org.apache.struts2.interceptor.httpmethod; import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.mock.MockActionInvocation; import com.opensymphony.xwork2.mock.MockActionProxy; import org.apache.struts2.HttpMethodsTestAction; import org.apache.struts2.StrutsInternalTestCase; import org.apache.struts2.TestAction; +import org.apache.struts2.config.StrutsXmlConfigurationProvider; import org.springframework.mock.web.MockHttpServletRequest; +import java.util.Map; + public class HttpMethodInterceptorTest extends StrutsInternalTestCase { private HttpMethodInterceptor interceptor; @@ -254,6 +258,73 @@ public void testWildcardResolvedMethodWithPostAnnotationAllowsPost() throws Exce assertEquals(HttpMethod.POST, action.getHttpMethod()); } + /** + * Regression for wildcard-resolved methods with no method-level HTTP annotation: + * a class-level {@code @AllowedHttpMethod(POST)} must still cause GET to be rejected. + * Previously the interceptor's {@code if/else-if} structure made the class-level + * branch unreachable when {@code isMethodSpecified()=true} and the resolved method + * carried no annotation of its own. + */ + public void testWildcardResolvedUnannotatedMethodRespectsClassLevelAnnotation() throws Exception { + HttpMethodsTestAction action = new HttpMethodsTestAction(); + prepareActionInvocation(action); + actionProxy.setMethod("execute"); + actionProxy.setMethodSpecified(true); + + prepareRequest("get"); + + String resultName = interceptor.intercept(invocation); + + assertEquals("bad-request", resultName); + } + + /** + * Counterpart to the above: POST against a wildcard-resolved unannotated method must succeed + * when the class allows POST via {@code @AllowedHttpMethod(POST)}. + */ + public void testWildcardResolvedUnannotatedMethodAllowsPostWithClassLevelAnnotation() throws Exception { + HttpMethodsTestAction action = new HttpMethodsTestAction(); + prepareActionInvocation(action); + actionProxy.setMethod("execute"); + actionProxy.setMethodSpecified(true); + invocation.setResultCode("success"); + + prepareRequest("post"); + + String resultName = interceptor.intercept(invocation); + + assertEquals("success", resultName); + } + + /** + * Exercises the full wildcard resolution path through a real {@link com.opensymphony.xwork2.DefaultActionProxy}. + *
+ * Config (from xwork-test-allowed-methods.xml):
+ * {@code