shashank created CAMEL-25305:
--------------------------------
Summary: camel-netty-http - a String body is sent in the exchange
charset, not in the charset the Content-Type declares, and the request charset
parameter is only recognized in lower case
Key: CAMEL-25305
URL: https://issues.apache.org/jira/browse/CAMEL-25305
Project: Camel
Issue Type: Bug
Components: camel-netty-http
Reporter: shashank
h3. 1. String body
{{DefaultNettyHttpBinding}} converts a body that is not a {{ByteBuf}} with
{{message.getBody(ByteBuf.class)}}, which for a {{String}} uses the exchange
charset ({{CamelCharsetName}}, UTF-8 when not set), and copies the
{{Content-Type}} header unchanged. So a route that answers with {{text/plain;
charset=ISO-8859-1}} and the text {{Grüße aus Köln}} sends 17 UTF-8 bytes
labelled ISO-8859-1, and a client that honours the header reads {{Grüße aus
Köln}}. The producer does the same for the request body. Bytes, streams and
{{ByteBuf}} bodies are not affected, and neither are messages whose declared
charset is the exchange charset.
camel-platform-http-vertx (CAMEL-25217) and camel-undertow (CAMEL-25248) were
fixed for this in 4.23; camel-http uses the {{Content-Type}} charset for a
String entity, and the servlet binding sets the response character encoding so
the header matches the bytes.
h3. 2. Charset parameter in upper case
The consumer ({{HttpServerChannelHandler}}) and
{{NettyHttpConverter.toString(FullHttpResponse)}} find the request charset with
the deprecated {{HttpUtil.getCharsetFromContentType}}, i.e.
{{contentType.indexOf("charset=")}}. Parameter names are case-insensitive (RFC
9110, section 5.6.6): with {{Content-Type: text/plain; Charset=ISO-8859-1}} no
{{CamelCharsetName}} is set and the body is decoded as UTF-8 ({{Gr��e aus
K�ln}}).
h3. Reproduction
New {{NettyHttpStringBodyCharsetTest}} (JDK HTTP client against a netty-http
consumer): response of a route that sets {{text/plain; charset=ISO-8859-1}}: 17
bytes instead of 14; request with {{Charset=ISO-8859-1}}: the route reads
mojibake; producer request with {{charset=ISO-8859-1}}: the server receives 17
bytes instead of 14. Control: a response without a charset is UTF-8 (passes on
main). A unit test of the new charset lookup pins that a {{Content-Type}}
without a charset parameter gives no charset (not a UTF-8 default).
h3. Proposed fix
* A String body is converted with the charset the {{Content-Type}} declares
when there is one (and it is supported); otherwise as before.
* A new {{NettyHttpHelper.getCharsetFromContentType}} finds the {{charset}}
parameter case-insensitively (no UTF-8 default, so no {{CamelCharsetName}} is
set when the header declares none, as today); used by the consumer and the
converter instead of the deprecated helper.
* Upgrade guide note for 4.23 (as for camel-undertow).
With the fix the 5 new tests and the module pass (281 tests, 8 skipped). As in
camel-undertow and camel-http ({{StringEntity}} with the Content-Type), the
declared charset wins over {{CamelCharsetName}}; without a declared charset the
exchange charset is used as today.
Found with the Lean 4 model of the String body encoding written for
CAMEL-25217, applied to camel-netty-http: the property "a peer that decodes
with the declared charset reads the text that was sent" fails for every text
with a character outside US-ASCII (theorem {{main_corrupts}}) and holds with
the fix; the case-sensitive parameter lookup misses {{Charset=}}
({{cex_upper}}).
Affected: 4.14.x, 4.18.x and main (same code).
Duplicate check (2026-10-03): JIRA component camel-netty-http with text
"charset" (only CAMEL-6872, an action parameter in the Content-Type, fixed in
2.x); GitHub pull requests "netty-http charset", "netty-http Content-Type
charset": none.
_Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)