Request streaming for Apache HttpClient

- Added org.springframework.http.StreamingHttpOutputMessage, which
  allows for a settable request body (as opposed to an output stream).

- Added http.client.HttpComponentsStreamingClientHttpRequest, which
  implements the above mentioned interface, mapping setBody() to a
  setEntity() call on the Apache HttpClient HttpEntityEnclosingRequest.

- Added a 'bufferRequestBody' property to the
  HttpComponentsClientHttpRequestFactory. When this property is set to
  false (default is true), we return a
  HttpComponentsStreamingClientHttpRequest instead of a (request
  buffering) HttpComponentsClientHttpRequest.

Issue: SPR-10728
This commit is contained in:
Arjen Poutsma
2013-07-09 11:45:34 +02:00
committed by Rossen Stoyanchev
parent 6407caac8f
commit 14ab2c88cc
8 changed files with 381 additions and 24 deletions

View File

@@ -18,6 +18,7 @@ package org.springframework.http.client;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Arrays;
import java.util.Enumeration;
@@ -40,8 +41,10 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.StreamingHttpOutputMessage;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.SocketUtils;
import org.springframework.util.StreamUtils;
import static org.junit.Assert.*;
@@ -111,9 +114,21 @@ public abstract class AbstractHttpRequestFactoryTestCase {
request.getHeaders().add(headerName, headerValue1);
String headerValue2 = "value2";
request.getHeaders().add(headerName, headerValue2);
byte[] body = "Hello World".getBytes("UTF-8");
final byte[] body = "Hello World".getBytes("UTF-8");
request.getHeaders().setContentLength(body.length);
FileCopyUtils.copy(body, request.getBody());
if (request instanceof StreamingHttpOutputMessage) {
StreamingHttpOutputMessage streamingRequest =
(StreamingHttpOutputMessage) request;
streamingRequest.setBody(new StreamingHttpOutputMessage.Body() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
StreamUtils.copy(body, outputStream);
}
});
}
else {
StreamUtils.copy(body, request.getBody());
}
ClientHttpResponse response = request.execute();
try {
assertEquals("Invalid status code", HttpStatus.OK, response.getStatusCode());
@@ -131,8 +146,21 @@ public abstract class AbstractHttpRequestFactoryTestCase {
@Test(expected = IllegalStateException.class)
public void multipleWrites() throws Exception {
ClientHttpRequest request = factory.createRequest(new URI(baseUrl + "/echo"), HttpMethod.POST);
byte[] body = "Hello World".getBytes("UTF-8");
FileCopyUtils.copy(body, request.getBody());
final byte[] body = "Hello World".getBytes("UTF-8");
if (request instanceof StreamingHttpOutputMessage) {
StreamingHttpOutputMessage streamingRequest =
(StreamingHttpOutputMessage) request;
streamingRequest.setBody(new StreamingHttpOutputMessage.Body() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
StreamUtils.copy(body, outputStream);
}
});
}
else {
StreamUtils.copy(body, request.getBody());
}
ClientHttpResponse response = request.execute();
try {
FileCopyUtils.copy(body, request.getBody());

View File

@@ -0,0 +1,40 @@
/*
* 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;
import org.junit.Test;
import org.springframework.http.HttpMethod;
public class StreamingHttpComponentsClientHttpRequestFactoryTests
extends AbstractHttpRequestFactoryTestCase {
@Override
protected ClientHttpRequestFactory createRequestFactory() {
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
return requestFactory;
}
@Override
@Test
public void httpMethods() throws Exception {
assertHttpMethod("patch", HttpMethod.PATCH);
}
}