lukaszlenart opened a new pull request, #1912:
URL: https://github.com/apache/struts/pull/1912

   Fixes [WW-5723](https://issues.apache.org/jira/browse/WW-5723)
   
   `ContentTypeInterceptor` handed `request.getInputStream()` to the 
content-type handler with no length limit, while the JSON plugin bounds the 
same read with `struts.json.maxLength` and `CspReportAction` with 
`struts.csp.report.maxSize`. This applies the same limit to the REST plugin.
   
   ## What changes
   
   - New constant `struts.rest.content.maxLength`, default `2097152` (matching 
the JSON plugin), declared in the plugin's `struts-plugin.xml` and injected 
into `ContentTypeInterceptor` via `@Inject(required = false)`. Blank, 
non-numeric or sub-1 values are ignored with a warning and the default kept, as 
`CspReportAction` does.
   - The handler now receives a `BoundedReader` — a `FilterReader` that counts 
characters and fails once the limit is passed. On overflow the interceptor 
throws the new `RequestBodyTooLargeException` (a `StrutsException`), and the 
action is never invoked.
   - `applyRequestBody` and the two authorization paths take a `Reader` instead 
of an `InputStreamReader`; `ContentTypeHandler.toObject` already declared 
`Reader`.
   - The `getContentLength() > 0` gate is unchanged.
   
   ## Design notes
   
   **Bound the read, not the header.** The limit is enforced on characters 
actually consumed, so it holds regardless of the declared `Content-Length`.
   
   **Lazy rather than buffered.** An earlier shape read the body into a buffer 
before calling the handler. That drained the stream even for handlers that 
never read it (`HtmlHandler`, `FormUrlEncodedHandler`, 
`MultipartFormDataHandler`), which would have broken an action reading the raw 
body itself behind one of them. Wrapping the reader instead means those 
handlers leave the body untouched exactly as before, and Jackson keeps 
streaming rather than parsing from a buffer.
   
   **One exception type regardless of handler.** Handlers wrap the reader's 
`IOException` in their own types — Jackson passes it through, XStream wraps in 
`StreamException`, Juneau in `ParseException`. Rather than depend on what 
propagates, `intercept()` consults the reader's flag after the call and throws 
`RequestBodyTooLargeException` either way. A handler that swallows the failure 
still fails closed: the flag is checked on the normal return path too. The 
dedicated type lets an application map this to 413 via `<exception-mapping>` 
without catching every `StrutsException`.
   
   **Framework constant, not an action property.** Matches both siblings and 
behaves identically on 6.x, where interceptor ordering differs.
   
   **No upper cap on the configured value.** `CspReportAction` caps because it 
pre-allocates a buffer of that size; nothing is pre-allocated here, so a large 
value costs nothing until a body that size arrives.
   
   **Authorization context.** The read now happens inside 
`applyWithAuthorizationContext`'s bind/unbind window. 
`ParameterAuthorizationContext.unbind()` removes all three thread-locals 
unconditionally in `finally`, and the Jackson handlers clear their dynamic-key 
scope in their own `finally`, so an abort mid-parse leaves nothing on the 
thread. Properties bound before the limit trips have each passed authorization 
individually — the outcome is the same as a malformed body truncated at that 
offset, and `invoke()` does not run.
   
   ## Tests
   
   Six new tests in `ContentTypeInterceptorTest`: over-limit body rejected 
before the action runs, body exactly at the limit passed in full, over-limit 
body not read to the end, non-numeric and sub-1 configuration keep the default, 
and a handler that ignores the reader leaves the body unread.
   
   Two existing tests asserted the handler received an `InputStreamReader` and 
read its encoding from it, i.e. an implementation type. They now assert the 
decoded content, and the ASCII case becomes ISO-8859-1 so the assertion 
discriminates between honouring the request charset and ignoring it — an ASCII 
body decodes the same under any charset.
   
   REST plugin suite: 155 tests, 0 failures.
   
   ## Follow-ups
   
   - 6.x port under the same ticket, once this lands.
   - Document `struts.rest.content.maxLength` on the REST plugin page in 
struts-site.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   
   https://claude.ai/code/session_01QmdzKqRSSMyCsdgnv2ubiy
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to