From 780ffb8e9841735e01d780ffbffc17cd81a66db0 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 1 Jul 2020 10:46:46 +0200 Subject: [PATCH] Use UTF-8 for application/*+json This commit makes sure that the StringHttpMessageConverter reads input with "application/*+json" as Content-Type with the UTF-8 character set. Closes gh-25328 --- .../converter/StringHttpMessageConverter.java | 10 ++++++-- .../StringHttpMessageConverterTests.java | 25 ++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java index d576855d95d5..407f13906913 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java @@ -43,6 +43,8 @@ */ public class StringHttpMessageConverter extends AbstractHttpMessageConverter { + private static final MediaType APPLICATION_PLUS_JSON = new MediaType("application", "*+json"); + /** * The default charset used by the converter. */ @@ -104,7 +106,9 @@ protected Long getContentLength(String str, @Nullable MediaType contentType) { @Override protected void addDefaultHeaders(HttpHeaders headers, String s, @Nullable MediaType type) throws IOException { if (headers.getContentType() == null ) { - if (type != null && type.isConcrete() && type.isCompatibleWith(MediaType.APPLICATION_JSON)) { + if (type != null && type.isConcrete() && + (type.isCompatibleWith(MediaType.APPLICATION_JSON) || + type.isCompatibleWith(APPLICATION_PLUS_JSON))) { // Prevent charset parameter for JSON.. headers.setContentType(type); } @@ -142,7 +146,9 @@ private Charset getContentTypeCharset(@Nullable MediaType contentType) { if (contentType != null && contentType.getCharset() != null) { return contentType.getCharset(); } - else if (contentType != null && contentType.isCompatibleWith(MediaType.APPLICATION_JSON)) { + else if (contentType != null && + (contentType.isCompatibleWith(MediaType.APPLICATION_JSON) || + contentType.isCompatibleWith(APPLICATION_PLUS_JSON))) { // Matching to AbstractJackson2HttpMessageConverter#DEFAULT_CHARSET return StandardCharsets.UTF_8; } diff --git a/spring-web/src/test/java/org/springframework/http/converter/StringHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/StringHttpMessageConverterTests.java index 5ee6df9b009b..3323dbdb3502 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/StringHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/StringHttpMessageConverterTests.java @@ -80,6 +80,16 @@ public void readJson() throws IOException { assertThat(result).as("Invalid result").isEqualTo(body); } + @Test // gh-25328 + public void readJsonApi() throws IOException { + String body = "{\"result\":\"\u0414\u0410\"}"; + MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8)); + inputMessage.getHeaders().setContentType(new MediaType("application", "vnd.api.v1+json")); + String result = this.converter.read(String.class, inputMessage); + + assertThat(result).as("Invalid result").isEqualTo(body); + } + @Test public void writeDefaultCharset() throws IOException { String body = "H\u00e9llo W\u00f6rld"; @@ -94,7 +104,7 @@ public void writeDefaultCharset() throws IOException { @Test // gh-24123 public void writeJson() throws IOException { - String body = "{\"foo\":\"bar\"}"; + String body = "{\"føø\":\"bår\"}"; this.converter.write(body, MediaType.APPLICATION_JSON, this.outputMessage); HttpHeaders headers = this.outputMessage.getHeaders(); @@ -104,6 +114,19 @@ public void writeJson() throws IOException { assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); } + @Test // gh-25328 + public void writeJsonApi() throws IOException { + String body = "{\"føø\":\"bår\"}"; + MediaType contentType = new MediaType("application", "vnd.api.v1+json"); + this.converter.write(body, contentType, this.outputMessage); + + HttpHeaders headers = this.outputMessage.getHeaders(); + assertThat(this.outputMessage.getBodyAsString(StandardCharsets.UTF_8)).isEqualTo(body); + assertThat(headers.getContentType()).isEqualTo(contentType); + assertThat(headers.getContentLength()).isEqualTo(body.getBytes(StandardCharsets.UTF_8).length); + assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); + } + @Test public void writeUTF8() throws IOException { String body = "H\u00e9llo W\u00f6rld";