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)

Reply via email to