diff --git a/spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java b/spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java index a88b5ddb667..b56856020f0 100644 --- a/spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java +++ b/spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 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. @@ -50,6 +50,18 @@ public interface StreamingHttpOutputMessage extends HttpOutputMessage { * @throws IOException in case of I/O errors */ void writeTo(OutputStream outputStream) throws IOException; + + /** + * Indicates whether this body is capable of + * {@linkplain #writeTo(OutputStream) writing its data} more than + * once. Default implementation returns {@code false}. + * @return {@code true} if this body can be written repeatedly, + * {@code false} otherwise + * @since 6.1 + */ + default boolean repeatable() { + return false; + } } } diff --git a/spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpRequestWrapper.java b/spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpRequestWrapper.java index 680921ffc04..47adf2431db 100644 --- a/spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpRequestWrapper.java +++ b/spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpRequestWrapper.java @@ -17,6 +17,7 @@ package org.springframework.http.client; import java.io.IOException; +import java.io.OutputStream; import java.net.URI; import org.springframework.http.HttpHeaders; @@ -55,7 +56,17 @@ final class BufferingClientHttpRequestWrapper extends AbstractBufferingClientHtt this.request.getHeaders().putAll(headers); if (this.request instanceof StreamingHttpOutputMessage streamingHttpOutputMessage) { - streamingHttpOutputMessage.setBody(outputStream -> StreamUtils.copy(bufferedOutput, outputStream)); + streamingHttpOutputMessage.setBody(new StreamingHttpOutputMessage.Body() { + @Override + public void writeTo(OutputStream outputStream) throws IOException { + StreamUtils.copy(bufferedOutput, outputStream); + } + + @Override + public boolean repeatable() { + return true; + } + }); } else { StreamUtils.copy(bufferedOutput, this.request.getBody()); diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java index ec1e6d33ee5..a14d8ef8cbe 100644 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java @@ -153,12 +153,12 @@ final class HttpComponentsClientHttpRequest extends AbstractStreamingClientHttpR @Override public boolean isRepeatable() { - return false; + return this.body.repeatable(); } @Override public boolean isStreaming() { - return true; + return false; } @Override