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.external;
28
29 import java.util.Objects;
30 import java.util.concurrent.ExecutionException;
31 import java.util.concurrent.Future;
32 import java.util.concurrent.TimeoutException;
33
34 import javax.net.ssl.SSLContext;
35
36 import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
37 import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
38 import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
39 import org.apache.hc.client5.http.auth.AuthScope;
40 import org.apache.hc.client5.http.auth.Credentials;
41 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
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.HttpAsyncClients;
45 import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
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.protocol.HttpClientContext;
49 import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
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.HttpRequest;
54 import org.apache.hc.core5.http.HttpStatus;
55 import org.apache.hc.core5.http.HttpVersion;
56 import org.apache.hc.core5.http2.HttpVersionPolicy;
57 import org.apache.hc.core5.ssl.SSLContexts;
58 import org.apache.hc.core5.util.TextUtils;
59 import org.apache.hc.core5.util.TimeValue;
60 import org.apache.hc.core5.util.Timeout;
61
62 public class HttpAsyncClientCompatibilityTest {
63
64 public static void main(final String... args) throws Exception {
65 final HttpAsyncClientCompatibilityTestlientCompatibilityTest.html#HttpAsyncClientCompatibilityTest">HttpAsyncClientCompatibilityTest[] tests = new HttpAsyncClientCompatibilityTest[] {
66 new HttpAsyncClientCompatibilityTest(
67 HttpVersion.HTTP_1_1,
68 new HttpHost("http", "localhost", 8080), null, null),
69 new HttpAsyncClientCompatibilityTest(
70 HttpVersion.HTTP_1_1,
71 new HttpHost("http", "test-httpd", 8080), new HttpHost("localhost", 8888), null),
72 new HttpAsyncClientCompatibilityTest(
73 HttpVersion.HTTP_1_1,
74 new HttpHost("http", "test-httpd", 8080), new HttpHost("localhost", 8889),
75 new UsernamePasswordCredentials("squid", "nopassword".toCharArray())),
76 new HttpAsyncClientCompatibilityTest(
77 HttpVersion.HTTP_1_1,
78 new HttpHost("https", "localhost", 8443), null, null),
79 new HttpAsyncClientCompatibilityTest(
80 HttpVersion.HTTP_1_1,
81 new HttpHost("https", "test-httpd", 8443), new HttpHost("localhost", 8888), null),
82 new HttpAsyncClientCompatibilityTest(
83 HttpVersion.HTTP_1_1,
84 new HttpHost("https", "test-httpd", 8443), new HttpHost("localhost", 8889),
85 new UsernamePasswordCredentials("squid", "nopassword".toCharArray())),
86 new HttpAsyncClientCompatibilityTest(
87 HttpVersion.HTTP_2_0,
88 new HttpHost("http", "localhost", 8080), null, null),
89 new HttpAsyncClientCompatibilityTest(
90 HttpVersion.HTTP_2_0,
91 new HttpHost("https", "localhost", 8443), null, null)
92 };
93 for (final HttpAsyncClientCompatibilityTest test: tests) {
94 try {
95 test.execute();
96 } finally {
97 test.shutdown();
98 }
99 }
100 }
101
102 private static final Timeout TIMEOUT = Timeout.ofSeconds(5);
103
104 private final HttpVersion protocolVersion;
105 private final HttpHost target;
106 private final HttpHost proxy;
107 private final BasicCredentialsProvider credentialsProvider;
108 private final PoolingAsyncClientConnectionManager connManager;
109 private final CloseableHttpAsyncClient client;
110
111 HttpAsyncClientCompatibilityTest(
112 final HttpVersion protocolVersion,
113 final HttpHost target,
114 final HttpHost proxy,
115 final Credentials proxyCreds) throws Exception {
116 this.protocolVersion = protocolVersion;
117 this.target = target;
118 this.proxy = proxy;
119 this.credentialsProvider = new BasicCredentialsProvider();
120 final RequestConfig requestConfig = RequestConfig.custom()
121 .setProxy(proxy)
122 .build();
123 if (proxy != null && proxyCreds != null) {
124 this.credentialsProvider.setCredentials(new AuthScope(proxy), proxyCreds);
125 }
126 final SSLContext sslContext = SSLContexts.custom()
127 .loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray()).build();
128 this.connManager = PoolingAsyncClientConnectionManagerBuilder.create()
129 .setTlsStrategy(new DefaultClientTlsStrategy(sslContext))
130 .build();
131 this.client = HttpAsyncClients.custom()
132 .setVersionPolicy(this.protocolVersion == HttpVersion.HTTP_2 ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1)
133 .setConnectionManager(this.connManager)
134 .setProxy(this.proxy)
135 .setDefaultRequestConfig(requestConfig)
136 .build();
137 }
138
139 void shutdown() throws Exception {
140 client.close();
141 }
142
143 enum TestResult {OK, NOK}
144
145 private void logResult(final TestResult result, final HttpRequest request, final String message) {
146 final StringBuilder buf = new StringBuilder();
147 buf.append(result);
148 if (buf.length() == 2) {
149 buf.append(" ");
150 }
151 buf.append(": ").append(protocolVersion).append(" ").append(target);
152 if (proxy != null) {
153 buf.append(" via ").append(proxy);
154 }
155 buf.append(": ");
156 buf.append(request.getMethod()).append(" ").append(request.getRequestUri());
157 if (message != null && !TextUtils.isBlank(message)) {
158 buf.append(" -> ").append(message);
159 }
160 System.out.println(buf);
161 }
162
163 void execute() throws Exception {
164
165 client.start();
166
167 {
168 final HttpClientContext context = HttpClientContext.create();
169 context.setCredentialsProvider(credentialsProvider);
170
171 final SimpleHttpRequest options = SimpleHttpRequests.options(target, "*");
172 final Future<SimpleHttpResponse> future = client.execute(options, context, null);
173 try {
174 final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
175 final int code = response.getCode();
176 if (code == HttpStatus.SC_OK) {
177 logResult(TestResult.OK, options, Objects.toString(response.getFirstHeader("server")));
178 } else {
179 logResult(TestResult.NOK, options, "(status " + code + ")");
180 }
181 } catch (final ExecutionException ex) {
182 final Throwable cause = ex.getCause();
183 logResult(TestResult.NOK, options, "(" + cause.getMessage() + ")");
184 } catch (final TimeoutException ex) {
185 logResult(TestResult.NOK, options, "(time out)");
186 }
187 }
188
189 {
190 connManager.closeIdle(TimeValue.NEG_ONE_MILLISECOND);
191 final HttpClientContext context = HttpClientContext.create();
192 context.setCredentialsProvider(credentialsProvider);
193
194 final String[] requestUris = new String[] {"/", "/news.html", "/status.html"};
195 for (final String requestUri: requestUris) {
196 final SimpleHttpRequest httpGet = SimpleHttpRequests.get(target, requestUri);
197 final Future<SimpleHttpResponse> future = client.execute(httpGet, context, null);
198 try {
199 final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
200 final int code = response.getCode();
201 if (code == HttpStatus.SC_OK) {
202 logResult(TestResult.OK, httpGet, "200");
203 } else {
204 logResult(TestResult.NOK, httpGet, "(status " + code + ")");
205 }
206 } catch (final ExecutionException ex) {
207 final Throwable cause = ex.getCause();
208 logResult(TestResult.NOK, httpGet, "(" + cause.getMessage() + ")");
209 } catch (final TimeoutException ex) {
210 logResult(TestResult.NOK, httpGet, "(time out)");
211 }
212 }
213 }
214
215 {
216 connManager.closeIdle(TimeValue.NEG_ONE_MILLISECOND);
217 credentialsProvider.setCredentials(
218 new AuthScope("http", "otherhost", -1, "Restricted Files", null),
219 new UsernamePasswordCredentials("testuser", "nopassword".toCharArray()));
220 final HttpClientContext context = HttpClientContext.create();
221 context.setCredentialsProvider(credentialsProvider);
222
223 final SimpleHttpRequest httpGetSecret = SimpleHttpRequests.get(target, "/private/big-secret.txt");
224 final Future<SimpleHttpResponse> future = client.execute(httpGetSecret, context, null);
225 try {
226 final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
227 final int code = response.getCode();
228 if (code == HttpStatus.SC_UNAUTHORIZED) {
229 logResult(TestResult.OK, httpGetSecret, "401 (wrong target auth scope)");
230 } else {
231 logResult(TestResult.NOK, httpGetSecret, "(status " + code + ")");
232 }
233 } catch (final ExecutionException ex) {
234 final Throwable cause = ex.getCause();
235 logResult(TestResult.NOK, httpGetSecret, "(" + cause.getMessage() + ")");
236 } catch (final TimeoutException ex) {
237 logResult(TestResult.NOK, httpGetSecret, "(time out)");
238 }
239 }
240
241 {
242 connManager.closeIdle(TimeValue.NEG_ONE_MILLISECOND);
243 credentialsProvider.setCredentials(
244 new AuthScope(target),
245 new UsernamePasswordCredentials("testuser", "wrong password".toCharArray()));
246 final HttpClientContext context = HttpClientContext.create();
247 context.setCredentialsProvider(credentialsProvider);
248
249 final SimpleHttpRequest httpGetSecret = SimpleHttpRequests.get(target, "/private/big-secret.txt");
250 final Future<SimpleHttpResponse> future = client.execute(httpGetSecret, context, null);
251 try {
252 final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
253 final int code = response.getCode();
254 if (code == HttpStatus.SC_UNAUTHORIZED) {
255 logResult(TestResult.OK, httpGetSecret, "401 (wrong target creds)");
256 } else {
257 logResult(TestResult.NOK, httpGetSecret, "(status " + code + ")");
258 }
259 } catch (final ExecutionException ex) {
260 final Throwable cause = ex.getCause();
261 logResult(TestResult.NOK, httpGetSecret, "(" + cause.getMessage() + ")");
262 } catch (final TimeoutException ex) {
263 logResult(TestResult.NOK, httpGetSecret, "(time out)");
264 }
265 }
266
267 {
268 connManager.closeIdle(TimeValue.NEG_ONE_MILLISECOND);
269 credentialsProvider.setCredentials(
270 new AuthScope(target),
271 new UsernamePasswordCredentials("testuser", "nopassword".toCharArray()));
272 final HttpClientContext context = HttpClientContext.create();
273 context.setCredentialsProvider(credentialsProvider);
274
275 final SimpleHttpRequest httpGetSecret = SimpleHttpRequests.get(target, "/private/big-secret.txt");
276 final Future<SimpleHttpResponse> future = client.execute(httpGetSecret, context, null);
277 try {
278 final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
279 final int code = response.getCode();
280 if (code == HttpStatus.SC_OK) {
281 logResult(TestResult.OK, httpGetSecret, "200 (correct target creds)");
282 } else {
283 logResult(TestResult.NOK, httpGetSecret, "(status " + code + ")");
284 }
285 } catch (final ExecutionException ex) {
286 final Throwable cause = ex.getCause();
287 logResult(TestResult.NOK, httpGetSecret, "(" + cause.getMessage() + ")");
288 } catch (final TimeoutException ex) {
289 logResult(TestResult.NOK, httpGetSecret, "(time out)");
290 }
291 }
292
293 if (protocolVersion.lessEquals(HttpVersion.HTTP_1_1))
294 {
295 connManager.closeIdle(TimeValue.NEG_ONE_MILLISECOND);
296 credentialsProvider.setCredentials(
297 new AuthScope(target),
298 new UsernamePasswordCredentials("testuser", "nopassword".toCharArray()));
299 final HttpClientContext context = HttpClientContext.create();
300 context.setCredentialsProvider(credentialsProvider);
301
302 final SimpleHttpRequest httpGetSecret = SimpleHttpRequests.get(target, "/private/big-secret.txt");
303 httpGetSecret.setHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE);
304 final Future<SimpleHttpResponse> future = client.execute(httpGetSecret, context, null);
305 try {
306 final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
307 final int code = response.getCode();
308 if (code == HttpStatus.SC_OK) {
309 logResult(TestResult.OK, httpGetSecret, "200 (correct target creds / no keep-alive)");
310 } else {
311 logResult(TestResult.NOK, httpGetSecret, "(status " + code + ")");
312 }
313 } catch (final ExecutionException ex) {
314 final Throwable cause = ex.getCause();
315 logResult(TestResult.NOK, httpGetSecret, "(" + cause.getMessage() + ")");
316 } catch (final TimeoutException ex) {
317 logResult(TestResult.NOK, httpGetSecret, "(time out)");
318 }
319 }
320 }
321
322 }