View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl.client.cache;
28  
29  import java.util.Date;
30  import java.util.Random;
31  
32  import org.apache.http.HttpRequest;
33  import org.apache.http.HttpResponse;
34  import org.apache.http.HttpStatus;
35  import org.apache.http.HttpVersion;
36  import org.apache.http.ProtocolVersion;
37  import org.apache.http.client.methods.HttpOptions;
38  import org.apache.http.client.utils.DateUtils;
39  import org.apache.http.message.BasicHttpRequest;
40  import org.apache.http.message.BasicHttpResponse;
41  import org.apache.http.message.BasicStatusLine;
42  import org.junit.Assert;
43  import org.junit.Before;
44  import org.junit.Test;
45  
46  public class TestResponseCachingPolicy {
47  
48      private static final ProtocolVersion HTTP_1_1 = new ProtocolVersion("HTTP", 1, 1);
49      private ResponseCachingPolicy policy;
50      private HttpResponse response;
51      private HttpRequest request;
52      private final int[] acceptableCodes = new int[] { HttpStatus.SC_OK,
53              HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION, HttpStatus.SC_MULTIPLE_CHOICES,
54              HttpStatus.SC_MOVED_PERMANENTLY, HttpStatus.SC_GONE };
55      private Date now;
56      private Date tenSecondsFromNow;
57      private Date sixSecondsAgo;
58  
59      @Before
60      public void setUp() throws Exception {
61          now = new Date();
62          sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
63          tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
64  
65          policy = new ResponseCachingPolicy(0, true, false, false);
66          request = new BasicHttpRequest("GET","/",HTTP_1_1);
67          response = new BasicHttpResponse(
68                  new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
69          response.setHeader("Date", DateUtils.formatDate(new Date()));
70          response.setHeader("Content-Length", "0");
71      }
72  
73      @Test
74      public void testIsGetCacheable() {
75          Assert.assertTrue(policy.isResponseCacheable("GET", response));
76      }
77  
78      @Test
79      public void testIsHeadCacheable() {
80          policy = new ResponseCachingPolicy(0, true, false, false);
81          Assert.assertTrue(policy.isResponseCacheable("HEAD", response));
82      }
83  
84      @Test
85      public void testResponsesToRequestsWithAuthorizationHeadersAreNotCacheableBySharedCache() {
86          request = new BasicHttpRequest("GET","/",HTTP_1_1);
87          request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
88          Assert.assertFalse(policy.isResponseCacheable(request,response));
89      }
90  
91      @Test
92      public void testResponsesToRequestsWithAuthorizationHeadersAreCacheableByNonSharedCache() {
93          policy = new ResponseCachingPolicy(0, false, false, false);
94          request = new BasicHttpRequest("GET","/",HTTP_1_1);
95          request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
96          Assert.assertTrue(policy.isResponseCacheable(request,response));
97      }
98  
99      @Test
100     public void testAuthorizedResponsesWithSMaxAgeAreCacheable() {
101         request = new BasicHttpRequest("GET","/",HTTP_1_1);
102         request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
103         response.setHeader("Cache-Control","s-maxage=3600");
104         Assert.assertTrue(policy.isResponseCacheable(request,response));
105     }
106 
107     @Test
108     public void testAuthorizedResponsesWithMustRevalidateAreCacheable() {
109         request = new BasicHttpRequest("GET","/",HTTP_1_1);
110         request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
111         response.setHeader("Cache-Control","must-revalidate");
112         Assert.assertTrue(policy.isResponseCacheable(request,response));
113     }
114 
115     @Test
116     public void testAuthorizedResponsesWithCacheControlPublicAreCacheable() {
117         request = new BasicHttpRequest("GET","/",HTTP_1_1);
118         request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
119         response.setHeader("Cache-Control","public");
120         Assert.assertTrue(policy.isResponseCacheable(request,response));
121     }
122 
123     @Test
124     public void testAuthorizedResponsesWithCacheControlMaxAgeAreNotCacheable() {
125         request = new BasicHttpRequest("GET","/",HTTP_1_1);
126         request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
127         response.setHeader("Cache-Control","max-age=3600");
128         Assert.assertFalse(policy.isResponseCacheable(request,response));
129     }
130 
131     @Test
132     public void test203ResponseCodeIsCacheable() {
133         response.setStatusCode(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION);
134         Assert.assertTrue(policy.isResponseCacheable("GET", response));
135     }
136 
137     @Test
138     public void test206ResponseCodeIsNotCacheable() {
139         response.setStatusCode(HttpStatus.SC_PARTIAL_CONTENT);
140         Assert.assertFalse(policy.isResponseCacheable("GET", response));
141     }
142 
143     @Test
144     public void test206ResponseCodeIsNotCacheableUsingSharedPublicCache() {
145         policy = new ResponseCachingPolicy(0, true, false, false);
146 
147         request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
148         response.setStatusCode(HttpStatus.SC_PARTIAL_CONTENT);
149         response.setHeader("Cache-Control", "public");
150         Assert.assertFalse(policy.isResponseCacheable(request, response));
151     }
152 
153     @Test
154     public void test300ResponseCodeIsCacheable() {
155         response.setStatusCode(HttpStatus.SC_MULTIPLE_CHOICES);
156         Assert.assertTrue(policy.isResponseCacheable("GET", response));
157     }
158 
159     @Test
160     public void test301ResponseCodeIsCacheable() {
161         response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY);
162         Assert.assertTrue(policy.isResponseCacheable("GET", response));
163     }
164 
165     @Test
166     public void test410ResponseCodeIsCacheable() {
167         response.setStatusCode(HttpStatus.SC_GONE);
168         Assert.assertTrue(policy.isResponseCacheable("GET", response));
169     }
170 
171     @Test
172     public void testPlain302ResponseCodeIsNotCacheable() {
173         response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
174         response.removeHeaders("Expires");
175         response.removeHeaders("Cache-Control");
176         Assert.assertFalse(policy.isResponseCacheable("GET", response));
177     }
178 
179     @Test
180     public void testPlain303ResponseCodeIsNotCacheableUnderDefaultBehavior() {
181         response.setStatusCode(HttpStatus.SC_SEE_OTHER);
182         response.removeHeaders("Expires");
183         response.removeHeaders("Cache-Control");
184         Assert.assertFalse(policy.isResponseCacheable("GET", response));
185     }
186 
187     @Test
188     public void testPlain303ResponseCodeIsNotCacheableEvenIf303CachingEnabled() {
189         policy = new ResponseCachingPolicy(0, true, false, true);
190         response.setStatusCode(HttpStatus.SC_SEE_OTHER);
191         response.removeHeaders("Expires");
192         response.removeHeaders("Cache-Control");
193         Assert.assertFalse(policy.isResponseCacheable("GET", response));
194     }
195 
196 
197     @Test
198     public void testPlain307ResponseCodeIsNotCacheable() {
199         response.setStatusCode(HttpStatus.SC_TEMPORARY_REDIRECT);
200         response.removeHeaders("Expires");
201         response.removeHeaders("Cache-Control");
202         Assert.assertFalse(policy.isResponseCacheable("GET", response));
203     }
204 
205     @Test
206     public void testNon206WithExplicitExpiresIsCacheable() {
207         final int status = getRandomStatus();
208         response.setStatusCode(status);
209         response.setHeader("Expires", DateUtils.formatDate(new Date()));
210         Assert.assertTrue(policy.isResponseCacheable("GET", response));
211     }
212 
213     @Test
214     public void testNon206WithMaxAgeIsCacheable() {
215         final int status = getRandomStatus();
216         response.setStatusCode(status);
217         response.setHeader("Cache-Control", "max-age=0");
218         Assert.assertTrue(policy.isResponseCacheable("GET", response));
219     }
220 
221     @Test
222     public void testNon206WithSMaxAgeIsCacheable() {
223         final int status = getRandomStatus();
224         response.setStatusCode(status);
225         response.setHeader("Cache-Control", "s-maxage=0");
226         Assert.assertTrue(policy.isResponseCacheable("GET", response));
227     }
228 
229     @Test
230     public void testNon206WithMustRevalidateIsCacheable() {
231         final int status = getRandomStatus();
232         response.setStatusCode(status);
233         response.setHeader("Cache-Control", "must-revalidate");
234         Assert.assertTrue(policy.isResponseCacheable("GET", response));
235     }
236 
237     @Test
238     public void testNon206WithProxyRevalidateIsCacheable() {
239         final int status = getRandomStatus();
240         response.setStatusCode(status);
241         response.setHeader("Cache-Control", "proxy-revalidate");
242         Assert.assertTrue(policy.isResponseCacheable("GET", response));
243     }
244 
245     @Test
246     public void testNon206WithPublicCacheControlIsCacheable() {
247         final int status = getRandomStatus();
248         response.setStatusCode(status);
249         response.setHeader("Cache-Control", "public");
250         Assert.assertTrue(policy.isResponseCacheable("GET", response));
251     }
252 
253     @Test
254     public void testNon206WithPrivateCacheControlIsNotCacheableBySharedCache() {
255         final int status = getRandomStatus();
256         response.setStatusCode(status);
257         response.setHeader("Cache-Control", "private");
258         Assert.assertFalse(policy.isResponseCacheable("GET", response));
259     }
260 
261     @Test
262     public void test200ResponseWithPrivateCacheControlIsCacheableByNonSharedCache() {
263         policy = new ResponseCachingPolicy(0, false, false, false);
264         response.setStatusCode(HttpStatus.SC_OK);
265         response.setHeader("Cache-Control", "private");
266         Assert.assertTrue(policy.isResponseCacheable("GET", response));
267     }
268 
269     @Test
270     public void testIsGetWithNoCacheCacheable() {
271         response.addHeader("Cache-Control", "no-cache");
272 
273         Assert.assertFalse(policy.isResponseCacheable("GET", response));
274     }
275 
276     @Test
277     public void testIsHeadWithNoCacheCacheable() {
278         response.addHeader("Cache-Control", "no-cache");
279 
280         Assert.assertFalse(policy.isResponseCacheable("HEAD", response));
281     }
282 
283     @Test
284     public void testIsGetWithNoStoreCacheable() {
285         response.addHeader("Cache-Control", "no-store");
286 
287         Assert.assertFalse(policy.isResponseCacheable("GET", response));
288     }
289 
290     @Test
291     public void testIsHeadWithNoStoreCacheable() {
292         response.addHeader("Cache-Control", "no-store");
293 
294         Assert.assertFalse(policy.isResponseCacheable("HEAD", response));
295     }
296 
297     @Test
298     public void testIsGetWithNoStoreEmbeddedInListCacheable() {
299         response.addHeader("Cache-Control", "public, no-store");
300 
301         Assert.assertFalse(policy.isResponseCacheable("GET", response));
302     }
303 
304     @Test
305     public void testIsHeadWithNoStoreEmbeddedInListCacheable() {
306         response.addHeader("Cache-Control", "public, no-store");
307 
308         Assert.assertFalse(policy.isResponseCacheable("HEAD", response));
309     }
310 
311     @Test
312     public void testIsGetWithNoCacheEmbeddedInListCacheable() {
313         response.addHeader("Cache-Control", "public, no-cache");
314 
315         Assert.assertFalse(policy.isResponseCacheable("GET", response));
316     }
317 
318     @Test
319     public void testIsHeadWithNoCacheEmbeddedInListCacheable() {
320         response.addHeader("Cache-Control", "public, no-cache");
321 
322         Assert.assertFalse(policy.isResponseCacheable("HEAD", response));
323     }
324 
325     @Test
326     public void testIsGetWithNoCacheEmbeddedInListAfterFirstHeaderCacheable() {
327         response.addHeader("Cache-Control", "max-age=20");
328         response.addHeader("Cache-Control", "public, no-cache");
329 
330         Assert.assertFalse(policy.isResponseCacheable("GET", response));
331     }
332 
333     @Test
334     public void testIsHeadWithNoCacheEmbeddedInListAfterFirstHeaderCacheable() {
335         response.addHeader("Cache-Control", "max-age=20");
336         response.addHeader("Cache-Control", "public, no-cache");
337 
338         Assert.assertFalse(policy.isResponseCacheable("HEAD", response));
339     }
340 
341     @Test
342     public void testIsGetWithNoStoreEmbeddedInListAfterFirstHeaderCacheable() {
343         response.addHeader("Cache-Control", "max-age=20");
344         response.addHeader("Cache-Control", "public, no-store");
345 
346         Assert.assertFalse(policy.isResponseCacheable("GET", response));
347     }
348 
349     @Test
350     public void testIsHeadWithNoStoreEmbeddedInListAfterFirstHeaderCacheable() {
351         response.addHeader("Cache-Control", "max-age=20");
352         response.addHeader("Cache-Control", "public, no-store");
353 
354         Assert.assertFalse(policy.isResponseCacheable("HEAD", response));
355     }
356 
357     @Test
358     public void testIsGetWithAnyCacheControlCacheable() {
359         response.addHeader("Cache-Control", "max=10");
360 
361         Assert.assertTrue(policy.isResponseCacheable("GET", response));
362 
363         response = new BasicHttpResponse(
364                 new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
365         response.setHeader("Date", DateUtils.formatDate(new Date()));
366         response.addHeader("Cache-Control", "no-transform");
367         response.setHeader("Content-Length", "0");
368 
369         Assert.assertTrue(policy.isResponseCacheable("GET", response));
370     }
371 
372     @Test
373     public void testIsHeadWithAnyCacheControlCacheable() {
374         policy = new ResponseCachingPolicy(0, true, false, false);
375         response.addHeader("Cache-Control", "max=10");
376 
377         Assert.assertTrue(policy.isResponseCacheable("HEAD", response));
378 
379         response = new BasicHttpResponse(
380                 new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
381         response.setHeader("Date", DateUtils.formatDate(new Date()));
382         response.addHeader("Cache-Control", "no-transform");
383         response.setHeader("Content-Length", "0");
384 
385         Assert.assertTrue(policy.isResponseCacheable("HEAD", response));
386     }
387 
388     @Test
389     public void testIsGetWithout200Cacheable() {
390         HttpResponse response404 = new BasicHttpResponse(new BasicStatusLine(HTTP_1_1,
391                 HttpStatus.SC_NOT_FOUND, ""));
392 
393         Assert.assertFalse(policy.isResponseCacheable("GET", response404));
394 
395         response404 = new BasicHttpResponse(new BasicStatusLine(HTTP_1_1,
396                 HttpStatus.SC_GATEWAY_TIMEOUT, ""));
397 
398         Assert.assertFalse(policy.isResponseCacheable("GET", response404));
399     }
400 
401     @Test
402     public void testIsHeadWithout200Cacheable() {
403         HttpResponse response404 = new BasicHttpResponse(new BasicStatusLine(HTTP_1_1,
404                 HttpStatus.SC_NOT_FOUND, ""));
405 
406         Assert.assertFalse(policy.isResponseCacheable("HEAD", response404));
407 
408         response404 = new BasicHttpResponse(new BasicStatusLine(HTTP_1_1,
409                 HttpStatus.SC_GATEWAY_TIMEOUT, ""));
410 
411         Assert.assertFalse(policy.isResponseCacheable("HEAD", response404));
412     }
413 
414     @Test
415     public void testVaryStarIsNotCacheable() {
416         response.setHeader("Vary", "*");
417         Assert.assertFalse(policy.isResponseCacheable("GET", response));
418     }
419 
420     @Test
421     public void testVaryStarIsNotCacheableUsingSharedPublicCache() {
422         policy = new ResponseCachingPolicy(0, true, false, false);
423 
424         request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
425         response.setHeader("Cache-Control", "public");
426         response.setHeader("Vary", "*");
427         Assert.assertFalse(policy.isResponseCacheable(request, response));
428     }
429 
430     @Test
431     public void testIsGetWithVaryHeaderCacheable() {
432         response.addHeader("Vary", "Accept-Encoding");
433         Assert.assertTrue(policy.isResponseCacheable("GET", response));
434     }
435 
436     @Test
437     public void testIsHeadWithVaryHeaderCacheable() {
438         policy = new ResponseCachingPolicy(0, true, false, false);
439         response.addHeader("Vary", "Accept-Encoding");
440         Assert.assertTrue(policy.isResponseCacheable("HEAD", response));
441     }
442 
443     @Test
444     public void testIsArbitraryMethodCacheable() {
445 
446         Assert.assertFalse(policy.isResponseCacheable("PUT", response));
447 
448         Assert.assertFalse(policy.isResponseCacheable("get", response));
449     }
450 
451     @Test
452     public void testIsArbitraryMethodCacheableUsingSharedPublicCache() {
453         policy = new ResponseCachingPolicy(0, true, false, false);
454 
455         request = new HttpOptions("http://foo.example.com/");
456         request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
457         response.setStatusCode(HttpStatus.SC_NO_CONTENT);
458         response.setHeader("Cache-Control", "public");
459 
460         Assert.assertFalse(policy.isResponseCacheable(request, response));
461     }
462 
463     @Test
464     public void testResponsesToRequestsWithNoStoreAreNotCacheable() {
465         request.setHeader("Cache-Control","no-store");
466         response.setHeader("Cache-Control","public");
467         Assert.assertFalse(policy.isResponseCacheable(request,response));
468     }
469 
470     @Test
471     public void testResponsesWithMultipleAgeHeadersAreNotCacheable() {
472         response.addHeader("Age", "3");
473         response.addHeader("Age", "5");
474         Assert.assertFalse(policy.isResponseCacheable("GET", response));
475     }
476 
477     @Test
478     public void testResponsesWithMultipleAgeHeadersAreNotCacheableUsingSharedPublicCache() {
479         policy = new ResponseCachingPolicy(0, true, false, false);
480 
481         request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
482         response.setHeader("Cache-Control", "public");
483         response.addHeader("Age", "3");
484         response.addHeader("Age", "5");
485         Assert.assertFalse(policy.isResponseCacheable(request, response));
486     }
487 
488     @Test
489     public void testResponsesWithMultipleDateHeadersAreNotCacheable() {
490         response.addHeader("Date", DateUtils.formatDate(now));
491         response.addHeader("Date", DateUtils.formatDate(sixSecondsAgo));
492         Assert.assertFalse(policy.isResponseCacheable("GET", response));
493     }
494 
495     @Test
496     public void testResponsesWithMultipleDateHeadersAreNotCacheableUsingSharedPublicCache() {
497         policy = new ResponseCachingPolicy(0, true, false, false);
498 
499         request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
500         response.setHeader("Cache-Control", "public");
501         response.addHeader("Date", DateUtils.formatDate(now));
502         response.addHeader("Date", DateUtils.formatDate(sixSecondsAgo));
503         Assert.assertFalse(policy.isResponseCacheable(request, response));
504     }
505 
506     @Test
507     public void testResponsesWithMalformedDateHeadersAreNotCacheable() {
508         response.addHeader("Date", "garbage");
509         Assert.assertFalse(policy.isResponseCacheable("GET", response));
510     }
511 
512     @Test
513     public void testResponsesWithMalformedDateHeadersAreNotCacheableUsingSharedPublicCache() {
514         policy = new ResponseCachingPolicy(0, true, false, false);
515 
516         request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
517         response.setHeader("Cache-Control", "public");
518         response.addHeader("Date", "garbage");
519         Assert.assertFalse(policy.isResponseCacheable(request, response));
520     }
521 
522     @Test
523     public void testResponsesWithMultipleExpiresHeadersAreNotCacheable() {
524         response.addHeader("Expires", DateUtils.formatDate(now));
525         response.addHeader("Expires", DateUtils.formatDate(sixSecondsAgo));
526         Assert.assertFalse(policy.isResponseCacheable("GET", response));
527     }
528 
529     @Test
530     public void testResponsesWithMultipleExpiresHeadersAreNotCacheableUsingSharedPublicCache() {
531         policy = new ResponseCachingPolicy(0, true, false, false);
532 
533         request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
534         response.setHeader("Cache-Control", "public");
535         response.addHeader("Expires", DateUtils.formatDate(now));
536         response.addHeader("Expires", DateUtils.formatDate(sixSecondsAgo));
537         Assert.assertFalse(policy.isResponseCacheable(request, response));
538     }
539 
540     @Test
541     public void testResponsesWithoutDateHeadersAreNotCacheable() {
542         response.removeHeaders("Date");
543         Assert.assertFalse(policy.isResponseCacheable("GET", response));
544     }
545 
546     @Test
547     public void testResponseThatHasTooMuchContentIsNotCacheable() {
548         response.setHeader("Content-Length", "9000");
549         Assert.assertFalse(policy.isResponseCacheable("GET", response));
550     }
551 
552     @Test
553     public void testResponseThatHasTooMuchContentIsNotCacheableUsingSharedPublicCache() {
554         policy = new ResponseCachingPolicy(0, true, false, false);
555 
556         request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
557         response.setHeader("Cache-Control", "public");
558         response.setHeader("Content-Length", "9000");
559         Assert.assertFalse(policy.isResponseCacheable(request, response));
560     }
561 
562     @Test
563     public void testResponsesThatAreSmallEnoughAreCacheable() {
564         response.setHeader("Content-Length", "0");
565         Assert.assertTrue(policy.isResponseCacheable("GET", response));
566     }
567 
568     @Test
569     public void testResponsesToGETWithQueryParamsButNoExplicitCachingAreNotCacheable() {
570         request = new BasicHttpRequest("GET", "/foo?s=bar");
571         Assert.assertFalse(policy.isResponseCacheable(request, response));
572     }
573 
574     @Test
575     public void testResponsesToHEADWithQueryParamsButNoExplicitCachingAreNotCacheable() {
576         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
577         Assert.assertFalse(policy.isResponseCacheable(request, response));
578     }
579 
580     @Test
581     public void testResponsesToGETWithQueryParamsButNoExplicitCachingAreNotCacheableEvenWhen1_0QueryCachingDisabled() {
582         policy = new ResponseCachingPolicy(0, true, true, false);
583         request = new BasicHttpRequest("GET", "/foo?s=bar");
584         Assert.assertFalse(policy.isResponseCacheable(request, response));
585     }
586 
587     @Test
588     public void testResponsesToHEADWithQueryParamsButNoExplicitCachingAreNotCacheableEvenWhen1_0QueryCachingDisabled() {
589         policy = new ResponseCachingPolicy(0, true, true, false);
590         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
591         Assert.assertFalse(policy.isResponseCacheable(request, response));
592     }
593 
594     @Test
595     public void testResponsesToGETWithQueryParamsAndExplicitCachingAreCacheable() {
596         request = new BasicHttpRequest("GET", "/foo?s=bar");
597         response.setHeader("Date", DateUtils.formatDate(now));
598         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
599         Assert.assertTrue(policy.isResponseCacheable(request, response));
600     }
601 
602     @Test
603     public void testResponsesToHEADWithQueryParamsAndExplicitCachingAreCacheable() {
604         policy = new ResponseCachingPolicy(0, true, false, false);
605         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
606         response.setHeader("Date", DateUtils.formatDate(now));
607         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
608         Assert.assertTrue(policy.isResponseCacheable(request, response));
609     }
610 
611     @Test
612     public void testResponsesToGETWithQueryParamsAndExplicitCachingAreCacheableEvenWhen1_0QueryCachingDisabled() {
613         policy = new ResponseCachingPolicy(0, true, true, false);
614         request = new BasicHttpRequest("GET", "/foo?s=bar");
615         response.setHeader("Date", DateUtils.formatDate(now));
616         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
617         Assert.assertTrue(policy.isResponseCacheable(request, response));
618     }
619 
620     @Test
621     public void testResponsesToHEADWithQueryParamsAndExplicitCachingAreCacheableEvenWhen1_0QueryCachingDisabled() {
622         policy = new ResponseCachingPolicy(0, true, true, false);
623         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
624         response.setHeader("Date", DateUtils.formatDate(now));
625         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
626         Assert.assertTrue(policy.isResponseCacheable(request, response));
627     }
628 
629     @Test
630     public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() {
631         request = new BasicHttpRequest("GET", "/foo?s=bar");
632         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
633         Assert.assertFalse(policy.isResponseCacheable(request, response));
634     }
635 
636     @Test
637     public void headsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() {
638         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
639         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
640         Assert.assertFalse(policy.isResponseCacheable(request, response));
641     }
642 
643     @Test
644     public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() {
645         policy = new ResponseCachingPolicy(0, true, true, false);
646         request = new BasicHttpRequest("GET", "/foo?s=bar");
647         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
648         Assert.assertFalse(policy.isResponseCacheable(request, response));
649     }
650 
651     @Test
652     public void headsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() {
653         policy = new ResponseCachingPolicy(0, true, true, false);
654         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
655         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
656         Assert.assertFalse(policy.isResponseCacheable(request, response));
657     }
658 
659     @Test
660     public void getsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() {
661         request = new BasicHttpRequest("GET", "/foo?s=bar");
662         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
663         response.setHeader("Date", DateUtils.formatDate(now));
664         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
665         Assert.assertTrue(policy.isResponseCacheable(request, response));
666     }
667 
668     @Test
669     public void headsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() {
670         policy = new ResponseCachingPolicy(0, true, false, false);
671         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
672         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
673         response.setHeader("Date", DateUtils.formatDate(now));
674         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
675         Assert.assertTrue(policy.isResponseCacheable(request, response));
676     }
677 
678     @Test
679     public void getsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() {
680         policy = new ResponseCachingPolicy(0, true, true, false);
681         request = new BasicHttpRequest("GET", "/foo?s=bar");
682         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
683         response.setHeader("Date", DateUtils.formatDate(now));
684         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
685         Assert.assertFalse(policy.isResponseCacheable(request, response));
686     }
687 
688     @Test
689     public void headsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() {
690         policy = new ResponseCachingPolicy(0, true, true, false);
691         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
692         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
693         response.setHeader("Date", DateUtils.formatDate(now));
694         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
695         Assert.assertFalse(policy.isResponseCacheable(request, response));
696     }
697 
698     @Test
699     public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheable() {
700         request = new BasicHttpRequest("GET", "/foo?s=bar");
701         response.setHeader("Via", "1.0 someproxy");
702         Assert.assertFalse(policy.isResponseCacheable(request, response));
703     }
704 
705     @Test
706     public void headsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheable() {
707         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
708         response.setHeader("Via", "1.0 someproxy");
709         Assert.assertFalse(policy.isResponseCacheable(request, response));
710     }
711 
712     @Test
713     public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreCacheableWithExpires() {
714         request = new BasicHttpRequest("GET", "/foo?s=bar");
715         response.setHeader("Date", DateUtils.formatDate(now));
716         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
717         response.setHeader("Via", "1.0 someproxy");
718         Assert.assertTrue(policy.isResponseCacheable(request, response));
719     }
720 
721     @Test
722     public void headsWithQueryParametersFrom1_0OriginsViaProxiesAreCacheableWithExpires() {
723         policy = new ResponseCachingPolicy(0, true, false, false);
724         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
725         response.setHeader("Date", DateUtils.formatDate(now));
726         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
727         response.setHeader("Via", "1.0 someproxy");
728         Assert.assertTrue(policy.isResponseCacheable(request, response));
729     }
730 
731     @Test
732     public void getsWithQueryParametersFrom1_0OriginsViaProxiesCanNotBeCacheableEvenWithExpires() {
733         policy = new ResponseCachingPolicy(0, true, true, true);
734         request = new BasicHttpRequest("GET", "/foo?s=bar");
735         response.setHeader("Date", DateUtils.formatDate(now));
736         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
737         response.setHeader("Via", "1.0 someproxy");
738         Assert.assertFalse(policy.isResponseCacheable(request, response));
739     }
740 
741     @Test
742     public void headsWithQueryParametersFrom1_0OriginsViaProxiesCanNotBeCacheableEvenWithExpires() {
743         policy = new ResponseCachingPolicy(0, true, true, true);
744         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
745         response.setHeader("Date", DateUtils.formatDate(now));
746         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
747         response.setHeader("Via", "1.0 someproxy");
748         Assert.assertFalse(policy.isResponseCacheable(request, response));
749     }
750 
751     @Test
752     public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesAreCacheableWithExpires() {
753         request = new BasicHttpRequest("GET", "/foo?s=bar");
754         response.setHeader("Date", DateUtils.formatDate(now));
755         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
756         response.setHeader("Via", "HTTP/1.0 someproxy");
757         Assert.assertTrue(policy.isResponseCacheable(request, response));
758     }
759 
760     @Test
761     public void headsWithQueryParametersFrom1_0OriginsViaExplicitProxiesAreCacheableWithExpires() {
762         policy = new ResponseCachingPolicy(0, true, false, false);
763         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
764         response.setHeader("Date", DateUtils.formatDate(now));
765         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
766         response.setHeader("Via", "HTTP/1.0 someproxy");
767         Assert.assertTrue(policy.isResponseCacheable(request, response));
768     }
769 
770     @Test
771     public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesCanNotBeCacheableEvenWithExpires() {
772         policy = new ResponseCachingPolicy(0, true, true, true);
773         request = new BasicHttpRequest("GET", "/foo?s=bar");
774         response.setHeader("Date", DateUtils.formatDate(now));
775         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
776         response.setHeader("Via", "HTTP/1.0 someproxy");
777         Assert.assertFalse(policy.isResponseCacheable(request, response));
778     }
779 
780     @Test
781     public void headsWithQueryParametersFrom1_0OriginsViaExplicitProxiesCanNotBeCacheableEvenWithExpires() {
782         policy = new ResponseCachingPolicy(0, true, true, true);
783         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
784         response.setHeader("Date", DateUtils.formatDate(now));
785         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
786         response.setHeader("Via", "HTTP/1.0 someproxy");
787         Assert.assertFalse(policy.isResponseCacheable(request, response));
788     }
789 
790     @Test
791     public void getsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() {
792         request = new BasicHttpRequest("GET", "/foo?s=bar");
793         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
794         response.setHeader("Date", DateUtils.formatDate(now));
795         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
796         response.setHeader("Via", "1.1 someproxy");
797         Assert.assertTrue(policy.isResponseCacheable(request, response));
798     }
799 
800     @Test
801     public void headsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() {
802         policy = new ResponseCachingPolicy(0, true, false, false);
803         request = new BasicHttpRequest("HEAD", "/foo?s=bar");
804         response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
805         response.setHeader("Date", DateUtils.formatDate(now));
806         response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
807         response.setHeader("Via", "1.1 someproxy");
808         Assert.assertTrue(policy.isResponseCacheable(request, response));
809     }
810 
811     @Test
812     public void notCacheableIfExpiresEqualsDateAndNoCacheControl() {
813         response.setHeader("Date", DateUtils.formatDate(now));
814         response.setHeader("Expires", DateUtils.formatDate(now));
815         response.removeHeaders("Cache-Control");
816         Assert.assertFalse(policy.isResponseCacheable(request, response));
817     }
818 
819     @Test
820     public void notCacheableIfExpiresPrecedesDateAndNoCacheControl() {
821         response.setHeader("Date", DateUtils.formatDate(now));
822         response.setHeader("Expires", DateUtils.formatDate(sixSecondsAgo));
823         response.removeHeaders("Cache-Control");
824         Assert.assertFalse(policy.isResponseCacheable(request, response));
825     }
826 
827     @Test
828     public void test302WithExplicitCachingHeaders() {
829         response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
830         response.setHeader("Date", DateUtils.formatDate(now));
831         response.setHeader("Cache-Control","max-age=300");
832         Assert.assertTrue(policy.isResponseCacheable(request, response));
833     }
834 
835     @Test
836     public void test303WithExplicitCachingHeadersUnderDefaultBehavior() {
837         // RFC 2616 says: 303 should not be cached
838         response.setStatusCode(HttpStatus.SC_SEE_OTHER);
839         response.setHeader("Date", DateUtils.formatDate(now));
840         response.setHeader("Cache-Control","max-age=300");
841         Assert.assertFalse(policy.isResponseCacheable(request, response));
842     }
843 
844     @Test
845     public void test303WithExplicitCachingHeadersWhenPermittedByConfig() {
846         // HTTPbis working group says ok if explicitly indicated by
847         // response headers
848         policy = new ResponseCachingPolicy(0, true, false, true);
849         response.setStatusCode(HttpStatus.SC_SEE_OTHER);
850         response.setHeader("Date", DateUtils.formatDate(now));
851         response.setHeader("Cache-Control","max-age=300");
852         Assert.assertTrue(policy.isResponseCacheable(request, response));
853     }
854 
855     @Test
856     public void test307WithExplicitCachingHeaders() {
857         response.setStatusCode(HttpStatus.SC_TEMPORARY_REDIRECT);
858         response.setHeader("Date", DateUtils.formatDate(now));
859         response.setHeader("Cache-Control","max-age=300");
860         Assert.assertTrue(policy.isResponseCacheable(request, response));
861     }
862 
863     @Test
864     public void otherStatusCodesAreCacheableWithExplicitCachingHeaders() {
865         response.setStatusCode(HttpStatus.SC_NOT_FOUND);
866         response.setHeader("Date", DateUtils.formatDate(now));
867         response.setHeader("Cache-Control","max-age=300");
868         Assert.assertTrue(policy.isResponseCacheable(request, response));
869     }
870 
871     private int getRandomStatus() {
872         final int rnd = new Random().nextInt(acceptableCodes.length);
873 
874         return acceptableCodes[rnd];
875     }
876 }