Add setOutputStreaming option for HTTP factory

Add setOutputStreaming on SimpleClientHttpRequestFactory to allow the
disabling of 'output streaming' mode on the underlying connection so
that authentication and redirection can be handled automatically.

Issue: SPR-9617
This commit is contained in:
Phillip Webb
2013-02-12 20:36:12 -08:00
parent 030c61f294
commit 92ad66bf10
5 changed files with 98 additions and 13 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2013 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.
@@ -39,9 +39,12 @@ final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttp
private final HttpURLConnection connection;
private final boolean outputStreaming;
SimpleBufferingClientHttpRequest(HttpURLConnection connection) {
SimpleBufferingClientHttpRequest(HttpURLConnection connection, boolean outputStreaming) {
this.connection = connection;
this.outputStreaming = outputStreaming;
}
@@ -67,7 +70,7 @@ final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttp
}
}
if (this.connection.getDoOutput()) {
if (this.connection.getDoOutput() && this.outputStreaming) {
this.connection.setFixedLengthStreamingMode(bufferedOutput.length);
}
this.connection.connect();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,8 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory
private int readTimeout = -1;
private boolean outputStreaming = true;
/**
* Set the {@link Proxy} to use for this request factory.
@@ -104,15 +106,31 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory
this.readTimeout = readTimeout;
}
/**
* Set if the underlying URLConnection can be set to 'output streaming' mode. When
* output streaming is enabled, authentication and redirection cannot be handled
* automatically. If output streaming is disabled the
* {@link HttpURLConnection#setFixedLengthStreamingMode(int)
* setFixedLengthStreamingMode} and
* {@link HttpURLConnection#setChunkedStreamingMode(int) setChunkedStreamingMode}
* methods of the underlying connection will never be called.
* <p>Default is {@code true}.
* @param outputStreaming if output streaming is enabled
*/
public void setOutputStreaming(boolean outputStreaming) {
this.outputStreaming = outputStreaming;
}
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpURLConnection connection = openConnection(uri.toURL(), this.proxy);
prepareConnection(connection, httpMethod.name());
if (this.bufferRequestBody) {
return new SimpleBufferingClientHttpRequest(connection);
return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming);
}
else {
return new SimpleStreamingClientHttpRequest(connection, this.chunkSize);
return new SimpleStreamingClientHttpRequest(connection, this.chunkSize,
this.outputStreaming);
}
}

View File

@@ -44,10 +44,14 @@ final class SimpleStreamingClientHttpRequest extends AbstractClientHttpRequest {
private OutputStream body;
private final boolean outputStreaming;
SimpleStreamingClientHttpRequest(HttpURLConnection connection, int chunkSize) {
SimpleStreamingClientHttpRequest(HttpURLConnection connection, int chunkSize,
boolean outputStreaming) {
this.connection = connection;
this.chunkSize = chunkSize;
this.outputStreaming = outputStreaming;
}
public HttpMethod getMethod() {
@@ -66,12 +70,14 @@ final class SimpleStreamingClientHttpRequest extends AbstractClientHttpRequest {
@Override
protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException {
if (this.body == null) {
int contentLength = (int) headers.getContentLength();
if (contentLength >= 0) {
this.connection.setFixedLengthStreamingMode(contentLength);
}
else {
this.connection.setChunkedStreamingMode(this.chunkSize);
if(this.outputStreaming) {
int contentLength = (int) headers.getContentLength();
if (contentLength >= 0) {
this.connection.setFixedLengthStreamingMode(contentLength);
}
else {
this.connection.setChunkedStreamingMode(this.chunkSize);
}
}
writeHeaders(headers);
this.connection.connect();

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2002-2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.client;
public class NoOutputStreamingBufferedSimpleHttpRequestFactoryTests extends AbstractHttpRequestFactoryTestCase {
@Override
protected ClientHttpRequestFactory createRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setOutputStreaming(false);
return factory;
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2002-2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.client;
public class NoOutputStreamingStreamingSimpleHttpRequestFactoryTests extends AbstractHttpRequestFactoryTestCase {
@Override
protected ClientHttpRequestFactory createRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setBufferRequestBody(false);
factory.setOutputStreaming(false);
return factory;
}
}