HTTPCLIENT-1015: Support only-if-cached directive

Contributed by Michajlo Matijkiw <michajlo_matijkiw at comcast.com>


git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1024383 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2010-10-19 19:54:29 +00:00
parent e4d6204517
commit de7daf36de
2 changed files with 74 additions and 0 deletions

View File

@ -407,6 +407,11 @@ public class CachingHttpClient implements HttpClient {
log.debug("Cache miss [host: " + target + "; uri: " + rl.getUri() + "]"); log.debug("Cache miss [host: " + target + "; uri: " + rl.getUri() + "]");
} }
if (!mayCallBackend(request)) {
return new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT,
"Gateway Timeout");
}
Set<HttpCacheEntry> variantEntries = null; Set<HttpCacheEntry> variantEntries = null;
try { try {
responseCache.getVariantCacheEntries(target, request); responseCache.getVariantCacheEntries(target, request);
@ -447,6 +452,11 @@ public class CachingHttpClient implements HttpClient {
return cachedResponse; return cachedResponse;
} }
if (!mayCallBackend(request)) {
return new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT,
"Gateway Timeout");
}
if (validityPolicy.isRevalidatable(entry)) { if (validityPolicy.isRevalidatable(entry)) {
log.debug("Revalidating the cache entry"); log.debug("Revalidating the cache entry");
@ -472,6 +482,17 @@ public class CachingHttpClient implements HttpClient {
return callBackend(target, request, context); return callBackend(target, request, context);
} }
private boolean mayCallBackend(HttpRequest request) {
for (Header h: request.getHeaders("Cache-Control")) {
for (HeaderElement elt : h.getElements()) {
if ("only-if-cached".equals(elt.getName())) {
return false;
}
}
}
return true;
}
private boolean explicitFreshnessRequest(HttpRequest request, HttpCacheEntry entry, Date now) { private boolean explicitFreshnessRequest(HttpRequest request, HttpCacheEntry entry, Date now) {
for(Header h : request.getHeaders("Cache-Control")) { for(Header h : request.getHeaders("Cache-Control")) {
for(HeaderElement elt : h.getElements()) { for(HeaderElement elt : h.getElements()) {

View File

@ -1931,6 +1931,59 @@ public class TestCachingHttpClient {
Assert.assertSame(resp, result); Assert.assertSame(resp, result);
} }
@Test
public void testIfOnlyIfCachedAndNoCacheEntryBackendNotCalled() throws IOException {
impl = new CachingHttpClient(mockBackend);
request.addHeader("Cache-Control", "only-if-cached");
HttpResponse resp = impl.execute(host, request);
Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getStatusLine().getStatusCode());
}
@Test
public void testIfOnlyIfCachedAndEntryNotSuitableBackendNotCalled() throws Exception {
request.setHeader("Cache-Control", "only-if-cached");
entry = HttpTestUtils.makeCacheEntry(new Header[]{new BasicHeader("Cache-Control", "must-revalidate")});
requestIsFatallyNonCompliant(null);
requestProtocolValidationIsCalled();
cacheInvalidatorWasCalled();
requestPolicyAllowsCaching(true);
getCacheEntryReturns(entry);
cacheEntrySuitable(false);
replayMocks();
HttpResponse resp = impl.execute(host, request);
verifyMocks();
Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getStatusLine().getStatusCode());
}
@Test
public void testIfOnlyIfCachedAndEntryExistsAndIsSuitableReturnsEntry() throws Exception {
request.setHeader("Cache-Control", "only-if-cached");
requestIsFatallyNonCompliant(null);
requestProtocolValidationIsCalled();
cacheInvalidatorWasCalled();
requestPolicyAllowsCaching(true);
getCacheEntryReturns(entry);
cacheEntrySuitable(true);
responseIsGeneratedFromCache();
entryHasStaleness(0);
replayMocks();
HttpResponse resp = impl.execute(host, request);
verifyMocks();
Assert.assertSame(mockCachedResponse, resp);
}
private void getCacheEntryReturns(HttpCacheEntry result) throws IOException { private void getCacheEntryReturns(HttpCacheEntry result) throws IOException {
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(result); EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(result);
} }