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 import static org.junit.jupiter.api.Assertions.assertFalse;
30 import static org.junit.jupiter.api.Assertions.assertTrue;
31
32 import java.time.Duration;
33 import java.time.Instant;
34 import java.time.temporal.ChronoUnit;
35 import java.util.Random;
36
37 import org.apache.hc.client5.http.auth.StandardAuthScheme;
38 import org.apache.hc.client5.http.classic.methods.HttpOptions;
39 import org.apache.hc.client5.http.utils.DateUtils;
40 import org.apache.hc.core5.http.HttpHeaders;
41 import org.apache.hc.core5.http.HttpRequest;
42 import org.apache.hc.core5.http.HttpResponse;
43 import org.apache.hc.core5.http.HttpStatus;
44 import org.apache.hc.core5.http.HttpVersion;
45 import org.apache.hc.core5.http.Method;
46 import org.apache.hc.core5.http.message.BasicHttpRequest;
47 import org.apache.hc.core5.http.message.BasicHttpResponse;
48 import org.junit.jupiter.api.Assertions;
49 import org.junit.jupiter.api.BeforeEach;
50 import org.junit.jupiter.api.Test;
51
52 public class TestResponseCachingPolicy {
53
54 private ResponseCachingPolicy policy;
55 private HttpResponse response;
56 private HttpRequest request;
57 private final int[] acceptableCodes = new int[] { HttpStatus.SC_OK,
58 HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION, HttpStatus.SC_MULTIPLE_CHOICES,
59 HttpStatus.SC_MOVED_PERMANENTLY, HttpStatus.SC_GONE };
60 private Instant now;
61 private Instant tenSecondsFromNow;
62 private Instant sixSecondsAgo;
63 private ResponseCacheControl responseCacheControl;
64
65 @BeforeEach
66 public void setUp() throws Exception {
67 now = Instant.now();
68 sixSecondsAgo = now.minusSeconds(6);
69 tenSecondsFromNow = now.plusSeconds(10);
70
71 policy = new ResponseCachingPolicy(true, false, false);
72 request = new BasicHttpRequest("GET","/");
73 response = new BasicHttpResponse(HttpStatus.SC_OK, "");
74 response.setHeader("Date", DateUtils.formatStandardDate(Instant.now()));
75 response.setHeader("Content-Length", "0");
76 responseCacheControl = ResponseCacheControl.builder().build();
77 }
78
79 @Test
80 public void testGetCacheable() {
81 policy = new ResponseCachingPolicy(true, false, false);
82 request = new BasicHttpRequest(Method.GET, "/");
83 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
84 }
85
86 @Test
87 public void testHeadCacheable() {
88 policy = new ResponseCachingPolicy(true, false, false);
89 request = new BasicHttpRequest(Method.HEAD, "/");
90 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
91 }
92
93 @Test
94 public void testArbitraryMethodNotCacheable() {
95 request = new BasicHttpRequest("PUT", "/");
96 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
97
98 request = new BasicHttpRequest("huh", "/");
99 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
100 }
101
102 @Test
103 public void testResponsesToRequestsWithAuthorizationHeadersAreNotCacheableBySharedCache() {
104 request = new BasicHttpRequest("GET","/");
105 request.setHeader("Authorization", StandardAuthScheme.BASIC + " dXNlcjpwYXNzd2Q=");
106 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
107 }
108
109 @Test
110 public void testResponsesToRequestsWithAuthorizationHeadersAreCacheableByNonSharedCache() {
111 policy = new ResponseCachingPolicy(false, false, false);
112 request = new BasicHttpRequest("GET","/");
113 request.setHeader("Authorization", StandardAuthScheme.BASIC + " dXNlcjpwYXNzd2Q=");
114 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
115 }
116
117 @Test
118 public void testAuthorizedResponsesWithSMaxAgeAreCacheable() {
119 request = new BasicHttpRequest("GET","/");
120 request.setHeader("Authorization", StandardAuthScheme.BASIC + " dXNlcjpwYXNzd2Q=");
121 responseCacheControl = ResponseCacheControl.builder()
122 .setSharedMaxAge(3600)
123 .build();
124
125 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
126 }
127
128 @Test
129 public void testAuthorizedResponsesWithCacheControlPublicAreCacheable() {
130 request = new BasicHttpRequest("GET","/");
131 request.setHeader("Authorization", StandardAuthScheme.BASIC + " dXNlcjpwYXNzd2Q=");
132 responseCacheControl = ResponseCacheControl.builder()
133 .setCachePublic(true)
134 .build();
135 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
136 }
137
138 @Test
139 public void testAuthorizedResponsesWithCacheControlMaxAgeAreNotCacheable() {
140 request = new BasicHttpRequest("GET","/");
141 request.setHeader("Authorization", StandardAuthScheme.BASIC + " dXNlcjpwYXNzd2Q=");
142 responseCacheControl = ResponseCacheControl.builder()
143 .setMaxAge(3600)
144 .build();
145 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
146 }
147
148 @Test
149 public void test203ResponseCodeIsCacheable() {
150 response.setCode(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION);
151 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
152 }
153
154 @Test
155 public void test206ResponseCodeIsNotCacheable() {
156 response.setCode(HttpStatus.SC_PARTIAL_CONTENT);
157 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
158 }
159
160 @Test
161 public void test300ResponseCodeIsCacheable() {
162 response.setCode(HttpStatus.SC_MULTIPLE_CHOICES);
163 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
164 }
165
166 @Test
167 public void test301ResponseCodeIsCacheable() {
168 response.setCode(HttpStatus.SC_MOVED_PERMANENTLY);
169 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
170 }
171
172 @Test
173 public void test410ResponseCodeIsCacheable() {
174 response.setCode(HttpStatus.SC_GONE);
175 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
176 }
177
178 @Test
179 public void testPlain302ResponseCodeIsNotCacheable() {
180 response.setCode(HttpStatus.SC_MOVED_TEMPORARILY);
181 response.removeHeaders("Expires");
182 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
183 }
184
185 @Test
186 public void testPlain303ResponseCodeIsNotCacheableUnderDefaultBehavior() {
187 response.setCode(HttpStatus.SC_SEE_OTHER);
188 response.removeHeaders("Expires");
189 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
190 }
191
192 @Test
193 public void testPlain303ResponseCodeIsNotCacheableEvenIf303CachingEnabled() {
194 policy = new ResponseCachingPolicy(true, false, true);
195 response.setCode(HttpStatus.SC_SEE_OTHER);
196 response.removeHeaders("Expires");
197 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
198 }
199
200
201 @Test
202 public void testPlain307ResponseCodeIsNotCacheable() {
203 response.setCode(HttpStatus.SC_TEMPORARY_REDIRECT);
204 response.removeHeaders("Expires");
205 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
206 }
207
208 @Test
209 public void testNon206WithExplicitExpiresIsCacheable() {
210 final int status = getRandomStatus();
211 response.setCode(status);
212 response.setHeader("Expires", DateUtils.formatStandardDate(Instant.now().plus(1, ChronoUnit.HOURS)));
213 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
214 }
215
216 @Test
217 public void testNon206WithMaxAgeIsCacheable() {
218 final int status = getRandomStatus();
219 response.setCode(status);
220 responseCacheControl = ResponseCacheControl.builder()
221 .setMaxAge(0)
222 .build();
223 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
224 }
225
226 @Test
227 public void testMissingCacheControlHeader() {
228 final int status = getRandomStatus();
229 response.setCode(status);
230 response.removeHeaders(HttpHeaders.CACHE_CONTROL);
231 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
232 }
233
234 @Test
235 public void testNon206WithSMaxAgeIsCacheable() {
236 final int status = getRandomStatus();
237 response.setCode(status);
238 responseCacheControl = ResponseCacheControl.builder()
239 .setSharedMaxAge(1)
240 .build();
241 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
242 }
243
244 @Test
245 public void testNon206WithMustRevalidateIsCacheable() {
246 final int status = getRandomStatus();
247 response.setCode(status);
248 responseCacheControl = ResponseCacheControl.builder()
249 .setMustRevalidate(true)
250 .build();
251 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
252 }
253
254 @Test
255 public void testNon206WithProxyRevalidateIsCacheable() {
256 final int status = getRandomStatus();
257 response.setCode(status);
258 responseCacheControl = ResponseCacheControl.builder()
259 .setProxyRevalidate(true)
260 .build();
261 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
262 }
263
264 @Test
265 public void testNon206WithPublicCacheControlIsCacheable() {
266 final int status = getRandomStatus();
267 response.setCode(status);
268 responseCacheControl = ResponseCacheControl.builder()
269 .setCachePublic(true)
270 .build();
271 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
272 }
273
274 @Test
275 public void testNon206WithPrivateCacheControlIsNotCacheableBySharedCache() {
276 final int status = getRandomStatus();
277 response.setCode(status);
278 responseCacheControl = ResponseCacheControl.builder()
279 .setCachePrivate(true)
280 .build();
281 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
282 }
283
284 @Test
285 public void test200ResponseWithPrivateCacheControlIsCacheableByNonSharedCache() {
286 policy = new ResponseCachingPolicy(false, false, false);
287 response.setCode(HttpStatus.SC_OK);
288 responseCacheControl = ResponseCacheControl.builder()
289 .setCachePrivate(true)
290 .build();
291 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
292 }
293
294 @Test
295 public void testControlNoCacheCacheable() {
296 responseCacheControl = ResponseCacheControl.builder()
297 .setNoCache(true)
298 .build();
299
300 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
301 }
302
303 @Test
304 public void testControlNoStoreNotCacheable() {
305 responseCacheControl = ResponseCacheControl.builder()
306 .setNoStore(true)
307 .build();
308
309 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
310 }
311
312 @Test
313 public void testControlNoStoreEmbeddedInListCacheable() {
314 responseCacheControl = ResponseCacheControl.builder()
315 .setCachePublic(true)
316 .setNoStore(true)
317 .build();
318
319 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
320 }
321
322 @Test
323 public void testControlNoCacheEmbeddedInListCacheable() {
324 responseCacheControl = ResponseCacheControl.builder()
325 .setCachePublic(true)
326 .setNoCache(true)
327 .build();
328
329 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
330 }
331
332 @Test
333 public void testControlNoCacheEmbeddedInListAfterFirstHeaderCacheable() {
334 responseCacheControl = ResponseCacheControl.builder()
335 .setMaxAge(20)
336 .setCachePublic(true)
337 .setNoCache(true)
338 .build();
339
340 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
341 }
342
343 @Test
344 public void testControlNoStoreEmbeddedInListAfterFirstHeaderCacheable() {
345 responseCacheControl = ResponseCacheControl.builder()
346 .setMaxAge(20)
347 .setCachePublic(true)
348 .setNoStore(true)
349 .build();
350
351 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
352 }
353
354 @Test
355 public void testControlAnyCacheControlCacheable() {
356 responseCacheControl = ResponseCacheControl.builder()
357 .setMaxAge(10)
358 .build();
359
360 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
361
362 response = new BasicHttpResponse(HttpStatus.SC_OK, "");
363 response.setHeader("Date", DateUtils.formatStandardDate(Instant.now()));
364 response.setHeader("Content-Length", "0");
365 responseCacheControl = ResponseCacheControl.builder()
366 .build();
367
368 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
369 }
370
371 @Test
372 public void testControlWithout200Cacheable() {
373 HttpResponse response404 = new BasicHttpResponse(HttpStatus.SC_NOT_FOUND, "");
374
375 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response404));
376
377 response404 = new BasicHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "");
378
379 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response404));
380 }
381
382 @Test
383 public void testVaryStarIsNotCacheable() {
384 response.setHeader("Vary", "*");
385 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
386 }
387
388 @Test
389 public void testVaryStarIsNotCacheableUsingSharedPublicCache() {
390 policy = new ResponseCachingPolicy(true, false, false);
391
392 request.setHeader("Authorization", StandardAuthScheme.BASIC + " QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
393 response.setHeader("Vary", "*");
394 responseCacheControl = ResponseCacheControl.builder()
395 .setCachePublic(true)
396 .build();
397 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
398 }
399
400 @Test
401 public void testRequestWithVaryHeaderCacheable() {
402 response.addHeader("Vary", "Accept-Encoding");
403 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
404 }
405
406 @Test
407 public void testIsArbitraryMethodCacheableUsingSharedPublicCache() {
408 policy = new ResponseCachingPolicy(true, false, false);
409
410 request = new HttpOptions("http://foo.example.com/");
411 request.setHeader("Authorization", StandardAuthScheme.BASIC + " QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
412 response.setCode(HttpStatus.SC_NO_CONTENT);
413 responseCacheControl = ResponseCacheControl.builder()
414 .setCachePublic(true)
415 .build();
416
417 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
418 }
419
420 @Test
421 public void testResponsesWithMultipleAgeHeadersAreCacheable() {
422 response.addHeader("Age", "3");
423 response.addHeader("Age", "5");
424 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
425 }
426
427 @Test
428 public void testResponsesWithMultipleAgeHeadersAreNotCacheableUsingSharedPublicCache() {
429 policy = new ResponseCachingPolicy(true, false, false);
430
431 request.setHeader("Authorization", StandardAuthScheme.BASIC + " QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
432 response.addHeader("Age", "3");
433 response.addHeader("Age", "5");
434 responseCacheControl = ResponseCacheControl.builder()
435 .setCachePublic(true)
436 .build();
437 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
438 }
439
440 @Test
441 public void testResponsesWithMultipleDateHeadersAreNotCacheable() {
442 response.addHeader("Date", DateUtils.formatStandardDate(now));
443 response.addHeader("Date", DateUtils.formatStandardDate(sixSecondsAgo));
444 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
445 }
446
447 @Test
448 public void testResponsesWithMultipleDateHeadersAreNotCacheableUsingSharedPublicCache() {
449 policy = new ResponseCachingPolicy(true, false, false);
450
451 request.setHeader("Authorization", StandardAuthScheme.BASIC + " QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
452 response.addHeader("Date", DateUtils.formatStandardDate(now));
453 response.addHeader("Date", DateUtils.formatStandardDate(sixSecondsAgo));
454 responseCacheControl = ResponseCacheControl.builder()
455 .setCachePublic(true)
456 .build();
457 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
458 }
459
460 @Test
461 public void testResponsesWithMalformedDateHeadersAreNotCacheable() {
462 response.addHeader("Date", "garbage");
463 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
464 }
465
466 @Test
467 public void testResponsesWithMalformedDateHeadersAreNotCacheableUsingSharedPublicCache() {
468 policy = new ResponseCachingPolicy(true, false, false);
469
470 request.setHeader("Authorization", StandardAuthScheme.BASIC + " QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
471 response.addHeader("Date", "garbage");
472 responseCacheControl = ResponseCacheControl.builder()
473 .setCachePublic(true)
474 .build();
475 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
476 }
477
478 @Test
479 public void testResponsesWithMultipleExpiresHeadersAreNotCacheable() {
480 response.addHeader("Expires", DateUtils.formatStandardDate(now));
481 response.addHeader("Expires", DateUtils.formatStandardDate(sixSecondsAgo));
482 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
483 }
484
485 @Test
486 public void testResponsesWithMultipleExpiresHeadersAreNotCacheableUsingSharedPublicCache() {
487 policy = new ResponseCachingPolicy(true, false, false);
488
489 request.setHeader("Authorization", StandardAuthScheme.BASIC + " QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
490 response.addHeader("Expires", DateUtils.formatStandardDate(now));
491 response.addHeader("Expires", DateUtils.formatStandardDate(sixSecondsAgo));
492 responseCacheControl = ResponseCacheControl.builder()
493 .setCachePublic(true)
494 .build();
495 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
496 }
497
498 @Test
499 public void testResponsesThatAreSmallEnoughAreCacheable() {
500 response.setHeader("Content-Length", "0");
501 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
502 }
503
504 @Test
505 public void testResponsesToGETWithQueryParamsButNoExplicitCachingAreNotCacheable() {
506 request = new BasicHttpRequest("GET", "/foo?s=bar");
507 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
508 }
509
510 @Test
511 public void testResponsesToHEADWithQueryParamsButNoExplicitCachingAreNotCacheable() {
512 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
513 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
514 }
515
516 @Test
517 public void testResponsesToGETWithQueryParamsButNoExplicitCachingAreNotCacheableEvenWhen1_0QueryCachingDisabled() {
518 policy = new ResponseCachingPolicy(true, true, false);
519 request = new BasicHttpRequest("GET", "/foo?s=bar");
520 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
521 }
522
523 @Test
524 public void testResponsesToHEADWithQueryParamsButNoExplicitCachingAreNotCacheableEvenWhen1_0QueryCachingDisabled() {
525 policy = new ResponseCachingPolicy(true, true, false);
526 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
527 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
528 }
529
530 @Test
531 public void testResponsesToGETWithQueryParamsAndExplicitCachingAreCacheable() {
532 request = new BasicHttpRequest("GET", "/foo?s=bar");
533 response.setHeader("Date", DateUtils.formatStandardDate(now));
534 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
535 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
536 }
537
538 @Test
539 public void testResponsesToHEADWithQueryParamsAndExplicitCachingAreCacheable() {
540 policy = new ResponseCachingPolicy(true, false, false);
541 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
542 response.setHeader("Date", DateUtils.formatStandardDate(now));
543 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
544 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
545 }
546
547 @Test
548 public void testResponsesToGETWithQueryParamsAndExplicitCachingAreCacheableEvenWhen1_0QueryCachingDisabled() {
549 policy = new ResponseCachingPolicy(true, true, false);
550 request = new BasicHttpRequest("GET", "/foo?s=bar");
551 response.setHeader("Date", DateUtils.formatStandardDate(now));
552 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
553 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
554 }
555
556 @Test
557 public void testResponsesToHEADWithQueryParamsAndExplicitCachingAreCacheableEvenWhen1_0QueryCachingDisabled() {
558 policy = new ResponseCachingPolicy(true, true, false);
559 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
560 response.setHeader("Date", DateUtils.formatStandardDate(now));
561 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
562 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
563 }
564
565 @Test
566 public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() {
567 request = new BasicHttpRequest("GET", "/foo?s=bar");
568 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
569 response.setVersion(HttpVersion.HTTP_1_0);
570 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
571 }
572
573 @Test
574 public void headsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() {
575 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
576 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
577 response.setVersion(HttpVersion.HTTP_1_0);
578 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
579 }
580
581 @Test
582 public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() {
583 policy = new ResponseCachingPolicy(true, true, false);
584 request = new BasicHttpRequest("GET", "/foo?s=bar");
585 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
586 response.setVersion(HttpVersion.HTTP_1_0);
587 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
588 }
589
590 @Test
591 public void headsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() {
592 policy = new ResponseCachingPolicy(true, true, false);
593 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
594 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
595 response.setVersion(HttpVersion.HTTP_1_0);
596 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
597 }
598
599 @Test
600 public void getsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() {
601 request = new BasicHttpRequest("GET", "/foo?s=bar");
602 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
603 response.setVersion(HttpVersion.HTTP_1_0);
604 response.setHeader("Date", DateUtils.formatStandardDate(now));
605 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
606 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
607 }
608
609 @Test
610 public void headsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() {
611 policy = new ResponseCachingPolicy(true, false, false);
612 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
613 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
614 response.setVersion(HttpVersion.HTTP_1_0);
615 response.setHeader("Date", DateUtils.formatStandardDate(now));
616 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
617 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
618 }
619
620 @Test
621 public void getsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() {
622 policy = new ResponseCachingPolicy(true, true, false);
623 request = new BasicHttpRequest("GET", "/foo?s=bar");
624 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
625 response.setVersion(HttpVersion.HTTP_1_0);
626 response.setHeader("Date", DateUtils.formatStandardDate(now));
627 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
628 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
629 }
630
631 @Test
632 public void headsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() {
633 policy = new ResponseCachingPolicy(true, true, false);
634 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
635 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
636 response.setVersion(HttpVersion.HTTP_1_0);
637 response.setHeader("Date", DateUtils.formatStandardDate(now));
638 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
639 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
640 }
641
642 @Test
643 public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheable() {
644 request = new BasicHttpRequest("GET", "/foo?s=bar");
645 response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
646 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
647 }
648
649 @Test
650 public void headsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheable() {
651 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
652 response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
653 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
654 }
655
656 @Test
657 public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreCacheableWithExpires() {
658 request = new BasicHttpRequest("GET", "/foo?s=bar");
659 response.setHeader("Date", DateUtils.formatStandardDate(now));
660 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
661 response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
662 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
663 }
664
665 @Test
666 public void headsWithQueryParametersFrom1_0OriginsViaProxiesAreCacheableWithExpires() {
667 policy = new ResponseCachingPolicy(true, false, false);
668 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
669 response.setHeader("Date", DateUtils.formatStandardDate(now));
670 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
671 response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
672 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
673 }
674
675 @Test
676 public void getsWithQueryParametersFrom1_0OriginsViaProxiesCanNotBeCacheableEvenWithExpires() {
677 policy = new ResponseCachingPolicy(true, true, true);
678 request = new BasicHttpRequest("GET", "/foo?s=bar");
679 response.setHeader("Date", DateUtils.formatStandardDate(now));
680 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
681 response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
682 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
683 }
684
685 @Test
686 public void headsWithQueryParametersFrom1_0OriginsViaProxiesCanNotBeCacheableEvenWithExpires() {
687 policy = new ResponseCachingPolicy(true, true, true);
688 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
689 response.setHeader("Date", DateUtils.formatStandardDate(now));
690 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
691 response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
692 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
693 }
694
695 @Test
696 public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesAreCacheableWithExpires() {
697 request = new BasicHttpRequest("GET", "/foo?s=bar");
698 response.setHeader("Date", DateUtils.formatStandardDate(now));
699 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
700 response.setHeader(HttpHeaders.VIA, "HTTP/1.0 someproxy");
701 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
702 }
703
704 @Test
705 public void headsWithQueryParametersFrom1_0OriginsViaExplicitProxiesAreCacheableWithExpires() {
706 policy = new ResponseCachingPolicy(true, false, false);
707 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
708 response.setHeader("Date", DateUtils.formatStandardDate(now));
709 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
710 response.setHeader(HttpHeaders.VIA, "HTTP/1.0 someproxy");
711 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
712 }
713
714 @Test
715 public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesCanNotBeCacheableEvenWithExpires() {
716 policy = new ResponseCachingPolicy(true, true, true);
717 request = new BasicHttpRequest("GET", "/foo?s=bar");
718 response.setHeader("Date", DateUtils.formatStandardDate(now));
719 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
720 response.setHeader(HttpHeaders.VIA, "HTTP/1.0 someproxy");
721 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
722 }
723
724 @Test
725 public void headsWithQueryParametersFrom1_0OriginsViaExplicitProxiesCanNotBeCacheableEvenWithExpires() {
726 policy = new ResponseCachingPolicy(true, true, true);
727 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
728 response.setHeader("Date", DateUtils.formatStandardDate(now));
729 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
730 response.setHeader(HttpHeaders.VIA, "HTTP/1.0 someproxy");
731 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
732 }
733
734 @Test
735 public void getsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() {
736 request = new BasicHttpRequest("GET", "/foo?s=bar");
737 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
738 response.setVersion(HttpVersion.HTTP_1_0);
739 response.setHeader("Date", DateUtils.formatStandardDate(now));
740 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
741 response.setHeader(HttpHeaders.VIA, "1.1 someproxy");
742 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
743 }
744
745 @Test
746 public void headsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() {
747 policy = new ResponseCachingPolicy(true, false, false);
748 request = new BasicHttpRequest("HEAD", "/foo?s=bar");
749 response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
750 response.setVersion(HttpVersion.HTTP_1_0);
751 response.setHeader("Date", DateUtils.formatStandardDate(now));
752 response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
753 response.setHeader(HttpHeaders.VIA, "1.1 someproxy");
754
755 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
756 }
757
758 @Test
759 public void notCacheableIfExpiresEqualsDateAndNoCacheControl() {
760 response.setHeader("Date", DateUtils.formatStandardDate(now));
761 response.setHeader("Expires", DateUtils.formatStandardDate(now));
762 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
763 }
764
765 @Test
766 public void notCacheableIfExpiresPrecedesDateAndNoCacheControl() {
767 response.setHeader("Date", DateUtils.formatStandardDate(now));
768 response.setHeader("Expires", DateUtils.formatStandardDate(sixSecondsAgo));
769 Assertions.assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
770 }
771
772 @Test
773 public void test302WithExplicitCachingHeaders() {
774 response.setCode(HttpStatus.SC_MOVED_TEMPORARILY);
775 response.setHeader("Date", DateUtils.formatStandardDate(now));
776 responseCacheControl = ResponseCacheControl.builder()
777 .setMaxAge(300)
778 .build();
779 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
780 }
781
782 @Test
783 public void test303WithExplicitCachingHeadersWhenPermittedByConfig() {
784
785
786 policy = new ResponseCachingPolicy(true, false, true);
787 response.setCode(HttpStatus.SC_SEE_OTHER);
788 response.setHeader("Date", DateUtils.formatStandardDate(now));
789 responseCacheControl = ResponseCacheControl.builder()
790 .setMaxAge(300)
791 .build();
792 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
793 }
794
795 @Test
796 public void test307WithExplicitCachingHeaders() {
797 response.setCode(HttpStatus.SC_TEMPORARY_REDIRECT);
798 response.setHeader("Date", DateUtils.formatStandardDate(now));
799 responseCacheControl = ResponseCacheControl.builder()
800 .setMaxAge(300)
801 .build();
802 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
803 }
804
805 @Test
806 public void otherStatusCodesAreCacheableWithExplicitCachingHeaders() {
807 response.setCode(HttpStatus.SC_NOT_FOUND);
808 response.setHeader("Date", DateUtils.formatStandardDate(now));
809 responseCacheControl = ResponseCacheControl.builder()
810 .setMaxAge(300)
811 .build();
812 assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
813 }
814
815 @Test
816 void testIsResponseCacheableNullCacheControl() {
817
818
819 final Duration tenSecondsFromNow = Duration.ofSeconds(10);
820
821 response = new BasicHttpResponse(HttpStatus.SC_OK, "");
822 response.setHeader(HttpHeaders.DATE, DateUtils.formatStandardDate(Instant.now()));
823 response.setHeader(HttpHeaders.EXPIRES, DateUtils.formatStandardDate(Instant.now().plus(tenSecondsFromNow)));
824
825
826
827 policy = new ResponseCachingPolicy(true, false, false);
828 request = new BasicHttpRequest("GET", "/foo");
829 assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
830 }
831
832
833 @Test
834 void testIsResponseCacheableNotNullCacheControlSmaxAge60() {
835
836
837 final Duration tenSecondsFromNow = Duration.ofSeconds(10);
838
839 response = new BasicHttpResponse(HttpStatus.SC_OK, "");
840 response.setHeader(HttpHeaders.DATE, DateUtils.formatStandardDate(Instant.now()));
841 response.setHeader(HttpHeaders.EXPIRES, DateUtils.formatStandardDate(Instant.now().plus(tenSecondsFromNow)));
842
843
844
845 policy = new ResponseCachingPolicy(true, false, false);
846 request = new BasicHttpRequest("GET", "/foo");
847 responseCacheControl = ResponseCacheControl.builder()
848 .setMaxAge(60)
849 .build();
850 assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
851 }
852
853 @Test
854 void testIsResponseCacheableNotNullCacheControlMaxAge60() {
855
856
857 final Duration tenSecondsFromNow = Duration.ofSeconds(10);
858
859 response = new BasicHttpResponse(HttpStatus.SC_OK, "");
860 response.setHeader(HttpHeaders.DATE, DateUtils.formatStandardDate(Instant.now()));
861 response.setHeader(HttpHeaders.EXPIRES, DateUtils.formatStandardDate(Instant.now().plus(tenSecondsFromNow)));
862
863
864
865 policy = new ResponseCachingPolicy(true, false, false);
866 request = new BasicHttpRequest("GET", "/foo");
867 responseCacheControl = ResponseCacheControl.builder()
868 .setMaxAge(60)
869 .build();
870 assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
871 }
872
873 @Test
874 void testIsResponseCacheableNotExsiresAndDate() {
875
876
877 final Duration tenSecondsFromNow = Duration.ofSeconds(10);
878
879 response = new BasicHttpResponse(HttpStatus.SC_OK, "");
880 response.setHeader(HttpHeaders.DATE, DateUtils.formatStandardDate(Instant.now()));
881 response.setHeader(HttpHeaders.EXPIRES, DateUtils.formatStandardDate(Instant.now().plus(tenSecondsFromNow)));
882
883
884
885 policy = new ResponseCachingPolicy(true, false, false);
886 request = new BasicHttpRequest("GET", "/foo");
887 assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
888 }
889
890 private int getRandomStatus() {
891 final int rnd = new Random().nextInt(acceptableCodes.length);
892
893 return acceptableCodes[rnd];
894 }
895
896 @Test
897 public void testIsResponseCacheable() {
898 request = new BasicHttpRequest("GET","/foo?s=bar");
899
900
901 policy = new ResponseCachingPolicy(true, false, true);
902 response.setCode(HttpStatus.SC_OK);
903 response.setHeader("Date", DateUtils.formatStandardDate(now));
904 assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
905 }
906
907 @Test
908 void testIsResponseCacheableNoCache() {
909
910 response = new BasicHttpResponse(HttpStatus.SC_OK, "");
911 response.setHeader(HttpHeaders.DATE, DateUtils.formatStandardDate(Instant.now()));
912
913
914 policy = new ResponseCachingPolicy(true, false, false);
915 request = new BasicHttpRequest("GET", "/foo");
916 responseCacheControl = ResponseCacheControl.builder()
917 .setNoCache(true)
918 .build();
919 assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
920 }
921
922 @Test
923 void testIsResponseCacheableNoStore() {
924
925 response = new BasicHttpResponse(HttpStatus.SC_OK, "");
926 response.setHeader(HttpHeaders.DATE, DateUtils.formatStandardDate(Instant.now()));
927
928
929 policy = new ResponseCachingPolicy(true, false, false);
930 request = new BasicHttpRequest("GET", "/foo");
931 responseCacheControl = ResponseCacheControl.builder()
932 .setNoStore(true)
933 .build();
934 assertFalse(policy.isResponseCacheable(responseCacheControl, request, response));
935 }
936
937 @Test
938 public void testImmutableAndFreshResponseIsCacheable() {
939 responseCacheControl = ResponseCacheControl.builder()
940 .setImmutable(true)
941 .setMaxAge(3600)
942 .build();
943
944 Assertions.assertTrue(policy.isResponseCacheable(responseCacheControl, request, response));
945 }
946 }