Skip to content

Commit 4b9be5a

Browse files
committed
Add setBody with byte[] to StreamingHttpOutputMessage
Sometimes the content to write is already buffered, but requires boilerplate to write through a Body callback. See gh-33785
1 parent 819a13f commit 4b9be5a

File tree

3 files changed

+33
-30
lines changed

3 files changed

+33
-30
lines changed

spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
1919
import java.io.IOException;
2020
import java.io.OutputStream;
2121

22+
import org.springframework.util.StreamUtils;
23+
2224
/**
2325
* Represents an HTTP output message that allows for setting a streaming body.
2426
* Note that such messages typically do not support {@link #getBody()} access.
@@ -35,6 +37,27 @@ public interface StreamingHttpOutputMessage extends HttpOutputMessage {
3537
*/
3638
void setBody(Body body);
3739

40+
/**
41+
* Variant of {@link #setBody(Body)} for a non-streaming write.
42+
* @param body the content to write
43+
* @throws IOException if an I/O exception occurs
44+
* @since 7.0
45+
*/
46+
default void setBody(byte[] body) throws IOException {
47+
setBody(new Body() {
48+
@Override
49+
public void writeTo(OutputStream outputStream) throws IOException {
50+
StreamUtils.copy(body, outputStream);
51+
}
52+
53+
@Override
54+
public boolean repeatable() {
55+
return true;
56+
}
57+
});
58+
}
59+
60+
3861

3962
/**
4063
* Defines the contract for bodies that can be written directly to an

spring-web/src/main/java/org/springframework/http/client/AbstractBufferingClientHttpRequest.java

+7-17
Original file line numberDiff line numberDiff line change
@@ -64,35 +64,25 @@ protected abstract ClientHttpResponse executeInternal(HttpHeaders headers, byte[
6464
/**
6565
* Execute with the given request and body.
6666
* @param request the request to execute with
67-
* @param body the body to send
67+
* @param bufferedOutput the body to write
6868
* @param bufferResponse whether to buffer the response
6969
* @return the resulting response
7070
* @throws IOException in case of I/O errors from execution
7171
* @since 7.0
7272
*/
7373
protected ClientHttpResponse executeWithRequest(
74-
ClientHttpRequest request, byte[] body, boolean bufferResponse) throws IOException {
74+
ClientHttpRequest request, byte[] bufferedOutput, boolean bufferResponse) throws IOException {
7575

76-
if (body.length > 0) {
76+
if (bufferedOutput.length > 0) {
7777
long contentLength = request.getHeaders().getContentLength();
78-
if (contentLength > -1 && contentLength != body.length) {
79-
request.getHeaders().setContentLength(body.length);
78+
if (contentLength > -1 && contentLength != bufferedOutput.length) {
79+
request.getHeaders().setContentLength(bufferedOutput.length);
8080
}
8181
if (request instanceof StreamingHttpOutputMessage streamingOutputMessage) {
82-
streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() {
83-
@Override
84-
public void writeTo(OutputStream outputStream) throws IOException {
85-
StreamUtils.copy(body, outputStream);
86-
}
87-
88-
@Override
89-
public boolean repeatable() {
90-
return true;
91-
}
92-
});
82+
streamingOutputMessage.setBody(bufferedOutput);
9383
}
9484
else {
95-
StreamUtils.copy(body, request.getBody());
85+
StreamUtils.copy(bufferedOutput, request.getBody());
9686
}
9787
}
9888

spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java

+2-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -404,17 +404,7 @@ private void writeForm(MultiValueMap<String, Object> formData, @Nullable MediaTy
404404
outputMessage.getHeaders().setContentLength(bytes.length);
405405

406406
if (outputMessage instanceof StreamingHttpOutputMessage streamingOutputMessage) {
407-
streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() {
408-
@Override
409-
public void writeTo(OutputStream outputStream) throws IOException {
410-
StreamUtils.copy(bytes, outputStream);
411-
}
412-
413-
@Override
414-
public boolean repeatable() {
415-
return true;
416-
}
417-
});
407+
streamingOutputMessage.setBody(bytes);
418408
}
419409
else {
420410
StreamUtils.copy(bytes, outputMessage.getBody());

0 commit comments

Comments
 (0)