|
|
|
@ -20,17 +20,24 @@ import java.io.IOException; |
|
|
|
import java.io.OutputStream; |
|
|
|
import java.io.OutputStream; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.http.HttpHeaders; |
|
|
|
import org.springframework.http.HttpHeaders; |
|
|
|
|
|
|
|
import org.springframework.http.HttpOutputMessage; |
|
|
|
import org.springframework.http.StreamingHttpOutputMessage; |
|
|
|
import org.springframework.http.StreamingHttpOutputMessage; |
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.FastByteArrayOutputStream; |
|
|
|
import org.springframework.util.FastByteArrayOutputStream; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Abstract base for {@link ClientHttpRequest} that also implement |
|
|
|
* Extension of {@link AbstractClientHttpRequest} that adds the ability to stream |
|
|
|
* {@link StreamingHttpOutputMessage}. Ensures that headers and |
|
|
|
* request body content directly to the underlying HTTP client library through |
|
|
|
* body are not written multiple times. |
|
|
|
* the {@link StreamingHttpOutputMessage} contract. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* <p>It is necessary to call {@link #setBody} and stream the request body through |
|
|
|
|
|
|
|
* a callback for access to the {@code OutputStream}. The alternative to call |
|
|
|
|
|
|
|
* {@link #getBody()} is also supported as a fallback, but that does not stream, |
|
|
|
|
|
|
|
* and returns an aggregating {@code OutputStream} instead. |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Arjen Poutsma |
|
|
|
* @author Arjen Poutsma |
|
|
|
|
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @since 6.1 |
|
|
|
* @since 6.1 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequest |
|
|
|
abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequest |
|
|
|
@ -43,6 +50,12 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ |
|
|
|
private FastByteArrayOutputStream bodyStream; |
|
|
|
private FastByteArrayOutputStream bodyStream; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Implements the {@link HttpOutputMessage} contract for request body content. |
|
|
|
|
|
|
|
* <p>Note that this method does not result in streaming, and the returned |
|
|
|
|
|
|
|
* {@code OutputStream} aggregates the full content in a byte[] before |
|
|
|
|
|
|
|
* sending. To use streaming, call {@link #setBody} instead. |
|
|
|
|
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected final OutputStream getBodyInternal(HttpHeaders headers) { |
|
|
|
protected final OutputStream getBodyInternal(HttpHeaders headers) { |
|
|
|
Assert.state(this.body == null, "Invoke either getBody or setBody; not both"); |
|
|
|
Assert.state(this.body == null, "Invoke either getBody or setBody; not both"); |
|
|
|
@ -53,6 +66,10 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ |
|
|
|
return this.bodyStream; |
|
|
|
return this.bodyStream; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Implements the {@link StreamingHttpOutputMessage} contract for writing |
|
|
|
|
|
|
|
* request body by streaming directly to the underlying HTTP client. |
|
|
|
|
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public final void setBody(Body body) { |
|
|
|
public final void setBody(Body body) { |
|
|
|
Assert.notNull(body, "Body must not be null"); |
|
|
|
Assert.notNull(body, "Body must not be null"); |
|
|
|
@ -73,12 +90,14 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Abstract template method that writes the given headers and content to the HTTP request. |
|
|
|
* Abstract method for concrete implementations to write the headers and |
|
|
|
* @param headers the HTTP headers |
|
|
|
* {@link StreamingHttpOutputMessage.Body} to the HTTP request. |
|
|
|
|
|
|
|
* @param headers the HTTP headers for the request |
|
|
|
* @param body the HTTP body, may be {@code null} if no body was {@linkplain #setBody(Body) set} |
|
|
|
* @param body the HTTP body, may be {@code null} if no body was {@linkplain #setBody(Body) set} |
|
|
|
* @return the response object for the executed request |
|
|
|
* @return the response object for the executed request |
|
|
|
* @since 6.1 |
|
|
|
* @since 6.1 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected abstract ClientHttpResponse executeInternal(HttpHeaders headers, @Nullable Body body) throws IOException; |
|
|
|
protected abstract ClientHttpResponse executeInternal( |
|
|
|
|
|
|
|
HttpHeaders headers, @Nullable Body body) throws IOException; |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|