revised package-level request and response classes
This commit is contained in:
parent
f5fdedea60
commit
0c2a6395e7
|
|
@ -28,7 +28,7 @@ import org.springframework.http.HttpHeaders;
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.0.6
|
* @since 3.0.6
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractBufferingClientHttpRequest extends AbstractClientHttpRequest {
|
abstract class AbstractBufferingClientHttpRequest extends AbstractClientHttpRequest {
|
||||||
|
|
||||||
private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream();
|
private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,13 @@ import org.springframework.util.Assert;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractClientHttpRequest implements ClientHttpRequest {
|
public abstract class AbstractClientHttpRequest implements ClientHttpRequest {
|
||||||
|
|
||||||
private boolean executed = false;
|
|
||||||
|
|
||||||
private final HttpHeaders headers = new HttpHeaders();
|
private final HttpHeaders headers = new HttpHeaders();
|
||||||
|
|
||||||
|
private boolean executed = false;
|
||||||
|
|
||||||
|
|
||||||
public final HttpHeaders getHeaders() {
|
public final HttpHeaders getHeaders() {
|
||||||
return executed ? HttpHeaders.readOnlyHttpHeaders(headers) : this.headers;
|
return (this.executed ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final OutputStream getBody() throws IOException {
|
public final OutputStream getBody() throws IOException {
|
||||||
|
|
@ -43,14 +44,6 @@ public abstract class AbstractClientHttpRequest implements ClientHttpRequest {
|
||||||
return getBodyInternal(this.headers);
|
return getBodyInternal(this.headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract template method that returns the body.
|
|
||||||
*
|
|
||||||
* @param headers the HTTP headers
|
|
||||||
* @return the body output stream
|
|
||||||
*/
|
|
||||||
protected abstract OutputStream getBodyInternal(HttpHeaders headers) throws IOException;
|
|
||||||
|
|
||||||
public final ClientHttpResponse execute() throws IOException {
|
public final ClientHttpResponse execute() throws IOException {
|
||||||
checkExecuted();
|
checkExecuted();
|
||||||
ClientHttpResponse result = executeInternal(this.headers);
|
ClientHttpResponse result = executeInternal(this.headers);
|
||||||
|
|
@ -62,13 +55,19 @@ public abstract class AbstractClientHttpRequest implements ClientHttpRequest {
|
||||||
Assert.state(!this.executed, "ClientHttpRequest already executed");
|
Assert.state(!this.executed, "ClientHttpRequest already executed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract template method that returns the body.
|
||||||
|
* @param headers the HTTP headers
|
||||||
|
* @return the body output stream
|
||||||
|
*/
|
||||||
|
protected abstract OutputStream getBodyInternal(HttpHeaders headers) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract template method that writes the given headers and content to the HTTP request.
|
* Abstract template method that writes the given headers and content to the HTTP request.
|
||||||
*
|
|
||||||
* @param headers the HTTP headers
|
* @param headers the HTTP headers
|
||||||
* @return the response object for the executed request
|
* @return the response object for the executed request
|
||||||
*/
|
*/
|
||||||
protected abstract ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException;
|
protected abstract ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,9 @@ public abstract class AbstractClientHttpRequestFactoryWrapper implements ClientH
|
||||||
|
|
||||||
private final ClientHttpRequestFactory requestFactory;
|
private final ClientHttpRequestFactory requestFactory;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code AbstractClientHttpRequestFactoryWrapper} wrapping the given request factory.
|
* Creates a {@code AbstractClientHttpRequestFactoryWrapper} wrapping the given request factory.
|
||||||
*
|
|
||||||
* @param requestFactory the request factory to be wrapped
|
* @param requestFactory the request factory to be wrapped
|
||||||
*/
|
*/
|
||||||
protected AbstractClientHttpRequestFactoryWrapper(ClientHttpRequestFactory requestFactory) {
|
protected AbstractClientHttpRequestFactoryWrapper(ClientHttpRequestFactory requestFactory) {
|
||||||
|
|
@ -42,29 +42,27 @@ public abstract class AbstractClientHttpRequestFactoryWrapper implements ClientH
|
||||||
this.requestFactory = requestFactory;
|
this.requestFactory = requestFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* This implementation simply calls {@link #createRequest(URI, HttpMethod, ClientHttpRequestFactory)}
|
||||||
*
|
* with the wrapped request factory provided to the
|
||||||
* <p>This implementation simply calls {@link #createRequest(URI, HttpMethod, ClientHttpRequestFactory)} with the
|
* {@linkplain #AbstractClientHttpRequestFactoryWrapper(ClientHttpRequestFactory) constructor}.
|
||||||
* wrapped request factory provided to the {@linkplain #AbstractClientHttpRequestFactoryWrapper(ClientHttpRequestFactory)
|
|
||||||
* constructor}.
|
|
||||||
*/
|
*/
|
||||||
public final ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
|
public final ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
|
||||||
return createRequest(uri, httpMethod, requestFactory);
|
return createRequest(uri, httpMethod, requestFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link ClientHttpRequest} for the specified URI and HTTP method by using the passed on request factory.
|
* Create a new {@link ClientHttpRequest} for the specified URI and HTTP method by using the
|
||||||
|
* passed-on request factory.
|
||||||
* <p>Called from {@link #createRequest(URI, HttpMethod)}.
|
* <p>Called from {@link #createRequest(URI, HttpMethod)}.
|
||||||
*
|
|
||||||
* @param uri the URI to create a request for
|
* @param uri the URI to create a request for
|
||||||
* @param httpMethod the HTTP method to execute
|
* @param httpMethod the HTTP method to execute
|
||||||
* @param requestFactory the wrapped request factory
|
* @param requestFactory the wrapped request factory
|
||||||
* @return the created request
|
* @return the created request
|
||||||
* @throws IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
*/
|
*/
|
||||||
protected abstract ClientHttpRequest createRequest(URI uri,
|
protected abstract ClientHttpRequest createRequest(
|
||||||
HttpMethod httpMethod,
|
URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) throws IOException;
|
||||||
ClientHttpRequestFactory requestFactory) throws IOException;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ public class BufferingClientHttpRequestFactory extends AbstractClientHttpRequest
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ClientHttpRequest request = requestFactory.createRequest(uri, httpMethod);
|
ClientHttpRequest request = requestFactory.createRequest(uri, httpMethod);
|
||||||
if (shouldBuffer(uri, httpMethod)) {
|
if (shouldBuffer(uri, httpMethod)) {
|
||||||
return new BufferingClientHttpRequest(request);
|
return new BufferingClientHttpRequestWrapper(request);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return request;
|
return request;
|
||||||
|
|
|
||||||
|
|
@ -31,29 +31,32 @@ import org.springframework.util.FileCopyUtils;
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
class BufferingClientHttpRequest extends AbstractBufferingClientHttpRequest {
|
final class BufferingClientHttpRequestWrapper extends AbstractBufferingClientHttpRequest {
|
||||||
|
|
||||||
private final ClientHttpRequest request;
|
private final ClientHttpRequest request;
|
||||||
|
|
||||||
BufferingClientHttpRequest(ClientHttpRequest request) {
|
|
||||||
|
BufferingClientHttpRequestWrapper(ClientHttpRequest request) {
|
||||||
Assert.notNull(request, "'request' must not be null");
|
Assert.notNull(request, "'request' must not be null");
|
||||||
this.request = request;
|
this.request = request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpMethod getMethod() {
|
public HttpMethod getMethod() {
|
||||||
return request.getMethod();
|
return this.request.getMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
public URI getURI() {
|
public URI getURI() {
|
||||||
return request.getURI();
|
return this.request.getURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
|
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
|
||||||
request.getHeaders().putAll(headers);
|
this.request.getHeaders().putAll(headers);
|
||||||
OutputStream body = request.getBody();
|
OutputStream body = this.request.getBody();
|
||||||
FileCopyUtils.copy(bufferedOutput, body);
|
FileCopyUtils.copy(bufferedOutput, body);
|
||||||
ClientHttpResponse response = request.execute();
|
ClientHttpResponse response = this.request.execute();
|
||||||
return new BufferingClientHttpResponse(response);
|
return new BufferingClientHttpResponseWrapper(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -25,43 +25,45 @@ import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple implementation of {@link ClientHttpResponse} that reads the request's body into memory, thus allowing for
|
* Simple implementation of {@link ClientHttpResponse} that reads the request's body into memory,
|
||||||
* multiple invocations of {@link #getBody()}.
|
* thus allowing for multiple invocations of {@link #getBody()}.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
class BufferingClientHttpResponse implements ClientHttpResponse {
|
final class BufferingClientHttpResponseWrapper implements ClientHttpResponse {
|
||||||
|
|
||||||
private final ClientHttpResponse response;
|
private final ClientHttpResponse response;
|
||||||
|
|
||||||
private byte[] body;
|
private byte[] body;
|
||||||
|
|
||||||
BufferingClientHttpResponse(ClientHttpResponse response) {
|
|
||||||
|
BufferingClientHttpResponseWrapper(ClientHttpResponse response) {
|
||||||
this.response = response;
|
this.response = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpStatus getStatusCode() throws IOException {
|
public HttpStatus getStatusCode() throws IOException {
|
||||||
return response.getStatusCode();
|
return this.response.getStatusCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatusText() throws IOException {
|
public String getStatusText() throws IOException {
|
||||||
return response.getStatusText();
|
return this.response.getStatusText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpHeaders getHeaders() {
|
public HttpHeaders getHeaders() {
|
||||||
return response.getHeaders();
|
return this.response.getHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getBody() throws IOException {
|
public InputStream getBody() throws IOException {
|
||||||
if (body == null) {
|
if (this.body == null) {
|
||||||
body = FileCopyUtils.copyToByteArray(response.getBody());
|
this.body = FileCopyUtils.copyToByteArray(this.response.getBody());
|
||||||
}
|
}
|
||||||
return new ByteArrayInputStream(body);
|
return new ByteArrayInputStream(this.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
response.close();
|
this.response.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ public class CommonsClientHttpRequestFactory implements ClientHttpRequestFactory
|
||||||
* {@link HttpClient} that uses a default {@link MultiThreadedHttpConnectionManager}.
|
* {@link HttpClient} that uses a default {@link MultiThreadedHttpConnectionManager}.
|
||||||
*/
|
*/
|
||||||
public CommonsClientHttpRequestFactory() {
|
public CommonsClientHttpRequestFactory() {
|
||||||
httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());
|
this.httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());
|
||||||
this.setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
|
this.setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,12 @@ import org.springframework.util.FileCopyUtils;
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod)
|
* @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod)
|
||||||
*/
|
*/
|
||||||
final class BufferingSimpleClientHttpRequest extends AbstractBufferingClientHttpRequest {
|
final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttpRequest {
|
||||||
|
|
||||||
private final HttpURLConnection connection;
|
private final HttpURLConnection connection;
|
||||||
|
|
||||||
BufferingSimpleClientHttpRequest(HttpURLConnection connection) {
|
|
||||||
|
SimpleBufferingClientHttpRequest(HttpURLConnection connection) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,9 +70,7 @@ final class BufferingSimpleClientHttpRequest extends AbstractBufferingClientHttp
|
||||||
if (this.connection.getDoOutput()) {
|
if (this.connection.getDoOutput()) {
|
||||||
this.connection.setFixedLengthStreamingMode(bufferedOutput.length);
|
this.connection.setFixedLengthStreamingMode(bufferedOutput.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connection.connect();
|
this.connection.connect();
|
||||||
|
|
||||||
if (this.connection.getDoOutput()) {
|
if (this.connection.getDoOutput()) {
|
||||||
FileCopyUtils.copy(bufferedOutput, this.connection.getOutputStream());
|
FileCopyUtils.copy(bufferedOutput, this.connection.getOutputStream());
|
||||||
}
|
}
|
||||||
|
|
@ -30,22 +30,24 @@ import org.springframework.util.Assert;
|
||||||
* {@link ClientHttpRequestFactory} implementation that uses standard J2SE facilities.
|
* {@link ClientHttpRequestFactory} implementation that uses standard J2SE facilities.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @since 3.0
|
||||||
* @see java.net.HttpURLConnection
|
* @see java.net.HttpURLConnection
|
||||||
* @see CommonsClientHttpRequestFactory
|
* @see CommonsClientHttpRequestFactory
|
||||||
* @since 3.0
|
|
||||||
*/
|
*/
|
||||||
public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory {
|
public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory {
|
||||||
|
|
||||||
private static final int DEFAULT_CHUNK_SIZE = 4096;
|
private static final int DEFAULT_CHUNK_SIZE = 4096;
|
||||||
|
|
||||||
|
|
||||||
private Proxy proxy;
|
private Proxy proxy;
|
||||||
|
|
||||||
private boolean bufferRequestBody = true;
|
private boolean bufferRequestBody = true;
|
||||||
|
|
||||||
private int chunkSize = DEFAULT_CHUNK_SIZE;
|
private int chunkSize = DEFAULT_CHUNK_SIZE;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link Proxy} to use for this request factory.
|
* Set the {@link Proxy} to use for this request factory.
|
||||||
*/
|
*/
|
||||||
public void setProxy(Proxy proxy) {
|
public void setProxy(Proxy proxy) {
|
||||||
this.proxy = proxy;
|
this.proxy = proxy;
|
||||||
|
|
@ -54,12 +56,11 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory
|
||||||
/**
|
/**
|
||||||
* Indicates whether this request factory should buffer the {@linkplain ClientHttpRequest#getBody() request body}
|
* Indicates whether this request factory should buffer the {@linkplain ClientHttpRequest#getBody() request body}
|
||||||
* internally.
|
* internally.
|
||||||
* <p>Default is {@code true}. When sending large amounts of data via POST or PUT, it is recommended to change this
|
* <p>Default is {@code true}. When sending large amounts of data via POST or PUT, it is recommended
|
||||||
* property to {@code false}, so as not to run out of memory. This will result in a {@link ClientHttpRequest}
|
* to change this property to {@code false}, so as not to run out of memory. This will result in a
|
||||||
* that either streams directly to the underlying {@link HttpURLConnection} (if the
|
* {@link ClientHttpRequest} that either streams directly to the underlying {@link HttpURLConnection}
|
||||||
* {@link org.springframework.http.HttpHeaders#getContentLength() Content-Length} is known in advance), or that will
|
* (if the {@link org.springframework.http.HttpHeaders#getContentLength() Content-Length} is known in advance),
|
||||||
* use "Chunked transfer encoding" (if the {@code Content-Length} is not known in advance).
|
* or that will use "Chunked transfer encoding" (if the {@code Content-Length} is not known in advance).
|
||||||
*
|
|
||||||
* @see #setChunkSize(int)
|
* @see #setChunkSize(int)
|
||||||
* @see HttpURLConnection#setFixedLengthStreamingMode(int)
|
* @see HttpURLConnection#setFixedLengthStreamingMode(int)
|
||||||
*/
|
*/
|
||||||
|
|
@ -72,43 +73,42 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory
|
||||||
* <p>Note that this parameter is only used when {@link #setBufferRequestBody(boolean) bufferRequestBody} is set
|
* <p>Note that this parameter is only used when {@link #setBufferRequestBody(boolean) bufferRequestBody} is set
|
||||||
* to {@code false}, and the {@link org.springframework.http.HttpHeaders#getContentLength() Content-Length}
|
* to {@code false}, and the {@link org.springframework.http.HttpHeaders#getContentLength() Content-Length}
|
||||||
* is not known in advance.
|
* is not known in advance.
|
||||||
*
|
|
||||||
* @see #setBufferRequestBody(boolean)
|
* @see #setBufferRequestBody(boolean)
|
||||||
*/
|
*/
|
||||||
public void setChunkSize(int chunkSize) {
|
public void setChunkSize(int chunkSize) {
|
||||||
this.chunkSize = chunkSize;
|
this.chunkSize = chunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
|
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
|
||||||
HttpURLConnection connection = openConnection(uri.toURL(), proxy);
|
HttpURLConnection connection = openConnection(uri.toURL(), this.proxy);
|
||||||
prepareConnection(connection, httpMethod.name());
|
prepareConnection(connection, httpMethod.name());
|
||||||
if (bufferRequestBody) {
|
if (this.bufferRequestBody) {
|
||||||
return new BufferingSimpleClientHttpRequest(connection);
|
return new SimpleBufferingClientHttpRequest(connection);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new StreamingSimpleClientHttpRequest(connection, chunkSize);
|
return new SimpleStreamingClientHttpRequest(connection, this.chunkSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens and returns a connection to the given URL. <p>The default implementation uses the given {@linkplain
|
* Opens and returns a connection to the given URL.
|
||||||
* #setProxy(java.net.Proxy) proxy} - if any - to open a connection.
|
* <p>The default implementation uses the given {@linkplain #setProxy(java.net.Proxy) proxy} -
|
||||||
*
|
* if any - to open a connection.
|
||||||
* @param url the URL to open a connection to
|
* @param url the URL to open a connection to
|
||||||
* @param proxy the proxy to use, may be {@code null}
|
* @param proxy the proxy to use, may be {@code null}
|
||||||
* @return the opened connection
|
* @return the opened connection
|
||||||
* @throws IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
*/
|
*/
|
||||||
protected HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException {
|
protected HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException {
|
||||||
URLConnection urlConnection = proxy != null ? url.openConnection(proxy) : url.openConnection();
|
URLConnection urlConnection = (proxy != null ? url.openConnection(proxy) : url.openConnection());
|
||||||
Assert.isInstanceOf(HttpURLConnection.class, urlConnection);
|
Assert.isInstanceOf(HttpURLConnection.class, urlConnection);
|
||||||
return (HttpURLConnection) urlConnection;
|
return (HttpURLConnection) urlConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template method for preparing the given {@link HttpURLConnection}. <p>The default implementation prepares the
|
* Template method for preparing the given {@link HttpURLConnection}.
|
||||||
* connection for input and output, and sets the HTTP method.
|
* <p>The default implementation prepares the connection for input and output, and sets the HTTP method.
|
||||||
*
|
|
||||||
* @param connection the connection to prepare
|
* @param connection the connection to prepare
|
||||||
* @param httpMethod the HTTP request method ({@code GET}, {@code POST}, etc.)
|
* @param httpMethod the HTTP request method ({@code GET}, {@code POST}, etc.)
|
||||||
* @throws IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
|
|
@ -130,4 +130,4 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory
|
||||||
connection.setRequestMethod(httpMethod);
|
connection.setRequestMethod(httpMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ClientHttpResponse} implementation that uses standard J2SE facilities.
|
* {@link ClientHttpResponse} implementation that uses standard J2SE facilities.
|
||||||
* Obtained via {@link BufferingSimpleClientHttpRequest#execute()} and
|
* Obtained via {@link SimpleBufferingClientHttpRequest#execute()} and
|
||||||
* {@link StreamingSimpleClientHttpRequest#execute()}.
|
* {@link SimpleStreamingClientHttpRequest#execute()}.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ import org.springframework.http.HttpMethod;
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod)
|
* @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod)
|
||||||
*/
|
*/
|
||||||
public class StreamingSimpleClientHttpRequest extends AbstractClientHttpRequest {
|
final class SimpleStreamingClientHttpRequest extends AbstractClientHttpRequest {
|
||||||
|
|
||||||
private final HttpURLConnection connection;
|
private final HttpURLConnection connection;
|
||||||
|
|
||||||
|
|
@ -44,7 +44,8 @@ public class StreamingSimpleClientHttpRequest extends AbstractClientHttpRequest
|
||||||
|
|
||||||
private OutputStream body;
|
private OutputStream body;
|
||||||
|
|
||||||
StreamingSimpleClientHttpRequest(HttpURLConnection connection, int chunkSize) {
|
|
||||||
|
SimpleStreamingClientHttpRequest(HttpURLConnection connection, int chunkSize) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.chunkSize = chunkSize;
|
this.chunkSize = chunkSize;
|
||||||
}
|
}
|
||||||
|
|
@ -64,13 +65,13 @@ public class StreamingSimpleClientHttpRequest extends AbstractClientHttpRequest
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException {
|
protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException {
|
||||||
if (body == null) {
|
if (this.body == null) {
|
||||||
int contentLength = (int) headers.getContentLength();
|
int contentLength = (int) headers.getContentLength();
|
||||||
if (contentLength >= 0) {
|
if (contentLength >= 0) {
|
||||||
this.connection.setFixedLengthStreamingMode(contentLength);
|
this.connection.setFixedLengthStreamingMode(contentLength);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.connection.setChunkedStreamingMode(chunkSize);
|
this.connection.setChunkedStreamingMode(this.chunkSize);
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
||||||
String headerName = entry.getKey();
|
String headerName = entry.getKey();
|
||||||
|
|
@ -81,14 +82,14 @@ public class StreamingSimpleClientHttpRequest extends AbstractClientHttpRequest
|
||||||
this.connection.connect();
|
this.connection.connect();
|
||||||
this.body = this.connection.getOutputStream();
|
this.body = this.connection.getOutputStream();
|
||||||
}
|
}
|
||||||
return new NonClosingOutputStream(body);
|
return new NonClosingOutputStream(this.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
|
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
|
||||||
try {
|
try {
|
||||||
if (body != null) {
|
if (this.body != null) {
|
||||||
body.close();
|
this.body.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
|
|
@ -97,6 +98,7 @@ public class StreamingSimpleClientHttpRequest extends AbstractClientHttpRequest
|
||||||
return new SimpleClientHttpResponse(this.connection);
|
return new SimpleClientHttpResponse(this.connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class NonClosingOutputStream extends FilterOutputStream {
|
private static class NonClosingOutputStream extends FilterOutputStream {
|
||||||
|
|
||||||
private NonClosingOutputStream(OutputStream out) {
|
private NonClosingOutputStream(OutputStream out) {
|
||||||
|
|
@ -108,5 +110,4 @@ public class StreamingSimpleClientHttpRequest extends AbstractClientHttpRequest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue