davsclaus opened a new pull request, #28911:
URL: https://github.com/apache/camel/pull/28911

   Fixes [CAMEL-26138](https://issues.apache.org/jira/browse/CAMEL-26138).
   
   The issue lists three bugs of `DefaultHttpBinding` / `HttpMessage` in 
camel-http-common (shared by camel-jetty and camel-servlet). Two are fixed 
here. The third needs a decision, see below.
   
   ### 1. With `chunked=true` a Map, List, POJO or number reply is a 200 with 
an empty body
   
   **What was wrong:** `doWriteDirectResponse` took 
`message.getBody(InputStream.class)` for a chunked reply. There is no converter 
from a Map, List, POJO or number to `InputStream`, so `MessageSupport.getBody` 
falls back to converting the message itself. For an `HttpMessage` that is 
`HttpConverter.toInputStream(HttpMessage)`: the request stream, which is 
already read. The reply was a 200 with an empty body and no error. With 
`chunked=false` the same body was written as its String form.
   
   This only happens when the body is set on the `HttpMessage` itself (a 
processor, a bean). The `setBody` EIP replaces a specialized message with a 
plain `DefaultMessage`, so it never hit the bug; that is why 
`HttpReturnDataNotInputStreamConvertableTest` passed.
   
   **What changed:** the chunked path converts only the body 
(`typeConverter.convertTo(InputStream.class, exchange, body)`). A body that is 
not convertable as a stream falls through to the existing String fallback, the 
same as the non-chunked path. Streams, byte arrays, String bodies and the 
charset handling of CAMEL-25316 are unchanged.
   
   ### 3. With `disableStreamCache=true` a form POST loses its body
   
   **What was wrong:** `readFormUrlEncodedBody` reads the body as a String to 
map the form fields to headers. With `disableStreamCache=true` the body is the 
raw request stream (or reader), so it was consumed: servlet (Undertow) failed 
with 500 "UT010029: Stream is closed". On jetty the stream is already consumed 
earlier: `readHeaders` calls `request.getParameterNames()`, and Jetty then 
reads the form body to parse the parameters, so the route got an empty body.
   
   **What changed:** `readBody`, which runs before `readHeaders`, reads such a 
form body as text and keeps it as the body. This applies only when the body is 
a raw stream or reader (not a `StreamCache`), the request is a form POST, and 
its fields are mapped to headers (`mapHttpMessageHeaders`, 
`mapHttpMessageFormUrlEncodedBody`, no `CamelSkipWwwFormUrlEncoding`, so a 
bridge endpoint is not affected). The form POST check moved into a small helper 
shared with `readFormUrlEncodedBody`. With stream caching on (the default) 
nothing changes.
   
   ### Tests
   
   - `HttpChunkedNonStreamBodyAndFormStreamTest` (camel-jetty) and 
`ServletChunkedNonStreamBodyAndFormStreamTest` (camel-servlet): chunked Map, 
List, number (and POJO for servlet) replies to GET and POST, a non-chunked Map 
reply, and a form POST with `disableStreamCache=true`. Before the fix 5 of 6 
(jetty) and 6 of 7 (servlet) failed (empty bodies, the jetty form test got an 
empty body, the servlet one a 500). All pass after it.
   - Full suites of camel-http-common, camel-servlet and camel-jetty pass 
against the changed camel-http-common.
   
   No options, headers or docs change, so there are no generated files and no 
upgrade guide entry: both fixes turn an empty or failed reply into the expected 
one.
   
   ### 2. `mapHttpMessageBody=false` still maps the body: NOT changed, needs a 
decision
   
   `readRequest` skips `readBody` when `mapHttpMessageBody=false`, and 
`HttpMessage.createBody` still reads the body lazily when the route asks for 
it. The issue proposes to return null from `createBody` instead.
   
   I did not do that. The option was added by CAMEL-9833 for proxy routes: 
"route the request to another endpoint without the need to access the 
body/headers", and "in `DefaultHttpBinding#readRequest` we should not force 
loading the message body". So the intent was "do not read the body eagerly", 
and the lazy read is what lets a proxy route still forward the body to the 
backend. Returning null would send an empty body in exactly that use case. What 
the option does today: no eager read, no multipart attachments, no Java 
serialized object, no form fields as headers.
   
   Options:
   - (a) keep the behaviour and fix the option description ("the body is not 
read eagerly, it is read when the route first accesses it, and no attachments 
or form fields are mapped"). Recommended.
   - (b) return null from `createBody`, as proposed in the issue: a behaviour 
change for proxy routes that needs an upgrade guide entry.
   
   _Claude Code on behalf of Claus Ibsen (davsclaus)_
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
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