You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Claus Ibsen (Jira)" <ji...@apache.org> on 2026/10/06 19:39:00 UTC

[jira] [Resolved] (CAMEL-25217) camel-platform-http-vertx - a String response body is always written as UTF-8, even when the response Content-Type declares another charset (for example charset=ISO-8859-1), so the client decodes it wrongly

     [ https://issues.apache.org/jira/browse/CAMEL-25217?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Claus Ibsen resolved CAMEL-25217.
---------------------------------
    Fix Version/s: 4.23.0
       Resolution: Fixed

The fix is merged on main, so it is in Camel 4.23.0:
* 8b451798f592 CAMEL-25217: camel-platform-http-vertx - write a String response in the charset of the Content-Type
* bc4afdf796b1 CAMEL-25217: fix the Javadoc of responseCharset

Resolving, as the ticket was not updated when the PR was merged.

_Claude Code on behalf of Claus Ibsen_

> camel-platform-http-vertx - a String response body is always written as UTF-8, even when the response Content-Type declares another charset (for example charset=ISO-8859-1), so the client decodes it wrongly
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25217
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25217
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-platform-http-vertx
>            Reporter: shashank
>            Priority: Minor
>             Fix For: 4.23.0
>
>
> {{VertxPlatformHttpSupport.toHttpResponse}} copies the {{Content-Type}} of the message, with its {{charset}} parameter, to the response. {{writeResponse}} then writes a {{String}} body with
> {code:java}
> } else if (body instanceof String string) {
>     ctx.end(string);
> {code}
> and Vert.x encodes a {{String}} as UTF-8, whatever the declared charset. A client that decodes the response with the charset of the {{Content-Type}} (as it should, RFC 9110 8.3.1) gets mojibake for every non-ASCII character. Two common cases:
> * a route that sets {{Content-Type: text/plain; charset=ISO-8859-1}} and a {{String}} body ({{setBody(constant(...))}}, {{simple}}, {{transform}}): {{Grüße aus Köln}} (14 characters) is sent as 17 bytes of UTF-8 labelled ISO-8859-1, and read as {{Grü...}} (every non-ASCII character becomes two);
> * an echo, or any route that keeps the request {{Content-Type}}: a request with {{charset=ISO-8859-1}} is read correctly (the consumer sets {{CamelCharsetName}} from it), but the reply, labelled with the same {{Content-Type}}, is UTF-8.
> {{byte[]}}, {{InputStream}} and {{Buffer}} bodies are not affected, and neither is ASCII text, which is why the existing tests pass. The type converter {{VertxBufferConverter.toBuffer(String, Exchange)}} already uses the charset of the message {{Content-Type}} first, then {{CamelCharsetName}} (CAMEL-16282); the {{String}} branch of {{writeResponse}} bypasses it. (camel-servlet encodes a {{String}} in the exchange charset, {{CamelCharsetName}} or UTF-8, and only in non-chunked mode also sets the response character encoding to match; so it gets the echo case right but not a route that only sets the {{Content-Type}}.)
> h3. Reproduction
> {code:java}
> from("platform-http:/latin1")
>     .setHeader(Exchange.CONTENT_TYPE, constant("text/plain; charset=ISO-8859-1"))
>     .setBody(constant("Grüße aus Köln"));
> from("platform-http:/echo")
>     .convertBodyTo(String.class);
> {code}
> {{GET /latin1}} returns {{Content-Type: text/plain; charset=ISO-8859-1}} with the UTF-8 bytes of the text (17 bytes instead of 14). {{POST /echo}} with {{Content-Type: text/plain; charset=ISO-8859-1}} and the 14 ISO-8859-1 bytes returns 17 bytes. A unit test with both routes fails on main; the control with {{Content-Type: text/plain}} (no charset, UTF-8 expected) passes. A small formal model (Lean 4) shows that for every text with a character outside ASCII what a client reads with the declared ISO-8859-1 charset is longer than the text, and that writing in the declared charset returns every text the charset can represent.
> h3. Proposed fix
> Write the {{String}} in the charset of the response {{Content-Type}} when it declares one (and the JVM supports it), otherwise keep UTF-8 as today:
> {code:java}
> } else if (body instanceof String string) {
>     // write the text in the charset declared by the response Content-Type (vert.x writes a String as UTF-8)
>     String charset = responseCharset(ctx);
>     if (charset != null) {
>         ctx.end(Buffer.buffer(string, charset));
>     } else {
>         ctx.end(string);
>     }
>     promise.complete();
> private static String responseCharset(RoutingContext ctx) {
>     String contentType = ctx.response().headers().get("Content-Type");
>     if (contentType == null) {
>         return null;
>     }
>     String charset = IOHelper.getCharsetNameFromContentType(contentType);
>     if (charset == null || charset.isEmpty()) {
>         return null;
>     }
>     try {
>         return Charset.isSupported(charset) ? charset : null;
>     } catch (IllegalCharsetNameException e) {
>         return null;
>     }
> }
> {code}
> Only responses that declare a charset other than UTF-8 change, and for them the bytes now match the header. A response without a charset parameter stays UTF-8 (using {{CamelCharsetName}} there as well, like camel-servlet, would change the bytes of responses whose header does not say so, so it is left out). With the fix the new test and the whole camel-platform-http-vertx suite pass (150 tests, 1 skipped, camel-core built from the same commit). Because the bytes of these responses change, the change gets an upgrade guide note (a client that ignored the declared charset and read UTF-8 must now use the declared one; characters the declared charset cannot represent are written as {{?}}).
> Duplicate check (2026-09-30): JIRA "platform-http" with "charset", "encoding" or "UTF-8", and "VertxPlatformHttpSupport": CAMEL-16282, CAMEL-16756, CAMEL-22125, CAMEL-23320 (Spring Boot starter, binary data), none about a String body. No pull request about it.
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)