Frode Austvik created CXF-7320:
----------------------------------
Summary: Returned charset is not decoded properly
Key: CXF-7320
URL: https://issues.apache.org/jira/browse/CXF-7320
Project: CXF
Issue Type: Bug
Components: JAX-RS
Affects Versions: 3.1.10, 3.1.9
Reporter: Frode Austvik
I have a simple CXF JAX-RS client that calls a simple web service which returns
a short text/plain response (using UTF-8). However, when I try to read the
entity of this response as a String, I get an exception because the client
failed to decode (or maybe unquote is more accurate) the charset parameter
properly.
The client code I'm using is this:
{code:java}
public static void main(String[] args) {
WebTarget target =
ClientBuilder.newClient().target("http://example.org").path("test");
Response response = target.request().get();
System.out.println("status: " + response.getStatus());
System.out.println("type: " + response.getMediaType());
System.out.println("entity: " +
response.readEntity(String.class));
}
{code}
The output I get is this:
{noformat}
status: 200
type: text/plain;charset="UTF-8"
19:58:35.095 [main] ERROR org.apache.cxf.jaxrs.utils.JAXRSUtils - Problem with
reading the data, class java.lang.String, ContentType:
text/plain;charset="UTF-8".
Exception in thread "main" javax.ws.rs.client.ResponseProcessingException:
Problem with reading the data, class java.lang.String, ContentType:
text/plain;charset="UTF-8".
at
org.apache.cxf.jaxrs.impl.ResponseImpl.reportMessageHandlerProblem(ResponseImpl.java:439)
at
org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:379)
at
org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:320)
at
org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:310)
at com.example.Main.main(Main.java:17)
Caused by: java.io.UnsupportedEncodingException: "UTF-8"
at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:71)
at java.io.InputStreamReader.<init>(InputStreamReader.java:100)
at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:302)
at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:288)
at
org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(StringTextProvider.java:45)
at
org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(StringTextProvider.java:36)
at
org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1374)
at
org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:370)
... 3 more
{noformat}
This shows that the server returned the content-type as {{text/plain;
charset="UTF-8"}} - which is valid according to the RFCs, using quoted-string
syntax for the charset value. (I think it recommends not quoting for this case,
but quoted is still valid AFAIK, so the client should support it, shouldn't it?)
The relevant line in
[StringTextProvider|https://github.com/apache/cxf/blob/cxf-3.1.10/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/StringTextProvider.java#L45]
seems perfectly sensible:
{code:java}return IOUtils.toString(is, HttpUtils.getEncoding(mt,
StandardCharsets.UTF_8.name()));{code}
In isolation, the
[HttpUtils.getEncoding|https://github.com/apache/cxf/blob/cxf-3.1.10/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java#L567]
method it uses also seems sensible - however, it assumes that any quoting of
the {{MediaType}} parameters has already been decoded, while CXF-4504 says that
they shouldn't be and it's up to whatever uses them to do that decoding.
While I've found an easy workaround for my particular case (in part because
this server always uses UTF-8), I still think it the client should handle this
so a workaround isn't necessary.
For reference, the workaround I came up with was inserting this before the
{{readEntity}} call:
{code:java}
if
("\"UTF-8\"".equals(response.getMediaType().getParameters().get("charset"))) {
response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE,
response.getMediaType().withCharset("UTF-8"));
}
{code}
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)