Allow repeatable writes in StreamingHttpOutputMessage

This commit adds a repeatable property to
StreamingHttpOutputMessage.Body, indicating that the body can be written
 multiple times. In HttpComponentsClientHttpRequest, this property is
 exposed via org.apache.hc.core5.http.HttpEntity.isRepeatable, to allow
 for redirects.

Closes gh-31449
This commit is contained in:
Arjen Poutsma 2023-10-24 12:09:11 +02:00
parent 71330ddb0f
commit e0ac000415
3 changed files with 27 additions and 4 deletions

View File

@ -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;
}
}
}

View File

@ -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());

View File

@ -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