[
https://issues.apache.org/jira/browse/WW-5535?focusedWorklogId=1021157&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1021157
]
ASF GitHub Bot logged work on WW-5535:
--------------------------------------
Author: ASF GitHub Bot
Created on: 20/May/26 06:16
Start Date: 20/May/26 06:16
Worklog Time Spent: 10m
Work Description: lukaszlenart opened a new pull request, #1693:
URL: https://github.com/apache/struts/pull/1693
## Summary
Backports the [#1690](https://github.com/apache/struts/pull/1690) fix to the
6.x line.
The WW-5535 fix in #1593 made `DefaultActionProxy.resolveMethod()` report
`isMethodSpecified()=true` for wildcard-resolved methods. That interacts with
`HttpMethodInterceptor`'s `if/else-if` so the class-level annotation branch
becomes unreachable when the resolved method carries no method-level annotation:
\`\`\`java
if (invocation.getProxy().isMethodSpecified()) {
Method method =
action.getClass().getMethod(invocation.getProxy().getMethod());
if (AnnotationUtils.isAnnotatedBy(method, HTTP_METHOD_ANNOTATIONS)) {
return doIntercept(invocation, method);
}
// unannotated method falls through silently
} else if (AnnotationUtils.isAnnotatedBy(action.getClass(),
HTTP_METHOD_ANNOTATIONS)) {
return doIntercept(invocation, action.getClass()); // never reached
}
return invocation.invoke();
\`\`\`
**Affected scenario:**
\`\`\`java
@HttpPost // intends to restrict the whole action to POST
public class OrderAction extends ActionSupport {
public String create() { ... } // no method-level annotation
}
\`\`\`
\`\`\`xml
<action name=\"order-*\" class=\"com.example.OrderAction\" method=\"{1}\">
\`\`\`
`GET /order-create` resolves \`create()\` via wildcard,
\`isMethodSpecified()=true\`, method has no annotation, the \`else-if\` never
evaluates, and the class-level \`@HttpPost\` is ignored.
## Fix
Convert \`else if\` to a standalone \`if\` so the class-level annotation
check is always evaluated as a fallback when the method carries no annotation.
Method-level annotations still take precedence (checked first, with early
return). One-line structural change.
## Tests added
Three new tests in `HttpMethodInterceptorTest`:
- `testWildcardResolvedUnannotatedMethodRespectsClassLevelAnnotation` — GET
rejected on a class annotated with `@AllowedHttpMethod(POST)` when the resolved
method is unannotated.
- `testWildcardResolvedUnannotatedMethodAllowsPostWithClassLevelAnnotation`
— POST allowed on the same configuration.
- `testWildcardResolvedExecuteRejectsGetThroughRealProxy` — integration
coverage via a real `DefaultActionProxy` against `<action name=\"Wild-*\"
method=\"{1}\">`, resolving to `ActionSupport.execute()`.
## Related
- Original issue: [WW-5535](https://issues.apache.org/jira/browse/WW-5535)
- 6.x line `DefaultActionProxy` change: #1593 (shipped in 6.9.0)
- Same fix already merged to `main`: #1690 and follow-up integration test
#1692
## Test plan
- [x] \`./mvnw -pl core test -Dtest=HttpMethodInterceptorTest
-DskipAssembly\` — 16/16 pass (13 pre-existing + 3 new)
- [ ] CI green
Issue Time Tracking
-------------------
Worklog Id: (was: 1021157)
Time Spent: 1.5h (was: 1h 20m)
> HttpMethodInterceptor does not work with action names using wildcards
> ---------------------------------------------------------------------
>
> Key: WW-5535
> URL: https://issues.apache.org/jira/browse/WW-5535
> Project: Struts 2
> Issue Type: Bug
> Components: Core Interceptors
> Affects Versions: 6.7.0, 7.0.0
> Reporter: Riccardo Proserpio
> Assignee: Lukasz Lenart
> Priority: Major
> Fix For: 6.9.0, 7.2.0
>
> Time Spent: 1.5h
> Remaining Estimate: 0h
>
> The ActionProxy.isMethodSpecified() method is documented as:
> {noformat}
> Gets status of the method value's initialization.
> Returns: true if the method returned by getMethod() is not a default
> initializer value.
> {noformat}
> However, the implementation in DefaultActionProxy has a different behavior:
>
> {code:java}
> private void resolveMethod() {
> // if the method is set to null, use the one from the configuration
> // if the one from the configuration is also null, use "execute"
> if (StringUtils.isEmpty(this.method)) {
> this.method = config.getMethodName();
> if (StringUtils.isEmpty(this.method)) {
> this.method = ActionConfig.DEFAULT_METHOD;
> }
> methodSpecified = false;
> }
> } {code}
> methodSpecified is set to false not only if the default value is used, but
> also \{*}if methodName is specified via config{*}.
> This method seems to have been introduced long ago as a patch for some DMI
> behavior regression: WW-3628
> The issue happens for example if you specify an action like
> {code:java}
> <action name="example-*" class="aClass" method="aMethod"/>
> {code}
> since the method value is resolved later by wildcard matching.
> The HttpMethodInterceptor uses isSpecifiedMethods to decide when to process
> the invocation:
>
> {code:java}
> if (invocation.getProxy().isMethodSpecified()) {
> Method method =
> action.getClass().getMethod(invocation.getProxy().getMethod());
> // doIntercept...
> }{code}
> thus skipping the validation for actionNames with wildcards.
> I'm not really sure if isMethodSpecified is wrong or has misleading
> documentation. I'm not even sure why the HttpMethodInterceptor should skip
> validation on the default execute methods.
> A fix might be just assessing the existence of
> invocation.getProxy().getMethod() instead on relying on isMethodSpecified,
> but before submitting a pr I'd like the opinion on the maintainers.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)