From e8972624acf83c1c84ddf34c7058d5dcb8079550 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 28 Sep 2017 15:41:06 +0200 Subject: [PATCH] Redesign of SimpleHttpRequest / SimpleHttpResponse APIs --- .../client5/http/cache/HttpCacheResponse.java | 140 +++++++++++++ .../AbstractSimpleServerExchangeHandler.java | 30 ++- .../testing/async/TestAsyncRedirects.java | 39 ++-- .../TestAsyncStatefulConnManagement.java | 8 +- .../async/TestClientAuthentication.java | 19 +- .../client5/testing/async/TestHttpAsync.java | 12 +- .../testing/async/TestHttpAsyncMinimal.java | 4 +- .../AsyncClientConnectionEviction.java | 8 +- .../http/examples/AsyncClientCustomSSL.java | 4 +- .../examples/AsyncClientHttp1Pipelining.java | 4 +- .../AsyncClientHttp2Multiplexing.java | 4 +- .../examples/AsyncClientMessageTrailers.java | 2 +- .../http/async/methods/SimpleBody.java | 99 ++++++++++ .../http/async/methods/SimpleHttpRequest.java | 184 ++++++++++-------- .../async/methods/SimpleHttpResponse.java | 71 ++++--- .../async/methods/SimpleRequestProducer.java | 33 +++- .../async/methods/SimpleResponseConsumer.java | 21 +- .../impl/async/CloseableHttpAsyncClient.java | 4 +- 18 files changed, 507 insertions(+), 179 deletions(-) create mode 100644 httpclient5-cache/src/main/java/org/apache/hc/client5/http/cache/HttpCacheResponse.java create mode 100644 httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleBody.java diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/cache/HttpCacheResponse.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/cache/HttpCacheResponse.java new file mode 100644 index 000000000..68a6dbaa7 --- /dev/null +++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/cache/HttpCacheResponse.java @@ -0,0 +1,140 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.client5.http.cache; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Set; + +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.EntityDetails; +import org.apache.hc.core5.util.Args; + +public final class HttpCacheResponse implements EntityDetails { + + private final int code; + private final String reasonPhrase; + private final byte[] body; + private final ContentType contentType; + + public static HttpCacheResponse create( + final int code, + final String reasonPhrase, + final byte[] body, + final ContentType contentType) { + return new HttpCacheResponse(code, reasonPhrase, body, contentType); + } + + public static HttpCacheResponse create( + final int code, + final byte[] body, + final ContentType contentType) { + return new HttpCacheResponse(code, null, body, contentType); + } + + public static HttpCacheResponse create( + final int code, + final String reasonPhrase) { + return new HttpCacheResponse(code, reasonPhrase, null, null); + } + + public static HttpCacheResponse create(final int code) { + return new HttpCacheResponse(code, null, null, null); + } + + public static HttpCacheResponse create( + final int code, + final String reasonPhrase, + final String body, + final ContentType contentType) { + if (body != null) { + final Charset charset = contentType != null ? contentType.getCharset() : null; + final byte[] b = body.getBytes(charset != null ? charset : StandardCharsets.US_ASCII); + return new HttpCacheResponse(code, reasonPhrase, b, contentType); + } else { + return create(code, reasonPhrase); + } + } + + public static HttpCacheResponse create( + final int code, + final String body, + final ContentType contentType) { + return create(code, null, body, contentType); + } + + private HttpCacheResponse( + final int code, + final String reasonPhrase, + final byte[] body, + final ContentType contentType) { + this.code = Args.checkRange(code, 200, 599, "HTTP status"); + this.reasonPhrase = reasonPhrase; + this.body = body; + this.contentType = contentType; + } + + public int getCode() { + return code; + } + + public String getReasonPhrase() { + return reasonPhrase; + } + + public byte[] getBody() { + return body; + } + + @Override + public long getContentLength() { + return body != null ? body.length : 0; + } + + @Override + public String getContentType() { + return contentType != null ? contentType.toString() : null; + } + + @Override + public String getContentEncoding() { + return null; + } + + @Override + public boolean isChunked() { + return false; + } + + @Override + public Set getTrailerNames() { + return null; + } + +} + diff --git a/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AbstractSimpleServerExchangeHandler.java b/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AbstractSimpleServerExchangeHandler.java index 5200e63e9..a88b576bc 100644 --- a/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AbstractSimpleServerExchangeHandler.java +++ b/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AbstractSimpleServerExchangeHandler.java @@ -28,15 +28,18 @@ package org.apache.hc.client5.testing.async; import java.io.IOException; +import org.apache.hc.client5.http.async.methods.SimpleBody; import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.nio.AsyncEntityProducer; import org.apache.hc.core5.http.nio.AsyncRequestConsumer; import org.apache.hc.core5.http.nio.AsyncServerRequestHandler; import org.apache.hc.core5.http.nio.BasicResponseProducer; -import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer; +import org.apache.hc.core5.http.nio.entity.BasicAsyncEntityConsumer; +import org.apache.hc.core5.http.nio.entity.BasicAsyncEntityProducer; import org.apache.hc.core5.http.nio.entity.StringAsyncEntityProducer; import org.apache.hc.core5.http.nio.support.AbstractAsyncRequesterConsumer; import org.apache.hc.core5.http.nio.support.AbstractServerExchangeHandler; @@ -51,14 +54,18 @@ public abstract class AbstractSimpleServerExchangeHandler extends AbstractServer protected final AsyncRequestConsumer supplyConsumer( final HttpRequest request, final HttpContext context) throws HttpException { - return new AbstractAsyncRequesterConsumer(new StringAsyncEntityConsumer()) { + return new AbstractAsyncRequesterConsumer(new BasicAsyncEntityConsumer()) { @Override protected SimpleHttpRequest buildResult( final HttpRequest request, - final String entity, + final byte[] body, final ContentType contentType) { - return new SimpleHttpRequest(request, entity, contentType); + final SimpleHttpRequest simpleRequest = SimpleHttpRequest.copy(request); + if (body != null) { + simpleRequest.setBodyBytes(body, contentType); + } + return simpleRequest; } }; @@ -70,9 +77,18 @@ public abstract class AbstractSimpleServerExchangeHandler extends AbstractServer final AsyncServerRequestHandler.ResponseTrigger responseTrigger, final HttpContext context) throws HttpException, IOException { final SimpleHttpResponse response = handle(request, HttpCoreContext.adapt(context)); - responseTrigger.submitResponse(new BasicResponseProducer( - response, - response.getBody() != null ? new StringAsyncEntityProducer(response.getBody(), response.getContentType()) : null)); + final SimpleBody body = response.getBody(); + final AsyncEntityProducer entityProducer; + if (body != null) { + if (body.isText()) { + entityProducer = new StringAsyncEntityProducer(body.getBodyText(), body.getContentType()); + } else { + entityProducer = new BasicAsyncEntityProducer(body.getBodyBytes(), body.getContentType()); + } + } else { + entityProducer = null; + } + responseTrigger.submitResponse(new BasicResponseProducer(response, entityProducer)); } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncRedirects.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncRedirects.java index a11081769..cacbef166 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncRedirects.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncRedirects.java @@ -122,9 +122,11 @@ public class TestAsyncRedirects extends IntegrationTestBase { } return response; } else if (path.equals("/newlocation/")) { - return new SimpleHttpResponse(HttpStatus.SC_OK, "Successful redirect", ContentType.TEXT_PLAIN); + final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_OK); + response.setBodyText("Successful redirect", ContentType.TEXT_PLAIN); + return response; } else { - return new SimpleHttpResponse(HttpStatus.SC_NOT_FOUND, null, null); + return new SimpleHttpResponse(HttpStatus.SC_NOT_FOUND); } } catch (final URISyntaxException ex) { throw new ProtocolException(ex.getMessage(), ex); @@ -154,7 +156,7 @@ public class TestAsyncRedirects extends IntegrationTestBase { response.addHeader(new BasicHeader("Location", "/circular-oldlocation")); return response; } else { - return new SimpleHttpResponse(HttpStatus.SC_NOT_FOUND, null, null); + return new SimpleHttpResponse(HttpStatus.SC_NOT_FOUND); } } catch (final URISyntaxException ex) { throw new ProtocolException(ex.getMessage(), ex); @@ -176,7 +178,9 @@ public class TestAsyncRedirects extends IntegrationTestBase { response.addHeader(new BasicHeader("Location", "/relativelocation/")); return response; } else if (path.equals("/relativelocation/")) { - return new SimpleHttpResponse(HttpStatus.SC_OK, "Successful redirect", ContentType.TEXT_PLAIN); + final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_OK); + response.setBodyText("Successful redirect", ContentType.TEXT_PLAIN); + return response; } else { return new SimpleHttpResponse(HttpStatus.SC_NOT_FOUND); } @@ -199,7 +203,9 @@ public class TestAsyncRedirects extends IntegrationTestBase { response.addHeader(new BasicHeader("Location", "relativelocation")); return response; } else if (path.equals("/test/relativelocation")) { - return new SimpleHttpResponse(HttpStatus.SC_OK, "Successful redirect", ContentType.TEXT_PLAIN); + final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_OK); + response.setBodyText("Successful redirect", ContentType.TEXT_PLAIN); + return response; } else { return new SimpleHttpResponse(HttpStatus.SC_NOT_FOUND); } @@ -450,9 +456,8 @@ public class TestAsyncRedirects extends IntegrationTestBase { .setMaxRedirects(5).build(); try { final Future future = httpclient.execute( - new SimpleRequestProducer( - SimpleHttpRequest.get(target, "/circular-oldlocation/"), config), - new SimpleResponseConsumer(), null); + SimpleRequestProducer.create(SimpleHttpRequest.get(target, "/circular-oldlocation/"), config), + SimpleResponseConsumer.create(), null); future.get(); } catch (final ExecutionException e) { Assert.assertTrue(e.getCause() instanceof RedirectException); @@ -477,9 +482,8 @@ public class TestAsyncRedirects extends IntegrationTestBase { .build(); try { final Future future = httpclient.execute( - new SimpleRequestProducer( - SimpleHttpRequest.get(target, "/circular-oldlocation/"), config), - new SimpleResponseConsumer(), null); + SimpleRequestProducer.create(SimpleHttpRequest.get(target, "/circular-oldlocation/"), config), + SimpleResponseConsumer.create(), null); future.get(); } catch (final ExecutionException e) { Assert.assertTrue(e.getCause() instanceof CircularRedirectException); @@ -501,8 +505,9 @@ public class TestAsyncRedirects extends IntegrationTestBase { final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute( - SimpleHttpRequest.post(target, "/oldlocation/", "stuff", ContentType.TEXT_PLAIN), context, null); + final SimpleHttpRequest post = SimpleHttpRequest.post(target, "/oldlocation/"); + post.setBodyText("stuff", ContentType.TEXT_PLAIN); + final Future future = httpclient.execute(post, context, null); final HttpResponse response = future.get(); Assert.assertNotNull(response); @@ -585,7 +590,9 @@ public class TestAsyncRedirects extends IntegrationTestBase { response.addHeader(new BasicHeader("Location", url)); return response; } else if (path.equals("/relativelocation/")) { - return new SimpleHttpResponse(HttpStatus.SC_OK, "Successful redirect", ContentType.TEXT_PLAIN); + final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_OK); + response.setBodyText("Successful redirect", ContentType.TEXT_PLAIN); + return response; } else { return new SimpleHttpResponse(HttpStatus.SC_NOT_FOUND); } @@ -793,7 +800,9 @@ public class TestAsyncRedirects extends IntegrationTestBase { final URI requestURI = request.getUri(); final String path = requestURI.getPath(); if (path.equals("/rome")) { - return new SimpleHttpResponse(HttpStatus.SC_OK, "Successful redirect", ContentType.TEXT_PLAIN); + final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_OK); + response.setBodyText("Successful redirect", ContentType.TEXT_PLAIN); + return response; } else { final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_MOVED_TEMPORARILY); response.addHeader(new BasicHeader("Location", "/rome")); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncStatefulConnManagement.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncStatefulConnManagement.java index 1918fa56c..bbede2559 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncStatefulConnManagement.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncStatefulConnManagement.java @@ -62,7 +62,9 @@ public class TestAsyncStatefulConnManagement extends IntegrationTestBase { protected SimpleHttpResponse handle( final SimpleHttpRequest request, final HttpCoreContext context) throws HttpException { - return new SimpleHttpResponse(HttpStatus.SC_OK, "Whatever", ContentType.TEXT_PLAIN); + final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_OK); + response.setBodyText("Whatever", ContentType.TEXT_PLAIN); + return response; } }; } @@ -185,7 +187,9 @@ public class TestAsyncStatefulConnManagement extends IntegrationTestBase { protected SimpleHttpResponse handle( final SimpleHttpRequest request, final HttpCoreContext context) throws HttpException { - return new SimpleHttpResponse(HttpStatus.SC_OK, "Whatever", ContentType.TEXT_PLAIN); + final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_OK); + response.setBodyText("Whatever", ContentType.TEXT_PLAIN); + return response; } }; } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestClientAuthentication.java index afde7f23a..606e66ae8 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestClientAuthentication.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestClientAuthentication.java @@ -234,8 +234,9 @@ public class TestClientAuthentication extends IntegrationTestBase { final HttpClientContext context = HttpClientContext.create(); context.setCredentialsProvider(credsProvider); - final Future future = httpclient.execute( - SimpleHttpRequest.put(target, "/", "Some important stuff", ContentType.TEXT_PLAIN), context, null); + final SimpleHttpRequest put = SimpleHttpRequest.put(target, "/"); + put.setBodyText("Some important stuff", ContentType.TEXT_PLAIN); + final Future future = httpclient.execute(put, context, null); final HttpResponse response = future.get(); Assert.assertNotNull(response); @@ -306,8 +307,9 @@ public class TestClientAuthentication extends IntegrationTestBase { context.setCredentialsProvider(credsProvider); context.setRequestConfig(RequestConfig.custom().setExpectContinueEnabled(true).build()); - final Future future = httpclient.execute( - SimpleHttpRequest.put(target, "/", "Some important stuff", ContentType.TEXT_PLAIN), context, null); + final SimpleHttpRequest put = SimpleHttpRequest.put(target, "/"); + put.setBodyText("Some important stuff", ContentType.TEXT_PLAIN); + final Future future = httpclient.execute(put, context, null); final HttpResponse response = future.get(); Assert.assertNotNull(response); @@ -332,8 +334,9 @@ public class TestClientAuthentication extends IntegrationTestBase { context.setCredentialsProvider(credsProvider); context.setRequestConfig(RequestConfig.custom().setExpectContinueEnabled(true).build()); - final Future future = httpclient.execute( - SimpleHttpRequest.put(target, "/", "Some important stuff", ContentType.TEXT_PLAIN), context, null); + final SimpleHttpRequest put = SimpleHttpRequest.put(target, "/"); + put.setBodyText("Some important stuff", ContentType.TEXT_PLAIN); + final Future future = httpclient.execute(put, context, null); final HttpResponse response = future.get(); Assert.assertNotNull(response); @@ -547,8 +550,8 @@ public class TestClientAuthentication extends IntegrationTestBase { final HttpGet httpget = new HttpGet("/"); httpget.setConfig(config); final Future future = httpclient.execute( - new SimpleRequestProducer(SimpleHttpRequest.get(target, "/"), config), - new SimpleResponseConsumer(), + SimpleRequestProducer.create(SimpleHttpRequest.get(target, "/"), config), + SimpleResponseConsumer.create(), context, null); final SimpleHttpResponse response = future.get(); Assert.assertNotNull(response); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsync.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsync.java index a4e4b981a..5f32a6f85 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsync.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsync.java @@ -78,7 +78,7 @@ public class TestHttpAsync extends IntegrationTestBase { final SimpleHttpResponse response = future.get(); Assert.assertThat(response, CoreMatchers.notNullValue()); Assert.assertThat(response.getCode(), CoreMatchers.equalTo(200)); - final String body = response.getBody(); + final String body = response.getBodyText(); Assert.assertThat(body, CoreMatchers.notNullValue()); Assert.assertThat(body.length(), CoreMatchers.equalTo(2048)); } @@ -93,7 +93,7 @@ public class TestHttpAsync extends IntegrationTestBase { final SimpleHttpResponse response = future.get(); Assert.assertThat(response, CoreMatchers.notNullValue()); Assert.assertThat(response.getCode(), CoreMatchers.equalTo(200)); - final String body = response.getBody(); + final String body = response.getBodyText(); Assert.assertThat(body, CoreMatchers.nullValue()); } } @@ -108,7 +108,7 @@ public class TestHttpAsync extends IntegrationTestBase { final SimpleHttpResponse response = future.get(); Assert.assertThat(response, CoreMatchers.notNullValue()); Assert.assertThat(response.getCode(), CoreMatchers.equalTo(200)); - final String body = response.getBody(); + final String body = response.getBodyText(); Assert.assertThat(body, CoreMatchers.notNullValue()); Assert.assertThat(body.length(), CoreMatchers.equalTo(2048)); } @@ -209,7 +209,7 @@ public class TestHttpAsync extends IntegrationTestBase { final SimpleHttpResponse response1 = future1.get(); Assert.assertThat(response1, CoreMatchers.notNullValue()); Assert.assertThat(response1.getCode(), CoreMatchers.equalTo(200)); - final String body1 = response1.getBody(); + final String body1 = response1.getBodyText(); Assert.assertThat(body1, CoreMatchers.notNullValue()); Assert.assertThat(body1.length(), CoreMatchers.equalTo(2048)); @@ -224,7 +224,7 @@ public class TestHttpAsync extends IntegrationTestBase { final SimpleHttpResponse response2 = future2.get(); Assert.assertThat(response2, CoreMatchers.notNullValue()); Assert.assertThat(response2.getCode(), CoreMatchers.equalTo(200)); - final String body2 = response2.getBody(); + final String body2 = response2.getBodyText(); Assert.assertThat(body2, CoreMatchers.notNullValue()); Assert.assertThat(body2.length(), CoreMatchers.equalTo(2048)); } @@ -234,7 +234,7 @@ public class TestHttpAsync extends IntegrationTestBase { final SimpleHttpResponse response3 = future3.get(); Assert.assertThat(response3, CoreMatchers.notNullValue()); Assert.assertThat(response3.getCode(), CoreMatchers.equalTo(200)); - final String body3 = response3.getBody(); + final String body3 = response3.getBodyText(); Assert.assertThat(body3, CoreMatchers.notNullValue()); Assert.assertThat(body3.length(), CoreMatchers.equalTo(2048)); } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java index 97e3acb97..b7b1ef50b 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java @@ -189,7 +189,7 @@ public class TestHttpAsyncMinimal { final SimpleHttpResponse response = future.get(); Assert.assertThat(response, CoreMatchers.notNullValue()); Assert.assertThat(response.getCode(), CoreMatchers.equalTo(200)); - final String body = response.getBody(); + final String body = response.getBodyText(); Assert.assertThat(body, CoreMatchers.notNullValue()); Assert.assertThat(body.length(), CoreMatchers.equalTo(2048)); } @@ -204,7 +204,7 @@ public class TestHttpAsyncMinimal { final SimpleHttpResponse response = future.get(); Assert.assertThat(response, CoreMatchers.notNullValue()); Assert.assertThat(response.getCode(), CoreMatchers.equalTo(200)); - final String body = response.getBody(); + final String body = response.getBodyText(); Assert.assertThat(body, CoreMatchers.nullValue()); } } diff --git a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java index ca7bd0190..d9dc7246e 100644 --- a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java +++ b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java @@ -66,8 +66,8 @@ public class AsyncClientConnectionEviction { final SimpleHttpRequest request = SimpleHttpRequest.get(target, "/"); final Future future1 = client.execute( - new SimpleRequestProducer(request), - new SimpleResponseConsumer(), + SimpleRequestProducer.create(request, null), + SimpleResponseConsumer.create(), new FutureCallback() { @Override @@ -95,8 +95,8 @@ public class AsyncClientConnectionEviction { // Previous connection should get evicted from the pool by now final Future future2 = client.execute( - new SimpleRequestProducer(request), - new SimpleResponseConsumer(), + SimpleRequestProducer.create(request, null), + SimpleResponseConsumer.create(), new FutureCallback() { @Override diff --git a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java index c16661213..4a66ba41d 100644 --- a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java +++ b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java @@ -105,8 +105,8 @@ public class AsyncClientCustomSSL { final SimpleHttpRequest request = SimpleHttpRequest.get(target, requestUri); final Future future = client.execute( - new SimpleRequestProducer(request), - new SimpleResponseConsumer(), + SimpleRequestProducer.create(request, null), + SimpleResponseConsumer.create(), clientContext, new FutureCallback() { diff --git a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java index efcb97581..ccf204f75 100644 --- a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java +++ b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java @@ -69,8 +69,8 @@ public class AsyncClientHttp1Pipelining { for (final String requestUri: requestUris) { final SimpleHttpRequest request = SimpleHttpRequest.get(target, requestUri); endpoint.execute( - new SimpleRequestProducer(request), - new SimpleResponseConsumer(), + SimpleRequestProducer.create(request, null), + SimpleResponseConsumer.create(), new FutureCallback() { @Override diff --git a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java index ae0c239ae..1c1bf96e1 100644 --- a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java +++ b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java @@ -70,8 +70,8 @@ public class AsyncClientHttp2Multiplexing { for (final String requestUri: requestUris) { final SimpleHttpRequest request = SimpleHttpRequest.get(target, requestUri); endpoint.execute( - new SimpleRequestProducer(request), - new SimpleResponseConsumer(), + SimpleRequestProducer.create(request, null), + SimpleResponseConsumer.create(), new FutureCallback() { @Override diff --git a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientMessageTrailers.java b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientMessageTrailers.java index 0af66f939..7da44f3e5 100644 --- a/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientMessageTrailers.java +++ b/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientMessageTrailers.java @@ -93,7 +93,7 @@ public class AsyncClientMessageTrailers { .build(); final Future future = client.execute( requestProducer, - new SimpleResponseConsumer(), + SimpleResponseConsumer.create(), new FutureCallback() { @Override diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleBody.java b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleBody.java new file mode 100644 index 000000000..4c2028f7b --- /dev/null +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleBody.java @@ -0,0 +1,99 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.client5.http.async.methods; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.util.Args; + +public final class SimpleBody { + + private final byte[] bodyAsBytes; + private final String bodyAsText; + private final ContentType contentType; + + SimpleBody(final byte[] bodyAsBytes, final String bodyAsText, final ContentType contentType) { + this.bodyAsBytes = bodyAsBytes; + this.bodyAsText = bodyAsText; + this.contentType = contentType; + } + + static SimpleBody create(final String body, final ContentType contentType) { + Args.notNull(body, "Body"); + if (body.length() > 2048) { + return new SimpleBody(null, body, contentType); + } else { + final Charset charset = (contentType != null ? contentType : ContentType.DEFAULT_TEXT).getCharset(); + final byte[] bytes = body.getBytes(charset != null ? charset : StandardCharsets.US_ASCII); + return new SimpleBody(bytes, null, contentType); + } + } + + static SimpleBody create(final byte[] body, final ContentType contentType) { + Args.notNull(body, "Body"); + return new SimpleBody(body, null, contentType); + } + + public ContentType getContentType() { + return contentType; + } + + public byte[] getBodyBytes() { + if (bodyAsBytes != null) { + return bodyAsBytes; + } else if (bodyAsText != null) { + final Charset charset = (contentType != null ? contentType : ContentType.DEFAULT_TEXT).getCharset(); + return bodyAsText.getBytes(charset != null ? charset : StandardCharsets.US_ASCII); + } else { + return null; + } + } + + public String getBodyText() { + if (bodyAsBytes != null) { + final Charset charset = (contentType != null ? contentType : ContentType.DEFAULT_TEXT).getCharset(); + return new String(bodyAsBytes, charset != null ? charset : StandardCharsets.US_ASCII); + } else if (bodyAsText != null) { + return bodyAsText; + } else { + return null; + } + } + + public boolean isText() { + return bodyAsText != null; + } + + public boolean isBytes() { + return bodyAsBytes != null; + } + +} + diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpRequest.java b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpRequest.java index c7e497d93..69238d91d 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpRequest.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpRequest.java @@ -28,174 +28,190 @@ package org.apache.hc.client5.http.async.methods; import java.net.URI; +import java.util.Iterator; import org.apache.hc.client5.http.StandardMethods; import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.message.BasicHttpRequest; -import org.apache.hc.core5.http.message.HttpRequestWrapper; import org.apache.hc.core5.util.Args; -public final class SimpleHttpRequest extends HttpRequestWrapper { +public final class SimpleHttpRequest extends BasicHttpRequest { - private final String body; - private final ContentType contentType; + private SimpleBody body; public static SimpleHttpRequest get(final URI requestUri) { Args.notNull(requestUri, "Request URI"); - return new SimpleHttpRequest(StandardMethods.GET, requestUri, null, null); + return new SimpleHttpRequest(StandardMethods.GET, requestUri); } public static SimpleHttpRequest get(final String requestUri) { - return new SimpleHttpRequest(StandardMethods.GET, URI.create(requestUri), null, null); + return new SimpleHttpRequest(StandardMethods.GET, URI.create(requestUri)); } public static SimpleHttpRequest get(final HttpHost host, final String path) { Args.notNull(host, "Host"); - return new SimpleHttpRequest(StandardMethods.GET, host, path, null, null); + return new SimpleHttpRequest(StandardMethods.GET, host, path); + } + + public static SimpleHttpRequest post(final URI requestUri) { + Args.notNull(requestUri, "Request URI"); + return new SimpleHttpRequest(StandardMethods.POST, requestUri); + } + + public static SimpleHttpRequest post(final String requestUri) { + return new SimpleHttpRequest(StandardMethods.POST, URI.create(requestUri)); + } + + public static SimpleHttpRequest post(final HttpHost host, final String path) { + Args.notNull(host, "Host"); + return new SimpleHttpRequest(StandardMethods.POST, host, path); + } + + public static SimpleHttpRequest put(final URI requestUri) { + Args.notNull(requestUri, "Request URI"); + return new SimpleHttpRequest(StandardMethods.PUT, requestUri); + } + + public static SimpleHttpRequest put(final String requestUri) { + return new SimpleHttpRequest(StandardMethods.PUT, URI.create(requestUri)); + } + + public static SimpleHttpRequest put(final HttpHost host, final String path) { + Args.notNull(host, "Host"); + return new SimpleHttpRequest(StandardMethods.PUT, host, path); } public static SimpleHttpRequest head(final URI requestUri) { Args.notNull(requestUri, "Request URI"); - return new SimpleHttpRequest(StandardMethods.HEAD, requestUri, null, null); + return new SimpleHttpRequest(StandardMethods.HEAD, requestUri); } public static SimpleHttpRequest head(final String requestUri) { - return new SimpleHttpRequest(StandardMethods.HEAD, URI.create(requestUri), null, null); + return new SimpleHttpRequest(StandardMethods.HEAD, URI.create(requestUri)); } public static SimpleHttpRequest head(final HttpHost host, final String path) { Args.notNull(host, "Host"); - return new SimpleHttpRequest(StandardMethods.HEAD, host, path, null, null); - } - - public static SimpleHttpRequest post(final URI requestUri, final String body, final ContentType contentType) { - Args.notNull(requestUri, "Request URI"); - return new SimpleHttpRequest(StandardMethods.POST, requestUri, body, contentType); - } - - public static SimpleHttpRequest post(final String requestUri, final String body, final ContentType contentType) { - return new SimpleHttpRequest(StandardMethods.POST, URI.create(requestUri), body, contentType); - } - - public static SimpleHttpRequest post(final HttpHost host, final String path, final String body, final ContentType contentType) { - Args.notNull(host, "Host"); - return new SimpleHttpRequest(StandardMethods.POST, host, path, body, contentType); - } - - public static SimpleHttpRequest PUT(final URI requestUri, final String body, final ContentType contentType) { - Args.notNull(requestUri, "Request URI"); - return new SimpleHttpRequest(StandardMethods.PUT, requestUri, body, contentType); - } - - public static SimpleHttpRequest put(final String requestUri, final String body, final ContentType contentType) { - return new SimpleHttpRequest(StandardMethods.PUT, URI.create(requestUri), body, contentType); - } - - public static SimpleHttpRequest put(final HttpHost host, final String path, final String body, final ContentType contentType) { - Args.notNull(host, "Host"); - return new SimpleHttpRequest(StandardMethods.PUT, host, path, body, contentType); + return new SimpleHttpRequest(StandardMethods.HEAD, host, path); } public static SimpleHttpRequest delete(final URI requestUri) { Args.notNull(requestUri, "Request URI"); - return new SimpleHttpRequest(StandardMethods.DELETE, requestUri, null, null); + return new SimpleHttpRequest(StandardMethods.DELETE, requestUri); } public static SimpleHttpRequest delete(final String requestUri) { - return new SimpleHttpRequest(StandardMethods.DELETE, URI.create(requestUri), null, null); + return new SimpleHttpRequest(StandardMethods.DELETE, URI.create(requestUri)); } public static SimpleHttpRequest delete(final HttpHost host, final String path) { Args.notNull(host, "Host"); - return new SimpleHttpRequest(StandardMethods.DELETE, host, path, null, null); + return new SimpleHttpRequest(StandardMethods.DELETE, host, path); } public static SimpleHttpRequest trace(final URI requestUri) { Args.notNull(requestUri, "Request URI"); - return new SimpleHttpRequest(StandardMethods.TRACE, requestUri, null, null); + return new SimpleHttpRequest(StandardMethods.TRACE, requestUri); } public static SimpleHttpRequest trace(final String requestUri) { - return new SimpleHttpRequest(StandardMethods.TRACE, URI.create(requestUri), null, null); + return new SimpleHttpRequest(StandardMethods.TRACE, URI.create(requestUri)); } public static SimpleHttpRequest trace(final HttpHost host, final String path) { Args.notNull(host, "Host"); - return new SimpleHttpRequest(StandardMethods.TRACE, host, path, null, null); + return new SimpleHttpRequest(StandardMethods.TRACE, host, path); } public static SimpleHttpRequest options(final URI requestUri) { Args.notNull(requestUri, "Request URI"); - return new SimpleHttpRequest(StandardMethods.OPTIONS, requestUri, null, null); + return new SimpleHttpRequest(StandardMethods.OPTIONS, requestUri); } public static SimpleHttpRequest options(final String requestUri) { - return new SimpleHttpRequest(StandardMethods.OPTIONS, URI.create(requestUri), null, null); + return new SimpleHttpRequest(StandardMethods.OPTIONS, URI.create(requestUri)); } public static SimpleHttpRequest options(final HttpHost host, final String path) { Args.notNull(host, "Host"); - return new SimpleHttpRequest(StandardMethods.OPTIONS, host, path, null, null); + return new SimpleHttpRequest(StandardMethods.OPTIONS, host, path); } - public static SimpleHttpRequest patch(final URI requestUri, final String body, final ContentType contentType) { + public static SimpleHttpRequest patch(final URI requestUri) { Args.notNull(requestUri, "Request URI"); - return new SimpleHttpRequest(StandardMethods.PATCH, requestUri, body, contentType); + return new SimpleHttpRequest(StandardMethods.PATCH, requestUri); } - public static SimpleHttpRequest patch(final String requestUri, final String body, final ContentType contentType) { - return new SimpleHttpRequest(StandardMethods.PATCH, URI.create(requestUri), body, contentType); + public static SimpleHttpRequest patch(final String requestUri) { + return new SimpleHttpRequest(StandardMethods.PATCH, URI.create(requestUri)); } - public static SimpleHttpRequest patch(final HttpHost host, final String path, final String body, final ContentType contentType) { + public static SimpleHttpRequest patch(final HttpHost host, final String path) { Args.notNull(host, "Host"); - return new SimpleHttpRequest(StandardMethods.PATCH, host, path, body, contentType); + return new SimpleHttpRequest(StandardMethods.PATCH, host, path); } - public SimpleHttpRequest(final HttpRequest head, final String body, final ContentType contentType) { - super(head); + public static SimpleHttpRequest copy(final HttpRequest original) { + Args.notNull(original, "HTTP request"); + final SimpleHttpRequest copy = new SimpleHttpRequest(original.getMethod(), original.getRequestUri()); + copy.setVersion(original.getVersion()); + for (final Iterator
it = original.headerIterator(); it.hasNext(); ) { + copy.addHeader(it.next()); + } + copy.setScheme(original.getScheme()); + copy.setAuthority(original.getAuthority()); + return copy; + } + + public SimpleHttpRequest(final String method, final String path) { + super(method, path); + } + + public SimpleHttpRequest(final String method, final HttpHost host, final String path) { + super(method, host, path); + } + + public SimpleHttpRequest(final String method, final URI requestUri) { + super(method, requestUri); + } + + SimpleHttpRequest(final StandardMethods method, final URI requestUri) { + this(method.name(), requestUri); + } + + SimpleHttpRequest(final StandardMethods method, final HttpHost host, final String path) { + this(method.name(), host, path); + } + + public void setBody(final SimpleBody body) { this.body = body; - this.contentType = contentType; } - public SimpleHttpRequest( - final String method, - final HttpHost host, - final String path, - final String body, - final ContentType contentType) { - super(new BasicHttpRequest(method, host, path)); - this.body = body; - this.contentType = contentType; + public void setBodyBytes(final byte[] bodyBytes, final ContentType contentType) { + this.body = SimpleBody.create(bodyBytes, contentType); } - SimpleHttpRequest( - final StandardMethods method, - final HttpHost host, - final String path, - final String body, - final ContentType contentType) { - this(method.name(), host, path, body, contentType); + public void setBodyText(final String bodyText, final ContentType contentType) { + this.body = SimpleBody.create(bodyText, contentType); } - public SimpleHttpRequest(final String method, final URI requestUri, final String body, final ContentType contentType) { - super(new BasicHttpRequest(method, requestUri)); - this.body = body; - this.contentType = contentType; - } - - SimpleHttpRequest(final StandardMethods method, final URI requestUri, final String body, final ContentType contentType) { - this(method.name(), requestUri, body, contentType); - } - - public String getBody() { + public SimpleBody getBody() { return body; } public ContentType getContentType() { - return contentType; + return body != null ? body.getContentType() : null; + } + + public String getBodyText() { + return body != null ? body.getBodyText() : null; + } + + public byte[] getBodyBytes() { + return body != null ? body.getBodyBytes() : null; } } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java index 6e51535a9..7d1686d33 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java @@ -27,51 +27,58 @@ package org.apache.hc.client5.http.async.methods; +import java.util.Iterator; + import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.message.BasicHttpResponse; -import org.apache.hc.core5.http.message.HttpResponseWrapper; +import org.apache.hc.core5.util.Args; -public final class SimpleHttpResponse extends HttpResponseWrapper { +public final class SimpleHttpResponse extends BasicHttpResponse { - private final String body; - private final ContentType contentType; - - public SimpleHttpResponse( - final HttpResponse head, - final String body, - final ContentType contentType) { - super(head); - this.body = body; - this.contentType = contentType; - } - - public SimpleHttpResponse( - final int code, - final String reasonPhrase, - final String body, - final ContentType contentType) { - super(new BasicHttpResponse(code, reasonPhrase)); - this.body = body; - this.contentType = contentType; - } - - public SimpleHttpResponse(final int code, final String body, final ContentType contentType) { - super(new BasicHttpResponse(code)); - this.body = body; - this.contentType = contentType; - } + private SimpleBody body; public SimpleHttpResponse(final int code) { - this(code, null, null); + super(code); } - public String getBody() { + public static SimpleHttpResponse copy(final HttpResponse original) { + Args.notNull(original, "HTTP response"); + final SimpleHttpResponse copy = new SimpleHttpResponse(original.getCode()); + copy.setVersion(original.getVersion()); + for (final Iterator
it = original.headerIterator(); it.hasNext(); ) { + copy.addHeader(it.next()); + } + return copy; + } + + public void setBody(final SimpleBody body) { + this.body = body; + } + + public void setBodyBytes(final byte[] bodyBytes, final ContentType contentType) { + this.body = SimpleBody.create(bodyBytes, contentType); + } + + public void setBodyText(final String bodyText, final ContentType contentType) { + this.body = SimpleBody.create(bodyText, contentType); + } + + public SimpleBody getBody() { return body; } public ContentType getContentType() { - return contentType; + return body != null ? body.getContentType() : null; + } + + public String getBodyText() { + return body != null ? body.getBodyText() : null; + } + + public byte[] getBodyBytes() { + return body != null ? body.getBodyBytes() : null; } } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleRequestProducer.java b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleRequestProducer.java index 943669d46..69bb6fad2 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleRequestProducer.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleRequestProducer.java @@ -27,18 +27,41 @@ package org.apache.hc.client5.http.async.methods; import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.nio.AsyncEntityProducer; +import org.apache.hc.core5.http.nio.entity.BasicAsyncEntityProducer; import org.apache.hc.core5.http.nio.entity.StringAsyncEntityProducer; import org.apache.hc.core5.util.Args; public final class SimpleRequestProducer extends DefaultAsyncRequestProducer { - public SimpleRequestProducer(final SimpleHttpRequest request, final RequestConfig requestConfig) { - super(Args.notNull(request, "Request"), request.getBody() != null ? - new StringAsyncEntityProducer(request.getBody(), request.getContentType()) : null, requestConfig); + SimpleRequestProducer(final HttpRequest request, final AsyncEntityProducer entityProducer, final RequestConfig requestConfig) { + super(request, entityProducer, requestConfig); } - public SimpleRequestProducer(final SimpleHttpRequest request) { - this(request, null); + public static SimpleRequestProducer create(final SimpleHttpRequest request, final RequestConfig requestConfig) { + Args.notNull(request, "Request"); + final SimpleBody body = request.getBody(); + final AsyncEntityProducer entityProducer; + if (body != null) { + if (body.isText()) { + entityProducer = new StringAsyncEntityProducer(body.getBodyText(), body.getContentType()); + } else { + entityProducer = new BasicAsyncEntityProducer(body.getBodyBytes(), body.getContentType()) { + + //TODO: return the actual content length once + // the entity producers made repeatable in HttpCore + @Override + public long getContentLength() { + return -1; + } + + }; + } + } else { + entityProducer = null; + } + return new SimpleRequestProducer(request, entityProducer, requestConfig); } } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleResponseConsumer.java b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleResponseConsumer.java index e84be5bc2..395d1db3b 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleResponseConsumer.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleResponseConsumer.java @@ -28,18 +28,27 @@ package org.apache.hc.client5.http.async.methods; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer; +import org.apache.hc.core5.http.nio.AsyncEntityConsumer; +import org.apache.hc.core5.http.nio.entity.BasicAsyncEntityConsumer; import org.apache.hc.core5.http.nio.support.AbstractAsyncResponseConsumer; -public final class SimpleResponseConsumer extends AbstractAsyncResponseConsumer { +public final class SimpleResponseConsumer extends AbstractAsyncResponseConsumer { - public SimpleResponseConsumer() { - super(new StringAsyncEntityConsumer()); + SimpleResponseConsumer(final AsyncEntityConsumer entityConsumer) { + super(entityConsumer); + } + + public static SimpleResponseConsumer create() { + return new SimpleResponseConsumer(new BasicAsyncEntityConsumer()); } @Override - protected SimpleHttpResponse buildResult(final HttpResponse response, final String entity, final ContentType contentType) { - return new SimpleHttpResponse(response, entity, contentType); + protected SimpleHttpResponse buildResult(final HttpResponse response, final byte[] entity, final ContentType contentType) { + final SimpleHttpResponse simpleResponse = SimpleHttpResponse.copy(response); + if (entity != null) { + simpleResponse.setBodyBytes(entity, contentType); + } + return simpleResponse; } } \ No newline at end of file diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java index 552680043..56bcd9346 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java @@ -48,6 +48,7 @@ import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.io.ShutdownType; import org.apache.hc.core5.reactor.ExceptionEvent; import org.apache.hc.core5.reactor.IOReactorStatus; +import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.TimeValue; /** @@ -85,8 +86,9 @@ public abstract class CloseableHttpAsyncClient implements HttpAsyncClient, Close final SimpleHttpRequest request, final HttpContext context, final FutureCallback callback) { + Args.notNull(request, "Request"); final BasicFuture future = new BasicFuture<>(callback); - execute(new SimpleRequestProducer(request), new SimpleResponseConsumer(), context, new FutureCallback() { + execute(SimpleRequestProducer.create(request, null), SimpleResponseConsumer.create(), context, new FutureCallback() { @Override public void completed(final SimpleHttpResponse response) {