Skip to content

Commit

Permalink
Use Content-Length for optimal read to byte[]
Browse files Browse the repository at this point in the history
If content-length is available, pass it to readNBytes in
ByteArrayHttpMessageConverter. When the content length is less than
the internal buffer size in InputStream (8192), this avoids a copy,
as readNBytes will return the buffer directly. When the content length
is greater than the buffer size used in InputStream, passing the
content-length at least avoids over-allocating the final buffer (e.g.,
if the content length were 8193 bytes, 1 byte more than the default
buffer size).

If the content length isn't present or is too large to represent as
an integer, fall back to the default behavior of readAllBytes by
passing in Integer.MAX_VALUE.

See gh-30010
  • Loading branch information
kilink authored and rstoyanchev committed Mar 2, 2023
1 parent 9624ea3 commit df1f813
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,15 @@ public boolean supports(Class<?> clazz) {

@Override
public byte[] readInternal(Class<? extends byte[]> clazz, HttpInputMessage inputMessage) throws IOException {
return inputMessage.getBody().readAllBytes();
long contentLength = inputMessage.getHeaders().getContentLength();
final int len;
if (contentLength >= 0 && contentLength <= Integer.MAX_VALUE) {
len = (int) contentLength;
}
else {
len = Integer.MAX_VALUE;
}
return inputMessage.getBody().readNBytes(len);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ public void read() throws IOException {
assertThat(result).as("Invalid result").isEqualTo(body);
}

@Test
public void readWithContentLengthHeaderSet() throws IOException {
byte[] body = new byte[]{0x1, 0x2, 0x3, 0x4, 0x5};
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body);
inputMessage.getHeaders().setContentType(new MediaType("application", "octet-stream"));
inputMessage.getHeaders().setContentLength(body.length);
byte[] result = converter.read(byte[].class, inputMessage);
assertThat(result).as("Invalid result").isEqualTo(body);
}

@Test
public void write() throws IOException {
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
Expand Down

0 comments on commit df1f813

Please sign in to comment.