From 7636eecb481d9d5ec9a145ec800dec09b90743da Mon Sep 17 00:00:00 2001 From: Patrick Strawderman Date: Tue, 25 Jul 2023 08:28:53 -0700 Subject: [PATCH] Use readNBytes in StringHttpMessageConverter when contentLength is available When the content length is known, use readNBytes on the InputStream in StringHttpMessageConverter, which avoids some extra copying and allocations. Closes gh-30942 --- .../http/converter/StringHttpMessageConverter.java | 9 ++++++++- .../converter/StringHttpMessageConverterTests.java | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) 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..f5b33fb97f9 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 @@ -93,7 +93,14 @@ 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(); + final byte[] bytes; + if (length >= 0 && length <= Integer.MAX_VALUE) { + bytes = inputMessage.getBody().readNBytes((int) length); + } else { + bytes = 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..7bd9479462f 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 @@ -70,6 +70,17 @@ public class StringHttpMessageConverterTests { assertThat(result).as("Invalid result").isEqualTo(body); } + @Test + public 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 { String body = "{\"result\":\"\u0414\u0410\"}";