HTTPCLIENT-1202: ResponseCachingPolicy had a bug that was making it too

draconian in refusing to cache certain responses.


git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1347627 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jonathan Moore 2012-06-07 14:14:42 +00:00
parent e8bc96c549
commit 2748f2748a
3 changed files with 46 additions and 25 deletions

View File

@ -1,5 +1,8 @@
Changes since 4.2
-------------------
* [HTTPCLIENT-1202] ResponseCachingPolicy should honor explicit cache-control
directives for other status codes
Contributed by Jon Moore <jonm at apache.org>
* [HTTPCLIENT-1199] DecompressingHttpClient strips content from entity enclosing requests
Contributed by Oleg Kalnichevski <olegk at apache.org>

View File

@ -26,7 +26,10 @@
*/
package org.apache.http.impl.client.cache;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -54,7 +57,16 @@ class ResponseCachingPolicy {
private final long maxObjectSizeBytes;
private final boolean sharedCache;
private final Log log = LogFactory.getLog(getClass());
private static final Set<Integer> cacheableStatuses =
new HashSet<Integer>(Arrays.asList(HttpStatus.SC_OK,
HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION,
HttpStatus.SC_MULTIPLE_CHOICES,
HttpStatus.SC_MOVED_PERMANENTLY,
HttpStatus.SC_GONE));
private static final Set<Integer> uncacheableStatuses =
new HashSet<Integer>(Arrays.asList(HttpStatus.SC_PARTIAL_CONTENT,
HttpStatus.SC_SEE_OTHER));
/**
* Define a cache policy that limits the size of things that should be stored
* in the cache to a maximum of {@link HttpResponse} bytes in size.
@ -82,30 +94,19 @@ class ResponseCachingPolicy {
log.debug("Response was not cacheable.");
return false;
}
switch (response.getStatusLine().getStatusCode()) {
case HttpStatus.SC_OK:
case HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION:
case HttpStatus.SC_MULTIPLE_CHOICES:
case HttpStatus.SC_MOVED_PERMANENTLY:
case HttpStatus.SC_GONE:
// these response codes MAY be cached
cacheable = true;
log.debug("Response was cacheable");
break;
case HttpStatus.SC_PARTIAL_CONTENT:
// we don't implement Range requests and hence are not
// allowed to cache partial content
log.debug("Response was not cacheable (Partial Content)");
return cacheable;
default:
// If the status code is not one of the recognized
// available codes in HttpStatus Don't Cache
log.debug("Response was not cacheable (Unknown Status code)");
return cacheable;
int status = response.getStatusLine().getStatusCode();
if (cacheableStatuses.contains(status)) {
// these response codes MAY be cached
cacheable = true;
} else if (uncacheableStatuses.contains(status)) {
return false;
} else if (unknownStatusCode(status)) {
// a response with an unknown status code MUST NOT be
// cached
return false;
}
Header contentLength = response.getFirstHeader(HTTP.CONTENT_LEN);
if (contentLength != null) {
int contentLengthValue = Integer.parseInt(contentLength.getValue());
@ -148,7 +149,16 @@ class ResponseCachingPolicy {
return (cacheable || isExplicitlyCacheable(response));
}
protected boolean isExplicitlyNonCacheable(HttpResponse response) {
private boolean unknownStatusCode(int status) {
if (status >= 100 && status <= 101) return false;
if (status >= 200 && status <= 206) return false;
if (status >= 300 && status <= 307) return false;
if (status >= 400 && status <= 417) return false;
if (status >= 500 && status <= 505) return false;
return true;
}
protected boolean isExplicitlyNonCacheable(HttpResponse response) {
Header[] cacheControlHeaders = response.getHeaders(HeaderConstants.CACHE_CONTROL);
for (Header header : cacheControlHeaders) {
for (HeaderElement elem : header.getElements()) {

View File

@ -459,6 +459,14 @@ public class TestResponseCachingPolicy {
response.removeHeaders("Cache-Control");
Assert.assertFalse(policy.isResponseCacheable(request, response));
}
@Test
public void otherStatusCodesAreCacheableWithExplicitCachingHeaders() {
response.setStatusCode(HttpStatus.SC_NOT_FOUND);
response.setHeader("Date", formatDate(now));
response.setHeader("Cache-Control","max-age=300");
Assert.assertTrue(policy.isResponseCacheable(request, response));
}
private int getRandomStatus() {
int rnd = (new Random()).nextInt(acceptableCodes.length);