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.ArrayList;
30 import java.util.List;
31 import java.util.Objects;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34
35 import javax.net.ssl.SSLContext;
36
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.classic.methods.HttpGet;
40 import org.apache.hc.client5.http.classic.methods.HttpOptions;
41 import org.apache.hc.client5.http.impl.cache.CacheConfig;
42 import org.apache.hc.client5.http.impl.cache.CachingHttpClients;
43 import org.apache.hc.client5.http.impl.cache.HeapResourceFactory;
44 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
45 import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
46 import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
47 import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
48 import org.apache.hc.core5.http.ClassicHttpResponse;
49 import org.apache.hc.core5.http.Header;
50 import org.apache.hc.core5.http.HttpHost;
51 import org.apache.hc.core5.http.HttpRequest;
52 import org.apache.hc.core5.http.HttpStatus;
53 import org.apache.hc.core5.http.io.entity.EntityUtils;
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
58 public class CachingHttpClientCompatibilityTest {
59
60 public static void main(final String... args) throws Exception {
61 final CachingHttpClientCompatibilityTest[] tests = new CachingHttpClientCompatibilityTest[] {
62 new CachingHttpClientCompatibilityTest(
63 new HttpHost("http", "localhost", 8080))
64 };
65 for (final CachingHttpClientCompatibilityTest test: tests) {
66 try {
67 test.execute();
68 } finally {
69 test.shutdown();
70 }
71 }
72 }
73
74 private final HttpHost target;
75 private final PoolingHttpClientConnectionManager connManager;
76 private final CloseableHttpClient client;
77
78 CachingHttpClientCompatibilityTest(final HttpHost target) throws Exception {
79 this.target = target;
80 final SSLContext sslContext = SSLContexts.custom()
81 .loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray()).build();
82 this.connManager = PoolingHttpClientConnectionManagerBuilder.create()
83 .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext))
84 .build();
85 this.client = CachingHttpClients.custom()
86 .setCacheConfig(CacheConfig.custom()
87 .setMaxObjectSize(20480)
88 .build())
89 .setResourceFactory(HeapResourceFactory.INSTANCE)
90 .setConnectionManager(this.connManager)
91 .build();
92 }
93
94 void shutdown() throws Exception {
95 client.close();
96 }
97
98 enum TestResult {OK, NOK}
99
100 private void logResult(final TestResult result, final HttpRequest request, final String message) {
101 final StringBuilder buf = new StringBuilder();
102 buf.append(result);
103 if (buf.length() == 2) {
104 buf.append(" ");
105 }
106 buf.append(": ").append(target);
107 buf.append(": ");
108 buf.append(request.getMethod()).append(" ").append(request.getRequestUri());
109 if (message != null && !TextUtils.isBlank(message)) {
110 buf.append(" -> ").append(message);
111 }
112 System.out.println(buf);
113 }
114
115 void execute() {
116
117
118 {
119 final HttpCacheContext context = HttpCacheContext.create();
120 final HttpOptions options = new HttpOptions("*");
121 try (final ClassicHttpResponse response = client.executeOpen(target, options, context)) {
122 final int code = response.getCode();
123 EntityUtils.consume(response.getEntity());
124 if (code == HttpStatus.SC_OK) {
125 logResult(TestResult.OK, options, Objects.toString(response.getFirstHeader("server")));
126 } else {
127 logResult(TestResult.NOK, options, "(status " + code + ")");
128 }
129 } catch (final Exception ex) {
130 logResult(TestResult.NOK, options, "(" + ex.getMessage() + ")");
131 }
132 }
133
134 {
135 connManager.closeIdle(TimeValue.NEG_ONE_MILLISECOND);
136 final HttpCacheContext context = HttpCacheContext.create();
137 final Pattern linkPattern = Pattern.compile("^<(.*)>;rel=preload$");
138 final List<String> links = new ArrayList<>();
139 final HttpGet getRoot1 = new HttpGet("/");
140 try (ClassicHttpResponse response = client.executeOpen(target, getRoot1, context)) {
141 final int code = response.getCode();
142 final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
143 EntityUtils.consume(response.getEntity());
144 if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.CACHE_MISS) {
145 logResult(TestResult.OK, getRoot1, "200, " + cacheResponseStatus);
146 } else {
147 logResult(TestResult.NOK, getRoot1, "(status " + code + ", " + cacheResponseStatus + ")");
148 }
149 for (final Header header: response.getHeaders("Link")) {
150 final Matcher matcher = linkPattern.matcher(header.getValue());
151 if (matcher.matches()) {
152 links.add(matcher.group(1));
153 }
154 }
155 } catch (final Exception ex) {
156 logResult(TestResult.NOK, getRoot1, "(" + ex.getMessage() + ")");
157 }
158
159 for (final String link: links) {
160 final HttpGet getLink = new HttpGet(link);
161 try (ClassicHttpResponse response = client.executeOpen(target, getLink, context)) {
162 final int code = response.getCode();
163 final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
164 EntityUtils.consume(response.getEntity());
165 if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.CACHE_MISS) {
166 logResult(TestResult.OK, getRoot1, "200, " + cacheResponseStatus);
167 } else {
168 logResult(TestResult.NOK, getRoot1, "(status " + code + ", " + cacheResponseStatus + ")");
169 }
170 } catch (final Exception ex) {
171 logResult(TestResult.NOK, getLink, "(" + ex.getMessage() + ")");
172 }
173 }
174 final HttpGet getRoot2 = new HttpGet("/");
175 try (ClassicHttpResponse response = client.executeOpen(target, getRoot2, context)) {
176 final int code = response.getCode();
177 final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
178 EntityUtils.consume(response.getEntity());
179 if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.VALIDATED) {
180 logResult(TestResult.OK, getRoot2, "200, " + cacheResponseStatus);
181 } else {
182 logResult(TestResult.NOK, getRoot2, "(status " + code + ", " + cacheResponseStatus + ")");
183 }
184 } catch (final Exception ex) {
185 logResult(TestResult.NOK, getRoot2, "(" + ex.getMessage() + ")");
186 }
187 for (final String link: links) {
188 final HttpGet getLink = new HttpGet(link);
189 try (ClassicHttpResponse response = client.executeOpen(target, getLink, context)) {
190 final int code = response.getCode();
191 final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
192 EntityUtils.consume(response.getEntity());
193 if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.VALIDATED) {
194 logResult(TestResult.OK, getRoot2, "200, " + cacheResponseStatus);
195 } else {
196 logResult(TestResult.NOK, getRoot2, "(status " + code + ", " + cacheResponseStatus + ")");
197 }
198 } catch (final Exception ex) {
199 logResult(TestResult.NOK, getLink, "(" + ex.getMessage() + ")");
200 }
201 }
202 }
203 }
204
205 }