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.http.impl.cache;
28
29
30 import static org.junit.jupiter.api.Assertions.assertEquals;
31 import static org.junit.jupiter.api.Assertions.assertFalse;
32 import static org.junit.jupiter.api.Assertions.assertNotNull;
33 import static org.junit.jupiter.api.Assertions.assertNull;
34 import static org.junit.jupiter.api.Assertions.assertSame;
35
36 import java.time.Instant;
37 import java.util.Map;
38
39 import org.apache.hc.client5.http.cache.HeaderConstants;
40 import org.apache.hc.client5.http.cache.HttpCacheEntry;
41 import org.apache.hc.client5.http.classic.methods.HttpDelete;
42 import org.apache.hc.client5.http.classic.methods.HttpGet;
43 import org.apache.hc.client5.http.classic.methods.HttpHead;
44 import org.apache.hc.client5.http.classic.methods.HttpOptions;
45 import org.apache.hc.client5.http.classic.methods.HttpPost;
46 import org.apache.hc.client5.http.classic.methods.HttpTrace;
47 import org.apache.hc.client5.http.utils.DateUtils;
48 import org.apache.hc.core5.http.Header;
49 import org.apache.hc.core5.http.HttpHost;
50 import org.apache.hc.core5.http.HttpRequest;
51 import org.apache.hc.core5.http.HttpResponse;
52 import org.apache.hc.core5.http.HttpStatus;
53 import org.apache.hc.core5.http.message.BasicHeader;
54 import org.apache.hc.core5.http.message.BasicHttpResponse;
55 import org.apache.hc.core5.util.ByteArrayBuffer;
56 import org.junit.jupiter.api.BeforeEach;
57 import org.junit.jupiter.api.Test;
58
59 public class TestBasicHttpCache {
60
61 private BasicHttpCache impl;
62 private SimpleHttpCacheStorage backing;
63
64 @BeforeEach
65 public void setUp() throws Exception {
66 backing = new SimpleHttpCacheStorage();
67 impl = new BasicHttpCache(new HeapResourceFactory(), backing);
68 }
69
70 @Test
71 public void testDoNotFlushCacheEntriesOnGet() throws Exception {
72 final HttpHost host = new HttpHost("foo.example.com");
73 final HttpRequest req = new HttpGet("/bar");
74 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, req);
75 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
76
77 backing.map.put(key, entry);
78
79 impl.flushCacheEntriesFor(host, req);
80
81 assertEquals(entry, backing.map.get(key));
82 }
83
84 @Test
85 public void testDoNotFlushCacheEntriesOnHead() throws Exception {
86 final HttpHost host = new HttpHost("foo.example.com");
87 final HttpRequest req = new HttpHead("/bar");
88 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, req);
89 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
90
91 backing.map.put(key, entry);
92
93 impl.flushCacheEntriesFor(host, req);
94
95 assertEquals(entry, backing.map.get(key));
96 }
97
98 @Test
99 public void testDoNotFlushCacheEntriesOnOptions() throws Exception {
100 final HttpHost host = new HttpHost("foo.example.com");
101 final HttpRequest req = new HttpOptions("/bar");
102 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, req);
103 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
104
105 backing.map.put(key, entry);
106
107 impl.flushCacheEntriesFor(host, req);
108
109 assertEquals(entry, backing.map.get(key));
110 }
111
112 @Test
113 public void testDoNotFlushCacheEntriesOnTrace() throws Exception {
114 final HttpHost host = new HttpHost("foo.example.com");
115 final HttpRequest req = new HttpTrace("/bar");
116 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, req);
117 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
118
119 backing.map.put(key, entry);
120
121 impl.flushCacheEntriesFor(host, req);
122
123 assertEquals(entry, backing.map.get(key));
124 }
125
126 @Test
127 public void testFlushContentLocationEntryIfUnSafeRequest()
128 throws Exception {
129 final HttpHost host = new HttpHost("foo.example.com");
130 final HttpRequest req = new HttpPost("/foo");
131 final HttpResponse resp = HttpTestUtils.make200Response();
132 resp.setHeader("Content-Location", "/bar");
133 resp.setHeader(HeaderConstants.ETAG, "\"etag\"");
134 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, new HttpGet("/bar"));
135
136 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
137 new BasicHeader("Date", DateUtils.formatStandardDate(Instant.now())),
138 new BasicHeader("ETag", "\"old-etag\"")
139 });
140
141 backing.map.put(key, entry);
142
143 impl.flushCacheEntriesInvalidatedByExchange(host, req, resp);
144
145 assertNull(backing.map.get(key));
146 }
147
148 @Test
149 public void testDoNotFlushContentLocationEntryIfSafeRequest()
150 throws Exception {
151 final HttpHost host = new HttpHost("foo.example.com");
152 final HttpRequest req = new HttpGet("/foo");
153 final HttpResponse resp = HttpTestUtils.make200Response();
154 resp.setHeader("Content-Location", "/bar");
155 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, new HttpGet("/bar"));
156
157 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
158 new BasicHeader("Date", DateUtils.formatStandardDate(Instant.now())),
159 new BasicHeader("ETag", "\"old-etag\"")
160 });
161
162 backing.map.put(key, entry);
163
164 impl.flushCacheEntriesInvalidatedByExchange(host, req, resp);
165
166 assertEquals(entry, backing.map.get(key));
167 }
168
169 @Test
170 public void testCanFlushCacheEntriesAtUri() throws Exception {
171 final HttpHost host = new HttpHost("foo.example.com");
172 final HttpRequest req = new HttpDelete("/bar");
173 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, req);
174 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
175
176 backing.map.put(key, entry);
177
178 impl.flushCacheEntriesFor(host, req);
179
180 assertNull(backing.map.get(key));
181 }
182
183 @Test
184 public void testStoreInCachePutsNonVariantEntryInPlace() throws Exception {
185 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
186 assertFalse(entry.hasVariants());
187 final HttpHost host = new HttpHost("foo.example.com");
188 final HttpRequest req = new HttpGet("http://foo.example.com/bar");
189 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, req);
190
191 impl.storeInCache(key, host, req, entry);
192 assertSame(entry, backing.map.get(key));
193 }
194
195 @Test
196 public void testGetCacheEntryReturnsNullOnCacheMiss() throws Exception {
197 final HttpHost host = new HttpHost("foo.example.com");
198 final HttpRequest request = new HttpGet("http://foo.example.com/bar");
199 final HttpCacheEntry result = impl.getCacheEntry(host, request);
200 assertNull(result);
201 }
202
203 @Test
204 public void testGetCacheEntryFetchesFromCacheOnCacheHitIfNoVariants() throws Exception {
205 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
206 assertFalse(entry.hasVariants());
207 final HttpHost host = new HttpHost("foo.example.com");
208 final HttpRequest request = new HttpGet("http://foo.example.com/bar");
209
210 final String key = CacheKeyGenerator.INSTANCE.generateKey(host, request);
211
212 backing.map.put(key,entry);
213
214 final HttpCacheEntry result = impl.getCacheEntry(host, request);
215 assertSame(entry, result);
216 }
217
218 @Test
219 public void testGetCacheEntryReturnsNullIfNoVariantInCache() throws Exception {
220 final HttpHost host = new HttpHost("foo.example.com");
221
222 final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
223 origRequest.setHeader("Accept-Encoding","gzip");
224
225 final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
226 final HttpResponse origResponse = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
227 origResponse.setHeader("Date", DateUtils.formatStandardDate(Instant.now()));
228 origResponse.setHeader("Cache-Control", "max-age=3600, public");
229 origResponse.setHeader("ETag", "\"etag\"");
230 origResponse.setHeader("Vary", "Accept-Encoding");
231 origResponse.setHeader("Content-Encoding","gzip");
232
233 impl.createCacheEntry(host, origRequest, origResponse, buf, Instant.now(), Instant.now());
234
235 final HttpRequest request = new HttpGet("http://foo.example.com/bar");
236 final HttpCacheEntry result = impl.getCacheEntry(host, request);
237 assertNull(result);
238 }
239
240 @Test
241 public void testGetCacheEntryReturnsVariantIfPresentInCache() throws Exception {
242 final HttpHost host = new HttpHost("foo.example.com");
243
244 final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
245 origRequest.setHeader("Accept-Encoding","gzip");
246
247 final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
248 final HttpResponse origResponse = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
249 origResponse.setHeader("Date", DateUtils.formatStandardDate(Instant.now()));
250 origResponse.setHeader("Cache-Control", "max-age=3600, public");
251 origResponse.setHeader("ETag", "\"etag\"");
252 origResponse.setHeader("Vary", "Accept-Encoding");
253 origResponse.setHeader("Content-Encoding","gzip");
254
255 impl.createCacheEntry(host, origRequest, origResponse, buf, Instant.now(), Instant.now());
256
257 final HttpRequest request = new HttpGet("http://foo.example.com/bar");
258 request.setHeader("Accept-Encoding","gzip");
259 final HttpCacheEntry result = impl.getCacheEntry(host, request);
260 assertNotNull(result);
261 }
262
263 @Test
264 public void testGetVariantCacheEntriesReturnsEmptySetOnNoVariants() throws Exception {
265 final HttpHost host = new HttpHost("foo.example.com");
266 final HttpRequest request = new HttpGet("http://foo.example.com/bar");
267
268 final Map<String,Variant> variants = impl.getVariantCacheEntriesWithEtags(host, request);
269
270 assertNotNull(variants);
271 assertEquals(0, variants.size());
272 }
273
274 @Test
275 public void testGetVariantCacheEntriesReturnsAllVariants() throws Exception {
276 final HttpHost host = new HttpHost("foo.example.com");
277 final HttpRequest req1 = new HttpGet("http://foo.example.com/bar");
278 req1.setHeader("Accept-Encoding", "gzip");
279
280 final HttpResponse resp1 = HttpTestUtils.make200Response();
281 resp1.setHeader("Date", DateUtils.formatStandardDate(Instant.now()));
282 resp1.setHeader("Cache-Control", "max-age=3600, public");
283 resp1.setHeader("ETag", "\"etag1\"");
284 resp1.setHeader("Vary", "Accept-Encoding");
285 resp1.setHeader("Content-Encoding","gzip");
286 resp1.setHeader("Vary", "Accept-Encoding");
287
288 final HttpRequest req2 = new HttpGet("http://foo.example.com/bar");
289 req2.setHeader("Accept-Encoding", "identity");
290
291 final HttpResponse resp2 = HttpTestUtils.make200Response();
292 resp2.setHeader("Date", DateUtils.formatStandardDate(Instant.now()));
293 resp2.setHeader("Cache-Control", "max-age=3600, public");
294 resp2.setHeader("ETag", "\"etag2\"");
295 resp2.setHeader("Vary", "Accept-Encoding");
296 resp2.setHeader("Content-Encoding","gzip");
297 resp2.setHeader("Vary", "Accept-Encoding");
298
299 impl.createCacheEntry(host, req1, resp1, null, Instant.now(), Instant.now());
300 impl.createCacheEntry(host, req2, resp2, null, Instant.now(), Instant.now());
301
302 final Map<String,Variant> variants = impl.getVariantCacheEntriesWithEtags(host, req1);
303
304 assertNotNull(variants);
305 assertEquals(2, variants.size());
306
307 }
308
309 }