shashank created CAMEL-25633:
--------------------------------

             Summary: camel-undertow - form fields of a request without a 
declared charset (as browsers send them) are decoded as ISO-8859-1: café 
arrives as café in the headers and the body map, for 
application/x-www-form-urlencoded and multipart/form-data
                 Key: CAMEL-25633
                 URL: https://issues.apache.org/jira/browse/CAMEL-25633
             Project: Camel
          Issue Type: Bug
          Components: camel-undertow
            Reporter: shashank
            Assignee: shashank


{{UndertowConsumer}} parses form requests with Undertow's 
{{EagerFormParsingHandler}} (line 121 at main 1de5ec5135f8):
{code:java}
HttpHandler httpHandler = new 
EagerFormParsingHandler().setNext(UndertowConsumer.this);
{code}
The no-argument constructor uses {{FormParserFactory.builder().build()}}; its 
two parsers ({{FormEncodedDataDefinition}}, {{MultiPartParserDefinition}}) fall 
back to ISO-8859-1 when the request does not declare a charset. A browser 
submits a form as UTF-8 and does not declare a charset (the WHATWG URL standard 
defines {{application/x-www-form-urlencoded}} without a charset parameter; RFC 
7578 4.6 leaves the charset of a text field to the form's encoding, UTF-8 for 
current pages). So every non-ASCII form value is corrupted, with default 
options: {{name=Gr%C3%BC%C3%9Fe}} gives the header {{name}} = {{GrüÃ\u009fe}}, 
and the body map (the consumer sets the body to a Map of the fields) has the 
same value. The same for a text field of a multipart form.

apache/camel PR #22471 (merged 2026-04-08) fixed the same Undertow ISO-8859-1 
default for the request body ("matching the behavior of 
{{DefaultHttpBinding}}"): the consumer now sets the exchange charset only when 
the request declares one. The form path, where Undertow's form parsers decode 
the fields themselves, was not covered by that change.

How the other HTTP consumers decode these fields (read on main 1de5ec5135f8; 
differential test with the same requests to each consumer, the servlet hosted 
in Jetty 12):
* camel-platform-http-vertx (Vert.x): UTF-8.
* camel-servlet and camel-jetty, form-urlencoded body: 
{{DefaultHttpBinding.readFormUrlEncodedBody}} (lines 281-283) decodes with 
{{request.getCharacterEncoding()}} and falls back to UTF-8 when it is null, 
which it is for a request without a charset unless the container has a default 
request encoding.
* camel-servlet and camel-jetty, multipart text fields: taken from the 
container ({{populateRequestParameters}}, {{request.getParameterValues}}), so 
the container default applies: Jetty 12 UTF-8; Tomcat ISO-8859-1 unless 
{{request-character-encoding}} is set (Spring Boot sets UTF-8 by default). 
camel-servlet therefore agrees with UTF-8 only when hosted in Jetty or in a 
Tomcat configured with a UTF-8 request encoding.
* camel-netty-http does not decode form values at all by default 
({{urlDecodeHeaders=false}}), a different, documented option.

h3. Reproduction

New {{UndertowFormCharsetTest}}: a form-urlencoded request and a multipart 
request with the field {{name=Grüße}} in UTF-8 and no charset. With main both 
fail: {{expected: <Grüße> but was: <GrüÃe>}}. A third test (form with 
{{charset=ISO-8859-1}} and ISO-8859-1 bytes) passes before and after; it guards 
that a declared charset is still used. A fourth pins the caveat below 
({{name=Gr%FC%DFe}} without a charset gives {{Gr\uFFFD\uFFFDe}} with the fix, 
{{Grüße}} on main).

Exhaustive check of the decoding: all 1920 code points from U+0080 to U+07FF, 
percent-encoded as UTF-8 the way a browser sends them: decoded as ISO-8859-1 
all 1920 are wrong, decoded as UTF-8 none.

h3. Proposed fix

{code:java}
new 
EagerFormParsingHandler(FormParserFactory.builder().withDefaultCharset(StandardCharsets.UTF_8.name()).build())
{code}
({{FormParserFactory.Builder.build()}} sets the default encoding of each 
parser, Undertow 2.4.4.Final, the version in {{parent/pom.xml}} on main and on 
camel-4.23.x.) A charset that the request or a part declares is still used.

Behaviour change (4.24 upgrade-guide entry): non-ASCII form fields without a 
declared charset are now decoded as UTF-8. A client that sends ISO-8859-1 form 
data without declaring it now gets U+FFFD replacement characters instead; such 
a client has to declare its charset.

camel-undertow tests with the fix: 228 run, 0 failures, 1 skipped.

Affected: main 1de5ec5135f8 (tested). camel-4.23.x, camel-4.22.1, camel-4.18.4 
and camel-4.14.9 have the same {{new EagerFormParsingHandler()}}: read, not run.

Duplicate check (2026-10-14): JIRA text "undertow form ISO-8859-1", "undertow 
form UTF-8", "undertow form charset": none about form fields. GitHub pull 
requests: #22471 (request body, merged; see above), none about form fields.

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to