Repository navigation
[fix][broker][branch-4.2] Fix admin API HTTP 400 FAIL_ON_TRAILING_TOKENS when a broker interceptor is loaded - #26223
Merged
lhotari merged 1 commit intoJul 22, 2026
Conversation
…ENS when a broker interceptor is loaded Copy RequestWrapper from master, where this fix shipped as part of apache#25912: - buffer the request body lazily on first access, bounded by Content-Length, reading raw bytes without a charset round-trip - cache a single stable ServletInputStream across getInputStream() calls (Servlet contract) so a reader that re-fetches the stream after EOF cannot re-read the body from the first byte, which surfaced as Jackson FAIL_ON_TRAILING_TOKENS (HTTP 400) on admin POST/PUT requests whenever a broker interceptor NAR is loaded Fixes apache#26185
2 of 3 tasks
sandeep-ctds
pushed a commit
to datastax/pulsar
that referenced
this pull request
Jul 31, 2026
…ENS when a broker interceptor is loaded (apache#26223) (cherry picked from commit 7a172ad)
nodece
pushed a commit
to ascentstream/pulsar
that referenced
this pull request
Aug 28, 2026
…ENS when a broker interceptor is loaded (apache#26223) (cherry picked from commit 7a172ad)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #26185
Motivation
When any broker interceptor NAR is loaded,
WebServiceregistersPreInterceptFilter, which wraps every incoming HTTP request inRequestWrapperso the body can be read multiple times. Thebranch-4.2RequestWrapper:InputStreamReader/charset round-trip, andServletInputStreamfor everygetInputStream()call, withisFinished()hardcoded tofalse.Jersey's Jackson provider enables
DeserializationFeature.FAIL_ON_TRAILING_TOKENSunconditionally (viaJaxRSFeature.READ_FULL_STREAM, default since jackson-jaxrs-providers 2.15). When a reader re-fetches the input stream after reaching EOF, the fresh stream replays the body from the first byte again, which surfaces as:on admin POST/PUT requests with a JSON body (reset cursor, set retention, bookie racks-info, etc.) whenever a broker interceptor is loaded. See the detailed root-cause analysis in #26185; the reporters confirmed that applying the
masterversion ofRequestWrapperto a 4.0.12 broker resolves the failures while the interceptor stays loaded.Independently of the replay bug, the constructor's charset round-trip is a latent body-corruption risk (it is not what triggered the 400s in #26185 — the reporters verified the round-trip is byte-for-byte lossless for their plain-ASCII JSON): it decodes the raw body with the JVM's default charset and re-encodes it with that same charset, ignoring the charset declared by the request. Concretely:
US-ASCIIunder aPOSIX/Clocale), and on JDK 18+ via-Dfile.encodingoverrides — a UTF-8 JSON body containing non-ASCII characters (unicode values in policies, subscription properties, etc.) can be silently corrupted: undecodable bytes are replaced withU+FFFD/?before the body reaches Jersey.Content-Length, which the wrapper does not override.The
masterimplementation eliminates this entire class of problems by buffering the raw bytes with no decode/re-encode step.masteralready contains the fixedRequestWrapper— the change shipped as part of the PIP-472 jakarta migration (#25912) — so no master-side change is needed; this PR brings the same code tobranch-4.2.Modifications
Copy
RequestWrapperfrommasterverbatim, withjakarta.servletimports mapped back tojavax.servlet(the only adaptation):Content-Length, reading raw bytes without a charset round-trip — this also removes the charset-dependent body-corruption risk described in the motivation. An interceptor that never reads the body (the common case) no longer causes the body to be buffered at all.ServletInputStreamacrossgetInputStream()calls (per the Servlet contract), with a workingisFinished(), so an EOF'd stream can no longer be replayed from the start.getBody()now declaresthrows IOException, matchingmaster. This is binary-compatible for existing compiled interceptor NARs.Verifying this change
This change is already covered by existing tests, such as
BrokerInterceptorTest(admin API calls with JSON bodies while interceptors are loaded, e.g.testWebserviceRequest) andInterceptFilterOutTest. The fix itself was validated by the issue reporters against a live 4.0.12 broker with an interceptor NAR loaded (see #26185).Does this pull request potentially affect one of the following parts:
If the box was checked, please highlight the changes