1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.client5.testing.async;
28
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.LinkedList;
32 import java.util.Queue;
33 import java.util.Random;
34 import java.util.concurrent.Executors;
35 import java.util.concurrent.Future;
36 import java.util.concurrent.ScheduledExecutorService;
37 import java.util.concurrent.TimeUnit;
38 import java.util.concurrent.TimeoutException;
39
40 import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
41 import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
42 import org.apache.hc.client5.http.config.RequestConfig;
43 import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
44 import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
45 import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
46 import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
47 import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
48 import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
49 import org.apache.hc.client5.testing.SSLTestContexts;
50 import org.apache.hc.core5.http.HeaderElements;
51 import org.apache.hc.core5.http.HttpHeaders;
52 import org.apache.hc.core5.http.HttpHost;
53 import org.apache.hc.core5.http.URIScheme;
54 import org.apache.hc.core5.http.config.Http1Config;
55 import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
56 import org.apache.hc.core5.http.protocol.RequestValidateHost;
57 import org.hamcrest.CoreMatchers;
58 import org.junit.Assert;
59 import org.junit.Rule;
60 import org.junit.Test;
61 import org.junit.rules.ExternalResource;
62 import org.junit.runner.RunWith;
63 import org.junit.runners.Parameterized;
64
65 @RunWith(Parameterized.class)
66 public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest<CloseableHttpAsyncClient> {
67
68 @Parameterized.Parameters(name = "HTTP/1.1 {0}")
69 public static Collection<Object[]> protocols() {
70 return Arrays.asList(new Object[][]{
71 { URIScheme.HTTP },
72 { URIScheme.HTTPS },
73 });
74 }
75
76 protected HttpAsyncClientBuilder clientBuilder;
77 protected PoolingAsyncClientConnectionManager connManager;
78
79 @Rule
80 public ExternalResource connManagerResource = new ExternalResource() {
81
82 @Override
83 protected void before() throws Throwable {
84 connManager = PoolingAsyncClientConnectionManagerBuilder.create()
85 .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
86 .build();
87 }
88
89 @Override
90 protected void after() {
91 if (connManager != null) {
92 connManager.close();
93 connManager = null;
94 }
95 }
96
97 };
98
99 @Rule
100 public ExternalResource clientBuilderResource = new ExternalResource() {
101
102 @Override
103 protected void before() throws Throwable {
104 clientBuilder = HttpAsyncClientBuilder.create()
105 .setDefaultRequestConfig(RequestConfig.custom()
106 .setConnectionRequestTimeout(TIMEOUT)
107 .setConnectTimeout(TIMEOUT)
108 .build())
109 .setConnectionManager(connManager);
110 }
111
112 };
113
114 public TestHttp1Async(final URIScheme scheme) {
115 super(scheme);
116 }
117
118 @Override
119 protected CloseableHttpAsyncClient createClient() {
120 return clientBuilder.build();
121 }
122
123 @Override
124 public HttpHost start() throws Exception {
125 return super.start(null, Http1Config.DEFAULT);
126 }
127
128 @Test
129 public void testSequentialGetRequestsCloseConnection() throws Exception {
130 final HttpHost target = start();
131 for (int i = 0; i < 3; i++) {
132 final Future<SimpleHttpResponse> future = httpclient.execute(
133 SimpleRequestBuilder.get()
134 .setHttpHost(target)
135 .setPath("/random/2048")
136 .addHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE)
137 .build(), null);
138 final SimpleHttpResponse response = future.get();
139 Assert.assertThat(response, CoreMatchers.notNullValue());
140 Assert.assertThat(response.getCode(), CoreMatchers.equalTo(200));
141 final String body = response.getBodyText();
142 Assert.assertThat(body, CoreMatchers.notNullValue());
143 Assert.assertThat(body.length(), CoreMatchers.equalTo(2048));
144 }
145 }
146
147 @Test
148 public void testGetRequestsIdentityEncodingResponse() throws Exception {
149 final HttpHost target = start(new DefaultHttpProcessor(new RequestValidateHost()), Http1Config.DEFAULT);
150
151 final int reqCount = 20;
152
153 final Queue<Future<SimpleHttpResponse>> queue = new LinkedList<>();
154 for (int i = 0; i < reqCount; i++) {
155 final Future<SimpleHttpResponse> future = httpclient.execute(
156 SimpleRequestBuilder.get()
157 .setHttpHost(target)
158 .setPath("/random/2048")
159 .build(), null);
160 queue.add(future);
161 }
162 while (!queue.isEmpty()) {
163 final Future<SimpleHttpResponse> future = queue.remove();
164 final SimpleHttpResponse response = future.get();
165 Assert.assertThat(response, CoreMatchers.notNullValue());
166 Assert.assertThat(response.getCode(), CoreMatchers.equalTo(200));
167 final String body = response.getBodyText();
168 Assert.assertThat(body, CoreMatchers.notNullValue());
169 Assert.assertThat(body.length(), CoreMatchers.equalTo(2048));
170 }
171 }
172
173 @Test
174 public void testConcurrentPostsOverMultipleConnections() throws Exception {
175 connManager.setDefaultMaxPerRoute(20);
176 connManager.setMaxTotal(100);
177 super.testConcurrentPostRequests();
178 }
179
180 @Test
181 public void testConcurrentPostsOverSingleConnection() throws Exception {
182 connManager.setDefaultMaxPerRoute(1);
183 connManager.setMaxTotal(100);
184 super.testConcurrentPostRequests();
185 }
186
187 @Test
188 public void testSharedPool() throws Exception {
189 final HttpHost target = start();
190 final Future<SimpleHttpResponse> future1 = httpclient.execute(
191 SimpleRequestBuilder.get()
192 .setHttpHost(target)
193 .setPath("/random/2048")
194 .build(), null);
195 final SimpleHttpResponse response1 = future1.get();
196 Assert.assertThat(response1, CoreMatchers.notNullValue());
197 Assert.assertThat(response1.getCode(), CoreMatchers.equalTo(200));
198 final String body1 = response1.getBodyText();
199 Assert.assertThat(body1, CoreMatchers.notNullValue());
200 Assert.assertThat(body1.length(), CoreMatchers.equalTo(2048));
201
202
203 try (final CloseableHttpAsyncClient httpclient2 = HttpAsyncClients.custom()
204 .setConnectionManager(connManager)
205 .setConnectionManagerShared(true)
206 .build()) {
207 httpclient2.start();
208 final Future<SimpleHttpResponse> future2 = httpclient2.execute(
209 SimpleRequestBuilder.get()
210 .setHttpHost(target)
211 .setPath("/random/2048")
212 .build(), null);
213 final SimpleHttpResponse response2 = future2.get();
214 Assert.assertThat(response2, CoreMatchers.notNullValue());
215 Assert.assertThat(response2.getCode(), CoreMatchers.equalTo(200));
216 final String body2 = response2.getBodyText();
217 Assert.assertThat(body2, CoreMatchers.notNullValue());
218 Assert.assertThat(body2.length(), CoreMatchers.equalTo(2048));
219 }
220
221 final Future<SimpleHttpResponse> future3 = httpclient.execute(
222 SimpleRequestBuilder.get()
223 .setHttpHost(target)
224 .setPath("/random/2048")
225 .build(), null);
226 final SimpleHttpResponse response3 = future3.get();
227 Assert.assertThat(response3, CoreMatchers.notNullValue());
228 Assert.assertThat(response3.getCode(), CoreMatchers.equalTo(200));
229 final String body3 = response3.getBodyText();
230 Assert.assertThat(body3, CoreMatchers.notNullValue());
231 Assert.assertThat(body3.length(), CoreMatchers.equalTo(2048));
232 }
233
234 @Test
235 public void testRequestCancellation() throws Exception {
236 this.connManager.setDefaultMaxPerRoute(1);
237 this.connManager.setMaxTotal(1);
238
239 final HttpHost target = start();
240
241 final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
242 try {
243
244 for (int i = 0; i < 20; i++) {
245 final Future<SimpleHttpResponse> future = httpclient.execute(
246 SimpleRequestBuilder.get()
247 .setHttpHost(target)
248 .setPath("/random/1000")
249 .build(), null);
250
251 executorService.schedule(new Runnable() {
252
253 @Override
254 public void run() {
255 future.cancel(true);
256 }
257 }, i % 5, TimeUnit.MILLISECONDS);
258
259 try {
260 future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
261 } catch (final TimeoutException ex) {
262 throw ex;
263 } catch (final Exception ignore) {
264 }
265 }
266
267 final Random rnd = new Random();
268 for (int i = 0; i < 20; i++) {
269 final Future<SimpleHttpResponse> future = httpclient.execute(
270 SimpleRequestBuilder.get()
271 .setHttpHost(target)
272 .setPath("/random/1000")
273 .build(), null);
274
275 executorService.schedule(new Runnable() {
276
277 @Override
278 public void run() {
279 future.cancel(true);
280 }
281 }, rnd.nextInt(200), TimeUnit.MILLISECONDS);
282
283 try {
284 future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
285 } catch (final TimeoutException ex) {
286 throw ex;
287 } catch (final Exception ignore) {
288 }
289 }
290
291 for (int i = 0; i < 5; i++) {
292 final Future<SimpleHttpResponse> future = httpclient.execute(
293 SimpleRequestBuilder.get()
294 .setHttpHost(target)
295 .setPath("/random/1000")
296 .build(), null);
297 final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
298 Assert.assertThat(response, CoreMatchers.notNullValue());
299 Assert.assertThat(response.getCode(), CoreMatchers.equalTo(200));
300 }
301
302 } finally {
303 executorService.shutdownNow();
304 }
305 }
306
307 }