12 changed files with 385 additions and 62 deletions
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/* |
||||
* Copyright 2002-2011 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; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
import org.springframework.http.HttpHeaders; |
||||
|
||||
/** |
||||
* Abstract base for {@link ClientHttpRequest} that buffers output in a byte array before sending it over the wire. |
||||
* |
||||
* @author Arjen Poutsma |
||||
* @since 3.0.6 |
||||
*/ |
||||
abstract class AbstractBufferingClientHttpRequest extends AbstractClientHttpRequest { |
||||
|
||||
private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream(); |
||||
|
||||
@Override |
||||
protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException { |
||||
return this.bufferedOutput; |
||||
} |
||||
|
||||
@Override |
||||
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException { |
||||
byte[] bytes = this.bufferedOutput.toByteArray(); |
||||
if (headers.getContentLength() == -1) { |
||||
headers.setContentLength(bytes.length); |
||||
} |
||||
ClientHttpResponse result = executeInternal(headers, bytes); |
||||
this.bufferedOutput = null; |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Abstract template method that writes the given headers and content to the HTTP request. |
||||
* @param headers the HTTP headers |
||||
* @param bufferedOutput the body content |
||||
* @return the response object for the executed request |
||||
*/ |
||||
protected abstract ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) |
||||
throws IOException; |
||||
|
||||
|
||||
} |
@ -0,0 +1,112 @@
@@ -0,0 +1,112 @@
|
||||
/* |
||||
* Copyright 2002-2011 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; |
||||
|
||||
import java.io.FilterOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.http.HttpHeaders; |
||||
import org.springframework.http.HttpMethod; |
||||
|
||||
/** |
||||
* {@link ClientHttpRequest} implementation that uses standard J2SE facilities to execute streaming requests. |
||||
* Created via the {@link SimpleClientHttpRequestFactory}. |
||||
* |
||||
* @author Arjen Poutsma |
||||
* @since 3.0 |
||||
* @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod) |
||||
*/ |
||||
public class StreamingSimpleClientHttpRequest extends AbstractClientHttpRequest { |
||||
|
||||
private final HttpURLConnection connection; |
||||
|
||||
private final int chunkSize; |
||||
|
||||
private OutputStream body; |
||||
|
||||
StreamingSimpleClientHttpRequest(HttpURLConnection connection, int chunkSize) { |
||||
this.connection = connection; |
||||
this.chunkSize = chunkSize; |
||||
} |
||||
|
||||
public HttpMethod getMethod() { |
||||
return HttpMethod.valueOf(this.connection.getRequestMethod()); |
||||
} |
||||
|
||||
public URI getURI() { |
||||
try { |
||||
return this.connection.getURL().toURI(); |
||||
} |
||||
catch (URISyntaxException ex) { |
||||
throw new IllegalStateException("Could not get HttpURLConnection URI: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException { |
||||
if (body == null) { |
||||
int contentLength = (int) headers.getContentLength(); |
||||
if (contentLength >= 0) { |
||||
this.connection.setFixedLengthStreamingMode(contentLength); |
||||
} |
||||
else { |
||||
this.connection.setChunkedStreamingMode(chunkSize); |
||||
} |
||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) { |
||||
String headerName = entry.getKey(); |
||||
for (String headerValue : entry.getValue()) { |
||||
this.connection.addRequestProperty(headerName, headerValue); |
||||
} |
||||
} |
||||
this.connection.connect(); |
||||
this.body = this.connection.getOutputStream(); |
||||
} |
||||
return new NonClosingOutputStream(body); |
||||
} |
||||
|
||||
@Override |
||||
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException { |
||||
try { |
||||
if (body != null) { |
||||
body.close(); |
||||
} |
||||
} |
||||
catch (IOException ex) { |
||||
// ignore
|
||||
} |
||||
return new SimpleClientHttpResponse(this.connection); |
||||
} |
||||
|
||||
private static class NonClosingOutputStream extends FilterOutputStream { |
||||
|
||||
private NonClosingOutputStream(OutputStream out) { |
||||
super(out); |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
/* |
||||
* Copyright 2002-2011 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; |
||||
|
||||
import java.io.OutputStream; |
||||
import java.net.URI; |
||||
import java.util.Random; |
||||
|
||||
import org.junit.Ignore; |
||||
import org.junit.Test; |
||||
|
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.http.HttpStatus; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class StreamingSimpleHttpRequestFactoryTests extends AbstractHttpRequestFactoryTestCase { |
||||
|
||||
@Override |
||||
protected ClientHttpRequestFactory createRequestFactory() { |
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); |
||||
factory.setStreaming(true); |
||||
return factory; |
||||
} |
||||
|
||||
@Test |
||||
@Ignore |
||||
public void largeFileUpload() throws Exception { |
||||
Random rnd = new Random(); |
||||
ClientHttpResponse response = null; |
||||
try { |
||||
ClientHttpRequest request = factory.createRequest(new URI(baseUrl + "/methods/post"), HttpMethod.POST); |
||||
final int BUF_SIZE = 4096; |
||||
final int ITERATIONS = Integer.MAX_VALUE / BUF_SIZE; |
||||
final int contentLength = ITERATIONS * BUF_SIZE; |
||||
// request.getHeaders().setContentLength(contentLength);
|
||||
OutputStream body = request.getBody(); |
||||
for (int i=0; i < ITERATIONS; i++) { |
||||
byte[] buffer = new byte[BUF_SIZE]; |
||||
rnd.nextBytes(buffer); |
||||
body.write(buffer); |
||||
} |
||||
response = request.execute(); |
||||
assertEquals("Invalid response status", HttpStatus.OK, response.getStatusCode()); |
||||
} |
||||
finally { |
||||
if (response != null) { |
||||
response.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue