This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts-site.git


The following commit(s) were added to refs/heads/main by this push:
     new 23fb2d5bb0 WW-5844 docs: describe httpMethod enforcement in the plugin 
stacks and annotation resolution (#372)
23fb2d5bb0 is described below

commit 23fb2d5bb03cd8e92293b3f8b7bca0b630a5b230
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sun Nov 8 15:51:31 2026 +0100

    WW-5844 docs: describe httpMethod enforcement in the plugin stacks and 
annotation resolution (#372)
    
    restDefaultStack and beanValidationDefaultStack now contain the httpMethod
    interceptor, so the action-configuration page lists them with the core
    stacks and both plugin pages carry a "Since 7.5.0" paragraph.
    
    The HTTP Methods section gains the resolution rules for method-level and
    class-level annotations across the class and interface hierarchy, and the
    REST page explains that the interceptor checks the request method itself,
    so update() and destroy() reached from a POST form with _method need
    @HttpPost as well.
    
    Co-authored-by: Claude Mythos 5.1 <[email protected]>
---
 source/core-developers/action-configuration.md | 21 ++++++++++++++--
 source/plugins/bean-validation/index.md        |  5 ++++
 source/plugins/rest/index.md                   | 35 ++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/source/core-developers/action-configuration.md 
b/source/core-developers/action-configuration.md
index 9ae376b4a4..f2a150dc5e 100644
--- a/source/core-developers/action-configuration.md
+++ b/source/core-developers/action-configuration.md
@@ -368,13 +368,30 @@ The attribute requires the 7.5 DTD. An unknown method 
name, e.g. `http-method="f
 Actions matched by a wildcard or regex pattern keep the restriction declared 
on the pattern.
 
 The restriction is enforced by the `httpMethod` interceptor, which is part of 
`basicStack`, `defaultStack`,
-`paramsPrepareParamsStack` and the stacks built on them. If an action declares 
`http-method` but its interceptors do
-not include `httpMethod`, a warning is logged at startup and the restriction 
is not enforced.
+`paramsPrepareParamsStack` and the stacks built on them, as well as the [REST 
Plugin](../plugins/rest)'s
+`restDefaultStack` and the [Bean Validation 
Plugin](../plugins/bean-validation)'s `beanValidationDefaultStack`.
+If an action declares `http-method` but its interceptors do not include 
`httpMethod`, a warning is logged at startup
+and the restriction is not enforced.
 
 The same interceptor enforces the `@AllowedHttpMethod`, `@HttpGet`, 
`@HttpPost`, `@HttpPut`, `@HttpDelete` and
 `@HttpGetOrPost` annotations on the action class or method. When both the 
attribute and an annotation apply,
 the request method must be allowed by both.
 
+Annotations are resolved as follows:
+
+- A method-level annotation applies to the action method the request invokes, 
including the implicit `execute()`
+  when the mapping names no method.
+- An annotation on the invoked method itself takes precedence. Otherwise the 
interceptor looks for the same method
+  declared on a superclass or on an implemented interface, including 
interfaces those extend, and uses the first
+  annotated declaration it finds. Only public instance methods count, so a 
private, static or package-private
+  method of the same name on a parent class carries no restriction.
+- Class-level annotations are consulted only when no method-level annotation 
applies. They are looked up on the
+  action class, its superclasses and their interfaces in the same way.
+
+The interceptor compares the HTTP method of the request as the container 
reports it. The `_method` parameter the
+REST plugin uses to route a POST form to `update` or `destroy` does not change 
it, see
+[HTTP method restrictions in 
restDefaultStack](../plugins/rest#http-method-restrictions-in-restdefaultstack).
+
 ### Rejected requests
 
 When the request method is not allowed, the interceptor returns the 
`bad-request` result if it can be resolved:
diff --git a/source/plugins/bean-validation/index.md 
b/source/plugins/bean-validation/index.md
index 872687a9b7..669f044398 100644
--- a/source/plugins/bean-validation/index.md
+++ b/source/plugins/bean-validation/index.md
@@ -69,6 +69,11 @@ returns the result code `403`, which needs a matching 
(global) result to render
 `fetchMetadata.disabled` to `true` on the stack for actions that must accept 
such requests.
 {:.alert .alert-warning}
 
+Since Struts 7.5.0 `beanValidationDefaultStack` also contains the `httpMethod` 
interceptor, placed after
+`servletConfig` as in core's `defaultStack` 
([WW-5844](https://issues.apache.org/jira/browse/WW-5844)). The
+`http-method` attribute and the `@HttpGet`, `@HttpPost` and related 
annotations are enforced for every package
+extending `struts-bean-validation`, see [HTTP 
Methods](/core-developers/action-configuration#http-methods).
+
 Here is another example that shows how you can combine bean-validation with 
other plugins by configuring your own
 Interceptor-Stack (note: this is just a very short example. In a real app you 
should take more care about your stack).
 You can combine bean validation with classic struts validation (or disable 
either) by putting the according interceptors
diff --git a/source/plugins/rest/index.md b/source/plugins/rest/index.md
index 4da7eb1a0d..741cb93c16 100644
--- a/source/plugins/rest/index.md
+++ b/source/plugins/rest/index.md
@@ -82,6 +82,8 @@ The following URL's will invoke its methods:
 - `DELETE: /movies/Thrillers`  => method=**destroy**, id=**Thrillers**
 
 To simulate the HTTP methods PUT and DELETE, since they aren't supported by 
HTML, the HTTP parameter `_method` will be used.
+It changes only which method the mapper selects; the request is still a POST 
for the `httpMethod` interceptor, see
+[HTTP method restrictions in 
restDefaultStack](#http-method-restrictions-in-restdefaultstack).
 
 Or, expressed as a table:
 
@@ -394,6 +396,39 @@ check for the stack serving it:
 
 Requests sent by non-browser clients carry no `Sec-Fetch-Site` header and are 
not affected.
 
+### HTTP method restrictions in restDefaultStack
+
+Since Struts 7.5.0 `restDefaultStack` contains the `httpMethod` interceptor, 
placed after `servletConfig` as in core's
+`defaultStack` ([WW-5844](https://issues.apache.org/jira/browse/WW-5844)). The 
`http-method` attribute and the
+`@AllowedHttpMethod`, `@HttpGet`, `@HttpPost`, `@HttpPut`, `@HttpDelete` and 
`@HttpGetOrPost` annotations are enforced
+for every package extending `rest-default`, see [HTTP 
Methods](/core-developers/action-configuration#http-methods).
+
+The interceptor checks the HTTP method of the request itself, not the 
`_method` parameter. A POST form carrying
+`_method=put` or `_method=delete` is routed to `update` or `destroy`, but the 
request stays a POST, so those methods
+must allow POST. `@HttpPut` and `@HttpDelete` alone accept only real PUT and 
DELETE requests, as sent by `fetch()`/XHR
+or non-browser clients; combine them with `@HttpPost` when the same method 
also serves HTML forms:
+{:.alert .alert-warning}
+
+```java
+public class OrdersController implements ModelDriven<Order> {
+
+    @HttpPost
+    @HttpPut
+    public HttpHeaders update() {
+        ...
+    }
+
+    @HttpPost
+    @HttpDelete
+    public HttpHeaders destroy() {
+        ...
+    }
+}
+```
+
+An XML `http-method` restriction on such an action must likewise include 
`post`. A request whose method is not
+allowed receives `405 Method Not Allowed` with an `Allow` header, or the 
`bad-request` result when one is mapped.
+
 ## Resources
 
 + [http://www.b-simple.de/documents](http://www.b-simple.de/documents) - Short 
RESTful Rails tutorial (PDF, multiple languages)

Reply via email to