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 b45c9ddeb82..5a408d87497 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,7 +93,11 @@ public class StringHttpMessageConverter extends AbstractHttpMessageConverter clazz, HttpInputMessage inputMessage) throws IOException { Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType()); - return StreamUtils.copyToString(inputMessage.getBody(), charset); + long length = inputMessage.getHeaders().getContentLength(); + byte[] bytes = (length >= 0 && length <= Integer.MAX_VALUE ? + inputMessage.getBody().readNBytes((int) length) : + inputMessage.getBody().readAllBytes()); + return new String(bytes, charset); } @Override 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 039da7a36cd..36bbff8866c 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ package org.springframework.http.converter; import java.io.IOException; import java.nio.charset.StandardCharsets; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpHeaders; @@ -30,38 +29,33 @@ import org.springframework.web.testfixture.http.MockHttpOutputMessage; import static org.assertj.core.api.Assertions.assertThat; /** + * Tests for {@link StringHttpMessageConverter}. + * * @author Arjen Poutsma * @author Rossen Stoyanchev */ -public class StringHttpMessageConverterTests { +class StringHttpMessageConverterTests { - public static final MediaType TEXT_PLAIN_UTF_8 = new MediaType("text", "plain", StandardCharsets.UTF_8); + private static final MediaType TEXT_PLAIN_UTF_8 = new MediaType("text", "plain", StandardCharsets.UTF_8); - private StringHttpMessageConverter converter; + private final StringHttpMessageConverter converter = new StringHttpMessageConverter(); - private MockHttpOutputMessage outputMessage; - - - @BeforeEach - public void setUp() { - this.converter = new StringHttpMessageConverter(); - this.outputMessage = new MockHttpOutputMessage(); - } + private final MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); @Test - public void canRead() { + void canRead() { assertThat(this.converter.canRead(String.class, MediaType.TEXT_PLAIN)).isTrue(); } @Test - public void canWrite() { + void canWrite() { assertThat(this.converter.canWrite(String.class, MediaType.TEXT_PLAIN)).isTrue(); assertThat(this.converter.canWrite(String.class, MediaType.ALL)).isTrue(); } @Test - public void read() throws IOException { + void read() throws IOException { String body = "Hello World"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8)); inputMessage.getHeaders().setContentType(TEXT_PLAIN_UTF_8); @@ -70,8 +64,19 @@ public class StringHttpMessageConverterTests { assertThat(result).as("Invalid result").isEqualTo(body); } + @Test + void readWithContentLengthHeader() throws IOException { + String body = "Hello World"; + MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8)); + inputMessage.getHeaders().setContentLength(body.length()); + inputMessage.getHeaders().setContentType(TEXT_PLAIN_UTF_8); + String result = this.converter.read(String.class, inputMessage); + + assertThat(result).as("Invalid result").isEqualTo(body); + } + @Test // gh-24123 - public void readJson() throws IOException { + void readJson() throws IOException { String body = "{\"result\":\"\u0414\u0410\"}"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8)); inputMessage.getHeaders().setContentType(MediaType.APPLICATION_JSON); @@ -81,7 +86,7 @@ public class StringHttpMessageConverterTests { } @Test // gh-25328 - public void readJsonApi() throws IOException { + 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")); @@ -91,7 +96,7 @@ public class StringHttpMessageConverterTests { } @Test - public void writeDefaultCharset() throws IOException { + void writeDefaultCharset() throws IOException { String body = "H\u00e9llo W\u00f6rld"; this.converter.write(body, null, this.outputMessage); @@ -99,11 +104,11 @@ public class StringHttpMessageConverterTests { assertThat(this.outputMessage.getBodyAsString(StandardCharsets.ISO_8859_1)).isEqualTo(body); assertThat(headers.getContentType()).isEqualTo(new MediaType("text", "plain", StandardCharsets.ISO_8859_1)); assertThat(headers.getContentLength()).isEqualTo(body.getBytes(StandardCharsets.ISO_8859_1).length); - assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); + assertThat(headers.getAcceptCharset()).isEmpty(); } @Test // gh-24123 - public void writeJson() throws IOException { + void writeJson() throws IOException { String body = "{\"føø\":\"bår\"}"; this.converter.write(body, MediaType.APPLICATION_JSON, this.outputMessage); @@ -111,11 +116,11 @@ public class StringHttpMessageConverterTests { assertThat(this.outputMessage.getBodyAsString(StandardCharsets.UTF_8)).isEqualTo(body); assertThat(headers.getContentType()).isEqualTo(MediaType.APPLICATION_JSON); assertThat(headers.getContentLength()).isEqualTo(body.getBytes(StandardCharsets.UTF_8).length); - assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); + assertThat(headers.getAcceptCharset()).isEmpty(); } @Test // gh-25328 - public void writeJsonApi() throws IOException { + 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); @@ -124,11 +129,11 @@ public class StringHttpMessageConverterTests { 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(); + assertThat(headers.getAcceptCharset()).isEmpty(); } @Test - public void writeUTF8() throws IOException { + void writeUTF8() throws IOException { String body = "H\u00e9llo W\u00f6rld"; this.converter.write(body, TEXT_PLAIN_UTF_8, this.outputMessage); @@ -136,11 +141,11 @@ public class StringHttpMessageConverterTests { assertThat(this.outputMessage.getBodyAsString(StandardCharsets.UTF_8)).isEqualTo(body); assertThat(headers.getContentType()).isEqualTo(TEXT_PLAIN_UTF_8); assertThat(headers.getContentLength()).isEqualTo(body.getBytes(StandardCharsets.UTF_8).length); - assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); + assertThat(headers.getAcceptCharset()).isEmpty(); } @Test // SPR-8867 - public void writeOverrideRequestedContentType() throws IOException { + void writeOverrideRequestedContentType() throws IOException { String body = "H\u00e9llo W\u00f6rld"; MediaType requestedContentType = new MediaType("text", "html"); @@ -151,11 +156,11 @@ public class StringHttpMessageConverterTests { assertThat(this.outputMessage.getBodyAsString(StandardCharsets.UTF_8)).isEqualTo(body); assertThat(headers.getContentType()).isEqualTo(TEXT_PLAIN_UTF_8); assertThat(headers.getContentLength()).isEqualTo(body.getBytes(StandardCharsets.UTF_8).length); - assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); + assertThat(headers.getAcceptCharset()).isEmpty(); } @Test // gh-24283 - public void writeWithWildCardMediaType() throws IOException { + void writeWithWildCardMediaType() throws IOException { String body = "Hello World"; this.converter.write(body, MediaType.ALL, this.outputMessage); @@ -163,7 +168,7 @@ public class StringHttpMessageConverterTests { assertThat(this.outputMessage.getBodyAsString(StandardCharsets.US_ASCII)).isEqualTo(body); assertThat(headers.getContentType()).isEqualTo(new MediaType("text", "plain", StandardCharsets.ISO_8859_1)); assertThat(headers.getContentLength()).isEqualTo(body.getBytes().length); - assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); + assertThat(headers.getAcceptCharset()).isEmpty(); } }