Skip to content

WW-5723 Bound the request body read in the REST plugin (6.x) - #1913

Open
lukaszlenart wants to merge 1 commit into
support/struts-6-x-xfrom
WW-5723-rest-body-limit-6x
Open

WW-5723 Bound the request body read in the REST plugin (6.x)#1913
lukaszlenart wants to merge 1 commit into
support/struts-6-x-xfrom
WW-5723-rest-body-limit-6x

Conversation

@lukaszlenart

Copy link
Copy Markdown
Member

Fixes WW-5723

6.x port of #1912. 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 on the 6.x line.

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.
  • The handler 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.
  • The getContentLength() > 0 gate is unchanged.

Differences from the main-line change

None in behaviour. The setter, the intercept() try/catch and post-call check, the BoundedReader and the exception class are identical to #1912. The 6.x interceptor has no @StrutsParameter authorization paths, so the change is smaller here: a single handler.toObject(...) call is wrapped rather than three.

The design notes in #1912 apply unchanged — bound the read rather than the header, lazy rather than buffered so no-op handlers leave the body untouched, one exception type regardless of which handler wrapped the reader's failure, and fail-closed when a handler swallows it.

Tests

ContentTypeInterceptorTest gains the same ten tests as #1912: over-limit body rejected before the action runs, body exactly at the limit passed in full, over-limit body not read to the end, blank / non-numeric / sub-1 configuration keeping the default, a handler that ignores the reader leaving the body unread, a handler that swallows the reader's failure still being rejected, a handler failure under the limit propagating as the same object, and skip() counting against the limit.

The two existing encoding tests asserted the handler received an InputStreamReader; they now assert the decoded content, with the ASCII case changed to ISO-8859-1 so the assertion discriminates.

REST plugin suite: 90 tests, 0 failures.

🤖 Generated with Claude Code

…ptor

6.x port of the main-line change. The REST plugin 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. Apply the same limit here.

Add struts.rest.content.maxLength (default 2097152, matching the JSON
plugin) as a framework constant injected into the interceptor. Blank,
non-numeric or sub-1 values are ignored with a warning and the default
kept. No upper cap: nothing is pre-allocated, so a large value costs
nothing until a body that size arrives.

The bound is enforced on the read itself: the handler receives a
FilterReader that counts characters and fails once the limit is
passed. Reading lazily means handlers that never touch the reader
leave the body untouched for the action, exactly as before. Handlers
wrap the reader's failure in their own types, so intercept() consults
the reader's flag after the call and throws
RequestBodyTooLargeException regardless of what propagated; a handler
that swallows the failure still fails closed on the normal-return
check, and the action is never invoked.

The getContentLength() > 0 gate is unchanged. Two existing tests that
asserted the handler received an InputStreamReader now assert the
decoded content instead; the ASCII case becomes ISO-8859-1 so the
assertion discriminates between honouring the request charset and
ignoring it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lukaszlenart
lukaszlenart marked this pull request as ready for review September 11, 2026 12:23
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant