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)