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 org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
35 import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
36 import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
37 import org.apache.hc.client5.http.cache.CacheResponseStatus;
38 import org.apache.hc.client5.http.cache.HttpCacheContext;
39 import org.apache.hc.client5.http.config.TlsConfig;
40 import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
41 import org.apache.hc.client5.http.impl.cache.CacheConfig;
42 import org.apache.hc.client5.http.impl.cache.CachingHttpAsyncClients;
43 import org.apache.hc.client5.http.impl.cache.HeapResourceFactory;
44 import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
45 import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
46 import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
47 import org.apache.hc.core5.http.HttpHeaders;
48 import org.apache.hc.core5.http.HttpHost;
49 import org.apache.hc.core5.http.HttpRequest;
50 import org.apache.hc.core5.http.HttpResponse;
51 import org.apache.hc.core5.http.HttpStatus;
52 import org.apache.hc.core5.http.HttpVersion;
53 import org.apache.hc.core5.http2.HttpVersionPolicy;
54 import org.apache.hc.core5.ssl.SSLContexts;
55 import org.apache.hc.core5.util.TextUtils;
56 import org.apache.hc.core5.util.TimeValue;
57 import org.apache.hc.core5.util.Timeout;
58
59 public class CachingHttpAsyncClientCompatibilityTest {
60
61 public static void main(final String... args) throws Exception {
62 final CachingHttpAsyncClientCompatibilityTest[] tests = new CachingHttpAsyncClientCompatibilityTest[] {
63 new CachingHttpAsyncClientCompatibilityTest(
64 HttpVersion.HTTP_1_1, new HttpHost("http", "localhost", 8080)),
65 new CachingHttpAsyncClientCompatibilityTest(
66 HttpVersion.HTTP_2_0, new HttpHost("http", "localhost", 8080))
67 };
68 for (final CachingHttpAsyncClientCompatibilityTest test: tests) {
69 try {
70 test.execute();
71 } finally {
72 test.shutdown();
73 }
74 }
75 }
76
77 private static final Timeout TIMEOUT = Timeout.ofSeconds(5);
78
79 private final HttpVersion protocolVersion;
80 private final HttpHost target;
81 private final PoolingAsyncClientConnectionManager connManager;
82 private final CloseableHttpAsyncClient client;
83
84 CachingHttpAsyncClientCompatibilityTest(final HttpVersion protocolVersion, final HttpHost target) throws Exception {
85 this.protocolVersion = protocolVersion;
86 this.target = target;
87 this.connManager = PoolingAsyncClientConnectionManagerBuilder.create()
88 .setTlsStrategy(new DefaultClientTlsStrategy(SSLContexts.custom()
89 .loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray())
90 .build()))
91 .setDefaultTlsConfig(TlsConfig.custom()
92 .setVersionPolicy(this.protocolVersion == HttpVersion.HTTP_2 ?
93 HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1)
94 .build())
95 .build();
96 this.client = CachingHttpAsyncClients.custom()
97 .setCacheConfig(CacheConfig.custom()
98 .setMaxObjectSize(20480)
99 .setHeuristicCachingEnabled(true)
100 .build())
101 .setResourceFactory(HeapResourceFactory.INSTANCE)
102 .setConnectionManager(this.connManager)
103 .build();
104 }
105
106 void shutdown() throws Exception {
107 client.close();
108 }
109
110 enum TestResult {OK, NOK}
111
112 private void logResult(final TestResult result,
113 final HttpRequest request,
114 final HttpResponse response,
115 final String message) {
116 final StringBuilder buf = new StringBuilder();
117 buf.append(result);
118 if (buf.length() == 2) {
119 buf.append(" ");
120 }
121 buf.append(": ");
122 if (response != null && response.getVersion() != null) {
123 buf.append(response.getVersion()).append(" ");
124 } else {
125 buf.append(protocolVersion).append(" ");
126 }
127 buf.append(target);
128 buf.append(": ");
129 buf.append(request.getMethod()).append(" ").append(request.getRequestUri());
130 if (message != null && !TextUtils.isBlank(message)) {
131 buf.append(" -> ").append(message);
132 }
133 System.out.println(buf);
134 }
135
136 void execute() throws InterruptedException {
137
138 client.start();
139
140 {
141 final HttpCacheContext context = HttpCacheContext.create();
142 final SimpleHttpRequest options = SimpleRequestBuilder.options()
143 .setHttpHost(target)
144 .setPath("*")
145 .build();
146 final Future<SimpleHttpResponse> future = client.execute(options, context, null);
147 try {
148 final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
149 final int code = response.getCode();
150 if (code == HttpStatus.SC_OK) {
151 logResult(TestResult.OK, options, response, Objects.toString(response.getFirstHeader("server")));
152 } else {
153 logResult(TestResult.NOK, options, response, "(status " + code + ")");
154 }
155 } catch (final ExecutionException ex) {
156 final Throwable cause = ex.getCause();
157 logResult(TestResult.NOK, options, null, "(" + cause.getMessage() + ")");
158 } catch (final TimeoutException ex) {
159 logResult(TestResult.NOK, options, null, "(time out)");
160 }
161 }
162
163
164 {
165 connManager.closeIdle(TimeValue.NEG_ONE_MILLISECOND);
166 final HttpCacheContext context = HttpCacheContext.create();
167
168 final String[] links = {"/", "/css/hc-maven.css", "/images/logos/httpcomponents.png"};
169
170 for (final String link: links) {
171 final SimpleHttpRequest httpGet1 = SimpleRequestBuilder.get()
172 .setHttpHost(target)
173 .setPath(link)
174 .build();
175 final Future<SimpleHttpResponse> linkFuture1 = client.execute(httpGet1, context, null);
176 try {
177 final SimpleHttpResponse response = linkFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
178 final int code = response.getCode();
179 final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
180 if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.CACHE_MISS) {
181 logResult(TestResult.OK, httpGet1, response, "200, " + cacheResponseStatus);
182 } else {
183 logResult(TestResult.NOK, httpGet1, response, "(status " + code + ", " + cacheResponseStatus + ")");
184 }
185 } catch (final ExecutionException ex) {
186 final Throwable cause = ex.getCause();
187 logResult(TestResult.NOK, httpGet1, null, "(" + cause.getMessage() + ")");
188 } catch (final TimeoutException ex) {
189 logResult(TestResult.NOK, httpGet1, null,"(time out)");
190 }
191
192 final SimpleHttpRequest httpGet2 = SimpleRequestBuilder.get()
193 .setHttpHost(target)
194 .setPath(link)
195 .build();
196 final Future<SimpleHttpResponse> linkFuture2 = client.execute(httpGet2, context, null);
197 try {
198 final SimpleHttpResponse response = linkFuture2.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
199 final int code = response.getCode();
200 final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
201 if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.CACHE_HIT) {
202 logResult(TestResult.OK, httpGet2, response, "200, " + cacheResponseStatus);
203 } else {
204 logResult(TestResult.NOK, httpGet2, response, "(status " + code + ", " + cacheResponseStatus + ")");
205 }
206 } catch (final ExecutionException ex) {
207 final Throwable cause = ex.getCause();
208 logResult(TestResult.NOK, httpGet2, null, "(" + cause.getMessage() + ")");
209 } catch (final TimeoutException ex) {
210 logResult(TestResult.NOK, httpGet2, null,"(time out)");
211 }
212
213 Thread.sleep(2000);
214
215 final SimpleHttpRequest httpGet3 = SimpleRequestBuilder.get()
216 .setHttpHost(target)
217 .setPath(link)
218 .setHeader(HttpHeaders.CACHE_CONTROL, "max-age=0")
219 .build();
220 final Future<SimpleHttpResponse> linkFuture3 = client.execute(httpGet3, context, null);
221 try {
222 final SimpleHttpResponse response = linkFuture3.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
223 final int code = response.getCode();
224 final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
225 if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.VALIDATED) {
226 logResult(TestResult.OK, httpGet3, response, "200, " + cacheResponseStatus);
227 } else {
228 logResult(TestResult.NOK, httpGet3, response, "(status " + code + ", " + cacheResponseStatus + ")");
229 }
230 } catch (final ExecutionException ex) {
231 final Throwable cause = ex.getCause();
232 logResult(TestResult.NOK, httpGet3, null, "(" + cause.getMessage() + ")");
233 } catch (final TimeoutException ex) {
234 logResult(TestResult.NOK, httpGet3, null,"(time out)");
235 }
236 }
237 }
238 }
239
240 }