HTTPCLIENT-1032: variant information is now passed back from the HttpCache
as a Map<String,Variant> mapping Etags to specific information about the variants (variant key, cache key, cache entry). git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1049045 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
022c25070e
commit
477fdb1a3c
|
@ -239,17 +239,19 @@ class BasicHttpCache implements HttpCache {
|
||||||
cacheInvalidator.flushInvalidatedCacheEntries(host, request);
|
cacheInvalidator.flushInvalidatedCacheEntries(host, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, HttpCacheEntry> getVariantCacheEntriesWithEtags(HttpHost host, HttpRequest request)
|
public Map<String, Variant> getVariantCacheEntriesWithEtags(HttpHost host, HttpRequest request)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Map<String,HttpCacheEntry> variants = new HashMap<String,HttpCacheEntry>();
|
Map<String,Variant> variants = new HashMap<String,Variant>();
|
||||||
HttpCacheEntry root = storage.getEntry(uriExtractor.getURI(host, request));
|
HttpCacheEntry root = storage.getEntry(uriExtractor.getURI(host, request));
|
||||||
if (root == null || !root.hasVariants()) return variants;
|
if (root == null || !root.hasVariants()) return variants;
|
||||||
for(String variantCacheKey : root.getVariantMap().values()) {
|
for(Map.Entry<String, String> variant : root.getVariantMap().entrySet()) {
|
||||||
|
String variantKey = variant.getKey();
|
||||||
|
String variantCacheKey = variant.getValue();
|
||||||
HttpCacheEntry entry = storage.getEntry(variantCacheKey);
|
HttpCacheEntry entry = storage.getEntry(variantCacheKey);
|
||||||
|
if (entry == null) continue;
|
||||||
Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
|
Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
|
||||||
if (etagHeader != null) {
|
if (etagHeader == null) continue;
|
||||||
variants.put(etagHeader.getValue(), entry);
|
variants.put(etagHeader.getValue(), new Variant(variantKey, variantCacheKey, entry));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return variants;
|
return variants;
|
||||||
}
|
}
|
||||||
|
|
|
@ -412,15 +412,15 @@ public class CachingHttpClient implements HttpClient {
|
||||||
"Gateway Timeout");
|
"Gateway Timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String,HttpCacheEntry> variantEntries = null;
|
Map<String,Variant> variants = null;
|
||||||
try {
|
try {
|
||||||
variantEntries = responseCache.getVariantCacheEntriesWithEtags(target, request);
|
variants = responseCache.getVariantCacheEntriesWithEtags(target, request);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
log.warn("Unable to retrieve variant entries from cache", ioe);
|
log.warn("Unable to retrieve variant entries from cache", ioe);
|
||||||
}
|
}
|
||||||
if (variantEntries != null && variantEntries.size() > 0) {
|
if (variants != null && variants.size() > 0) {
|
||||||
try {
|
try {
|
||||||
return negotiateResponseFromVariants(target, request, context, variantEntries);
|
return negotiateResponseFromVariants(target, request, context, variants);
|
||||||
} catch (ProtocolException e) {
|
} catch (ProtocolException e) {
|
||||||
throw new ClientProtocolException(e);
|
throw new ClientProtocolException(e);
|
||||||
}
|
}
|
||||||
|
@ -594,8 +594,8 @@ public class CachingHttpClient implements HttpClient {
|
||||||
|
|
||||||
HttpResponse negotiateResponseFromVariants(HttpHost target,
|
HttpResponse negotiateResponseFromVariants(HttpHost target,
|
||||||
HttpRequest request, HttpContext context,
|
HttpRequest request, HttpContext context,
|
||||||
Map<String, HttpCacheEntry> variantEntries) throws IOException, ProtocolException {
|
Map<String, Variant> variants) throws IOException, ProtocolException {
|
||||||
HttpRequest conditionalRequest = conditionalRequestBuilder.buildConditionalRequestFromVariants(request, variantEntries);
|
HttpRequest conditionalRequest = conditionalRequestBuilder.buildConditionalRequestFromVariants(request, variants);
|
||||||
|
|
||||||
Date requestDate = getCurrentDate();
|
Date requestDate = getCurrentDate();
|
||||||
HttpResponse backendResponse = backend.execute(target, conditionalRequest, context);
|
HttpResponse backendResponse = backend.execute(target, conditionalRequest, context);
|
||||||
|
@ -605,7 +605,6 @@ public class CachingHttpClient implements HttpClient {
|
||||||
|
|
||||||
if (backendResponse.getStatusLine().getStatusCode() != HttpStatus.SC_NOT_MODIFIED) {
|
if (backendResponse.getStatusLine().getStatusCode() != HttpStatus.SC_NOT_MODIFIED) {
|
||||||
return handleBackendResponse(target, request, requestDate, responseDate, backendResponse);
|
return handleBackendResponse(target, request, requestDate, responseDate, backendResponse);
|
||||||
// return handleBackendResponse(target, conditionalRequest, requestDate, responseDate, backendResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Header resultEtagHeader = backendResponse.getFirstHeader(HeaderConstants.ETAG);
|
Header resultEtagHeader = backendResponse.getFirstHeader(HeaderConstants.ETAG);
|
||||||
|
@ -615,13 +614,15 @@ public class CachingHttpClient implements HttpClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
String resultEtag = resultEtagHeader.getValue();
|
String resultEtag = resultEtagHeader.getValue();
|
||||||
HttpCacheEntry matchedEntry = variantEntries.get(resultEtag);
|
Variant matchingVariant = variants.get(resultEtag);
|
||||||
|
|
||||||
if (matchedEntry == null) {
|
if (matchingVariant == null) {
|
||||||
log.debug("304 response did not contain ETag matching one sent in If-None-Match");
|
log.debug("304 response did not contain ETag matching one sent in If-None-Match");
|
||||||
return callBackend(target, request, context);
|
return callBackend(target, request, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpCacheEntry matchedEntry = matchingVariant.getEntry();
|
||||||
|
|
||||||
if (revalidationResponseIsTooOld(backendResponse, matchedEntry)) {
|
if (revalidationResponseIsTooOld(backendResponse, matchedEntry)) {
|
||||||
HttpRequest unconditional = conditionalRequestBuilder
|
HttpRequest unconditional = conditionalRequestBuilder
|
||||||
.buildUnconditionalRequest(request, matchedEntry);
|
.buildUnconditionalRequest(request, matchedEntry);
|
||||||
|
|
|
@ -93,7 +93,7 @@ class ConditionalRequestBuilder {
|
||||||
* @throws ProtocolException when I am unable to build a new origin request.
|
* @throws ProtocolException when I am unable to build a new origin request.
|
||||||
*/
|
*/
|
||||||
public HttpRequest buildConditionalRequestFromVariants(HttpRequest request,
|
public HttpRequest buildConditionalRequestFromVariants(HttpRequest request,
|
||||||
Map<String, HttpCacheEntry> variantEntries)
|
Map<String, Variant> variants)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
RequestWrapper wrapperRequest = new RequestWrapper(request);
|
RequestWrapper wrapperRequest = new RequestWrapper(request);
|
||||||
wrapperRequest.resetHeaders();
|
wrapperRequest.resetHeaders();
|
||||||
|
@ -101,7 +101,7 @@ class ConditionalRequestBuilder {
|
||||||
// we do not support partial content so all etags are used
|
// we do not support partial content so all etags are used
|
||||||
StringBuilder etags = new StringBuilder();
|
StringBuilder etags = new StringBuilder();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for(String etag : variantEntries.keySet()) {
|
for(String etag : variants.keySet()) {
|
||||||
if (!first) {
|
if (!first) {
|
||||||
etags.append(",");
|
etags.append(",");
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ interface HttpCache {
|
||||||
* @return a <code>Map</code> mapping Etags to variant cache entries
|
* @return a <code>Map</code> mapping Etags to variant cache entries
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
Map<String,HttpCacheEntry> getVariantCacheEntriesWithEtags(HttpHost host, HttpRequest request)
|
Map<String,Variant> getVariantCacheEntriesWithEtags(HttpHost host, HttpRequest request)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.HttpVersion;
|
import org.apache.http.HttpVersion;
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
|
||||||
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.easymock.IExpectationSetters;
|
import org.easymock.IExpectationSetters;
|
||||||
|
@ -104,7 +103,7 @@ public abstract class AbstractProtocolTest {
|
||||||
EasyMock.expect(mockCache.getCacheEntry(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)))
|
EasyMock.expect(mockCache.getCacheEntry(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)))
|
||||||
.andReturn(null).anyTimes();
|
.andReturn(null).anyTimes();
|
||||||
EasyMock.expect(mockCache.getVariantCacheEntriesWithEtags(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)))
|
EasyMock.expect(mockCache.getVariantCacheEntriesWithEtags(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)))
|
||||||
.andReturn(new HashMap<String,HttpCacheEntry>()).anyTimes();
|
.andReturn(new HashMap<String,Variant>()).anyTimes();
|
||||||
|
|
||||||
mockCache.flushCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class));
|
mockCache.flushCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class));
|
||||||
EasyMock.expectLastCall().anyTimes();
|
EasyMock.expectLastCall().anyTimes();
|
||||||
|
|
|
@ -338,7 +338,7 @@ public class TestBasicHttpCache {
|
||||||
HttpHost host = new HttpHost("foo.example.com");
|
HttpHost host = new HttpHost("foo.example.com");
|
||||||
HttpRequest request = new HttpGet("http://foo.example.com/bar");
|
HttpRequest request = new HttpGet("http://foo.example.com/bar");
|
||||||
|
|
||||||
Map<String,HttpCacheEntry> variants = impl.getVariantCacheEntriesWithEtags(host, request);
|
Map<String,Variant> variants = impl.getVariantCacheEntriesWithEtags(host, request);
|
||||||
|
|
||||||
assertNotNull(variants);
|
assertNotNull(variants);
|
||||||
assertEquals(0, variants.size());
|
assertEquals(0, variants.size());
|
||||||
|
@ -372,7 +372,7 @@ public class TestBasicHttpCache {
|
||||||
impl.cacheAndReturnResponse(host, req1, resp1, new Date(), new Date());
|
impl.cacheAndReturnResponse(host, req1, resp1, new Date(), new Date());
|
||||||
impl.cacheAndReturnResponse(host, req2, resp2, new Date(), new Date());
|
impl.cacheAndReturnResponse(host, req2, resp2, new Date(), new Date());
|
||||||
|
|
||||||
Map<String,HttpCacheEntry> variants = impl.getVariantCacheEntriesWithEtags(host, req1);
|
Map<String,Variant> variants = impl.getVariantCacheEntriesWithEtags(host, req1);
|
||||||
|
|
||||||
assertNotNull(variants);
|
assertNotNull(variants);
|
||||||
assertEquals(2, variants.size());
|
assertEquals(2, variants.size());
|
||||||
|
|
|
@ -300,7 +300,7 @@ public class TestCachingHttpClient {
|
||||||
cacheInvalidatorWasCalled();
|
cacheInvalidatorWasCalled();
|
||||||
requestPolicyAllowsCaching(true);
|
requestPolicyAllowsCaching(true);
|
||||||
getCacheEntryReturns(null);
|
getCacheEntryReturns(null);
|
||||||
getVariantCacheEntriesReturns(new HashMap<String,HttpCacheEntry>());
|
getVariantCacheEntriesReturns(new HashMap<String,Variant>());
|
||||||
|
|
||||||
requestProtocolValidationIsCalled();
|
requestProtocolValidationIsCalled();
|
||||||
requestIsFatallyNonCompliant(null);
|
requestIsFatallyNonCompliant(null);
|
||||||
|
@ -450,7 +450,7 @@ public class TestCachingHttpClient {
|
||||||
@Test
|
@Test
|
||||||
public void testRevalidationRetriesUnconditionallyIfOlderResponseReceived()
|
public void testRevalidationRetriesUnconditionallyIfOlderResponseReceived()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
// TODO
|
|
||||||
mockImplMethods(GET_CURRENT_DATE);
|
mockImplMethods(GET_CURRENT_DATE);
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
|
@ -1593,10 +1593,10 @@ public class TestCachingHttpClient {
|
||||||
HttpCacheEntry variant3 = HttpTestUtils
|
HttpCacheEntry variant3 = HttpTestUtils
|
||||||
.makeCacheEntry(new Header[] {new BasicHeader(HeaderConstants.ETAG, "\"etag3\"") });
|
.makeCacheEntry(new Header[] {new BasicHeader(HeaderConstants.ETAG, "\"etag3\"") });
|
||||||
|
|
||||||
Map<String,HttpCacheEntry> variants = new HashMap<String,HttpCacheEntry>();
|
Map<String,Variant> variants = new HashMap<String,Variant>();
|
||||||
variants.put("\"etag1\"", variant1);
|
variants.put("\"etag1\"", new Variant("A","B",variant1));
|
||||||
variants.put("\"etag2\"", variant2);
|
variants.put("\"etag2\"", new Variant("C","D",variant2));
|
||||||
variants.put("\"etag3\"", variant3);
|
variants.put("\"etag3\"", new Variant("E","F",variant3));
|
||||||
|
|
||||||
HttpRequest variantConditionalRequest = new BasicHttpRequest("GET", "http://foo.com/bar", HttpVersion.HTTP_1_1);
|
HttpRequest variantConditionalRequest = new BasicHttpRequest("GET", "http://foo.com/bar", HttpVersion.HTTP_1_1);
|
||||||
variantConditionalRequest.addHeader(new BasicHeader(HeaderConstants.IF_NONE_MATCH, "etag1, etag2, etag3"));
|
variantConditionalRequest.addHeader(new BasicHeader(HeaderConstants.IF_NONE_MATCH, "etag1, etag2, etag3"));
|
||||||
|
@ -1641,10 +1641,10 @@ public class TestCachingHttpClient {
|
||||||
|
|
||||||
HttpCacheEntry cacheEntry = null;
|
HttpCacheEntry cacheEntry = null;
|
||||||
|
|
||||||
Map<String,HttpCacheEntry> variants = new HashMap<String,HttpCacheEntry>();
|
Map<String,Variant> variants = new HashMap<String,Variant>();
|
||||||
variants.put("\"etag1\"", variant1);
|
variants.put("\"etag1\"", new Variant("A","B",variant1));
|
||||||
variants.put("\"etag2\"", variant2);
|
variants.put("\"etag2\"", new Variant("C","D",variant2));
|
||||||
variants.put("\"etag3\"", variant3);
|
variants.put("\"etag3\"", new Variant("E","F",variant3));
|
||||||
|
|
||||||
HttpRequest variantConditionalRequest = new BasicHttpRequest("GET", "http://foo.com/bar", HttpVersion.HTTP_1_1);
|
HttpRequest variantConditionalRequest = new BasicHttpRequest("GET", "http://foo.com/bar", HttpVersion.HTTP_1_1);
|
||||||
variantConditionalRequest.addHeader(new BasicHeader(HeaderConstants.IF_NONE_MATCH, "etag1, etag2, etag3"));
|
variantConditionalRequest.addHeader(new BasicHeader(HeaderConstants.IF_NONE_MATCH, "etag1, etag2, etag3"));
|
||||||
|
@ -1957,7 +1957,7 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(result);
|
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getVariantCacheEntriesReturns(Map<String,HttpCacheEntry> result) throws IOException {
|
private void getVariantCacheEntriesReturns(Map<String,Variant> result) throws IOException {
|
||||||
EasyMock.expect(mockCache.getVariantCacheEntriesWithEtags(host, request)).andReturn(result);
|
EasyMock.expect(mockCache.getVariantCacheEntriesWithEtags(host, request)).andReturn(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1989,7 +1989,7 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.<HttpCacheEntry>anyObject())).andReturn(b);
|
EasyMock.<HttpCacheEntry>anyObject())).andReturn(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void conditionalVariantRequestBuilderReturns(Map<String,HttpCacheEntry> variantEntries, HttpRequest validate)
|
private void conditionalVariantRequestBuilderReturns(Map<String,Variant> variantEntries, HttpRequest validate)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
EasyMock.expect(mockConditionalRequestBuilder.buildConditionalRequestFromVariants(request, variantEntries))
|
EasyMock.expect(mockConditionalRequestBuilder.buildConditionalRequestFromVariants(request, variantEntries))
|
||||||
.andReturn(validate);
|
.andReturn(validate);
|
||||||
|
|
|
@ -307,10 +307,10 @@ public class TestConditionalRequestBuilder {
|
||||||
String etag2 = "\"456\"";
|
String etag2 = "\"456\"";
|
||||||
String etag3 = "\"789\"";
|
String etag3 = "\"789\"";
|
||||||
|
|
||||||
Map<String,HttpCacheEntry> variantEntries = new HashMap<String,HttpCacheEntry>();
|
Map<String,Variant> variantEntries = new HashMap<String,Variant>();
|
||||||
variantEntries.put(etag1, HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag1) }));
|
variantEntries.put(etag1, new Variant("A","B",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag1) })));
|
||||||
variantEntries.put(etag2, HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag2) }));
|
variantEntries.put(etag2, new Variant("C","D",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag2) })));
|
||||||
variantEntries.put(etag3, HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag3) }));
|
variantEntries.put(etag3, new Variant("E","F",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag3) })));
|
||||||
|
|
||||||
HttpRequest conditional = impl.buildConditionalRequestFromVariants(request, variantEntries);
|
HttpRequest conditional = impl.buildConditionalRequestFromVariants(request, variantEntries);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue