Browse Source

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
pull/34223/head
rstoyanchev 1 year ago
parent
commit
4b9be5aaf8
  1. 25
      spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java
  2. 24
      spring-web/src/main/java/org/springframework/http/client/AbstractBufferingClientHttpRequest.java
  3. 14
      spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java

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

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,8 @@ package org.springframework.http;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.springframework.util.StreamUtils;
/** /**
* Represents an HTTP output message that allows for setting a streaming body. * Represents an HTTP output message that allows for setting a streaming body.
* Note that such messages typically do not support {@link #getBody()} access. * Note that such messages typically do not support {@link #getBody()} access.
@ -35,6 +37,27 @@ public interface StreamingHttpOutputMessage extends HttpOutputMessage {
*/ */
void setBody(Body body); void setBody(Body body);
/**
* Variant of {@link #setBody(Body)} for a non-streaming write.
* @param body the content to write
* @throws IOException if an I/O exception occurs
* @since 7.0
*/
default void setBody(byte[] body) throws IOException {
setBody(new Body() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
StreamUtils.copy(body, outputStream);
}
@Override
public boolean repeatable() {
return true;
}
});
}
/** /**
* Defines the contract for bodies that can be written directly to an * Defines the contract for bodies that can be written directly to an

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

@ -64,35 +64,25 @@ abstract class AbstractBufferingClientHttpRequest extends AbstractClientHttpRequ
/** /**
* Execute with the given request and body. * Execute with the given request and body.
* @param request the request to execute with * @param request the request to execute with
* @param body the body to send * @param bufferedOutput the body to write
* @param bufferResponse whether to buffer the response * @param bufferResponse whether to buffer the response
* @return the resulting response * @return the resulting response
* @throws IOException in case of I/O errors from execution * @throws IOException in case of I/O errors from execution
* @since 7.0 * @since 7.0
*/ */
protected ClientHttpResponse executeWithRequest( protected ClientHttpResponse executeWithRequest(
ClientHttpRequest request, byte[] body, boolean bufferResponse) throws IOException { ClientHttpRequest request, byte[] bufferedOutput, boolean bufferResponse) throws IOException {
if (body.length > 0) { if (bufferedOutput.length > 0) {
long contentLength = request.getHeaders().getContentLength(); long contentLength = request.getHeaders().getContentLength();
if (contentLength > -1 && contentLength != body.length) { if (contentLength > -1 && contentLength != bufferedOutput.length) {
request.getHeaders().setContentLength(body.length); request.getHeaders().setContentLength(bufferedOutput.length);
} }
if (request instanceof StreamingHttpOutputMessage streamingOutputMessage) { if (request instanceof StreamingHttpOutputMessage streamingOutputMessage) {
streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() { streamingOutputMessage.setBody(bufferedOutput);
@Override
public void writeTo(OutputStream outputStream) throws IOException {
StreamUtils.copy(body, outputStream);
}
@Override
public boolean repeatable() {
return true;
}
});
} }
else { else {
StreamUtils.copy(body, request.getBody()); StreamUtils.copy(bufferedOutput, request.getBody());
} }
} }

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

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2024 the original author or authors. * Copyright 2002-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -404,17 +404,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
outputMessage.getHeaders().setContentLength(bytes.length); outputMessage.getHeaders().setContentLength(bytes.length);
if (outputMessage instanceof StreamingHttpOutputMessage streamingOutputMessage) { if (outputMessage instanceof StreamingHttpOutputMessage streamingOutputMessage) {
streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() { streamingOutputMessage.setBody(bytes);
@Override
public void writeTo(OutputStream outputStream) throws IOException {
StreamUtils.copy(bytes, outputStream);
}
@Override
public boolean repeatable() {
return true;
}
});
} }
else { else {
StreamUtils.copy(bytes, outputMessage.getBody()); StreamUtils.copy(bytes, outputMessage.getBody());

Loading…
Cancel
Save