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]
