HTTPCLIENT-975: committed patch to support stale-if-error from
RFC5861, with thanks to Mohammed Azeem Uddin (mohammedazeem_uddin at comcast dot com). git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1049179 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8aef0609de
commit
a91847b57c
|
@ -30,6 +30,7 @@ import java.util.Date;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HeaderElement;
|
import org.apache.http.HeaderElement;
|
||||||
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.annotation.Immutable;
|
import org.apache.http.annotation.Immutable;
|
||||||
import org.apache.http.client.cache.HeaderConstants;
|
import org.apache.http.client.cache.HeaderConstants;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
import org.apache.http.client.cache.HttpCacheEntry;
|
||||||
|
@ -119,6 +120,35 @@ class CacheValidityPolicy {
|
||||||
return hasCacheControlDirective(entry, "proxy-revalidate");
|
return hasCacheControlDirective(entry, "proxy-revalidate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean mayReturnStaleIfError(HttpRequest request,
|
||||||
|
HttpCacheEntry entry, Date now) {
|
||||||
|
long stalenessSecs = getStalenessSecs(entry, now);
|
||||||
|
return mayReturnStaleIfError(request.getHeaders("Cache-Control"),
|
||||||
|
stalenessSecs)
|
||||||
|
|| mayReturnStaleIfError(entry.getHeaders("Cache-Control"),
|
||||||
|
stalenessSecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean mayReturnStaleIfError(Header[] headers, long stalenessSecs) {
|
||||||
|
boolean result = false;
|
||||||
|
for(Header h : headers) {
|
||||||
|
for(HeaderElement elt : h.getElements()) {
|
||||||
|
if ("stale-if-error".equals(elt.getName())) {
|
||||||
|
try {
|
||||||
|
int staleIfErrorSecs = Integer.parseInt(elt.getValue());
|
||||||
|
if (stalenessSecs <= staleIfErrorSecs) {
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
// skip malformed directive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
protected Date getDateValue(final HttpCacheEntry entry) {
|
protected Date getDateValue(final HttpCacheEntry entry) {
|
||||||
Header dateHdr = entry.getFirstHeader(HTTP.DATE_HEADER);
|
Header dateHdr = entry.getFirstHeader(HTTP.DATE_HEADER);
|
||||||
if (dateHdr == null)
|
if (dateHdr == null)
|
||||||
|
|
|
@ -692,10 +692,24 @@ public class CachingHttpClient implements HttpClient {
|
||||||
return responseGenerator.generateResponse(updatedEntry);
|
return responseGenerator.generateResponse(updatedEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (staleIfErrorAppliesTo(statusCode)
|
||||||
|
&& validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
|
||||||
|
final HttpResponse cachedResponse = responseGenerator.generateResponse(cacheEntry);
|
||||||
|
cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
|
||||||
|
return cachedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
return handleBackendResponse(target, conditionalRequest, requestDate, responseDate,
|
return handleBackendResponse(target, conditionalRequest, requestDate, responseDate,
|
||||||
backendResponse);
|
backendResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean staleIfErrorAppliesTo(int statusCode) {
|
||||||
|
return statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR
|
||||||
|
|| statusCode == HttpStatus.SC_BAD_GATEWAY
|
||||||
|
|| statusCode == HttpStatus.SC_SERVICE_UNAVAILABLE
|
||||||
|
|| statusCode == HttpStatus.SC_GATEWAY_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
HttpResponse handleBackendResponse(
|
HttpResponse handleBackendResponse(
|
||||||
HttpHost target,
|
HttpHost target,
|
||||||
HttpRequest request,
|
HttpRequest request,
|
||||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HeaderElement;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpMessage;
|
import org.apache.http.HttpMessage;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
|
@ -43,8 +44,10 @@ import org.apache.http.client.cache.HttpCacheEntry;
|
||||||
import org.apache.http.entity.ByteArrayEntity;
|
import org.apache.http.entity.ByteArrayEntity;
|
||||||
import org.apache.http.impl.cookie.DateUtils;
|
import org.apache.http.impl.cookie.DateUtils;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicHeader;
|
||||||
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
import org.apache.http.message.BasicHttpResponse;
|
import org.apache.http.message.BasicHttpResponse;
|
||||||
import org.apache.http.message.BasicStatusLine;
|
import org.apache.http.message.BasicStatusLine;
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
public class HttpTestUtils {
|
public class HttpTestUtils {
|
||||||
|
|
||||||
|
@ -54,7 +57,7 @@ public class HttpTestUtils {
|
||||||
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
|
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
|
||||||
*/
|
*/
|
||||||
private static final String[] HOP_BY_HOP_HEADERS = { "Connection", "Keep-Alive", "Proxy-Authenticate",
|
private static final String[] HOP_BY_HOP_HEADERS = { "Connection", "Keep-Alive", "Proxy-Authenticate",
|
||||||
"Proxy-Authorization", "TE", "Trailers", "Transfer-Encoding", "Upgrade" };
|
"Proxy-Authorization", "TE", "Trailers", "Transfer-Encoding", "Upgrade" };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Multiple message-header fields with the same field-name MAY be present
|
* "Multiple message-header fields with the same field-name MAY be present
|
||||||
|
@ -64,15 +67,15 @@ public class HttpTestUtils {
|
||||||
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
|
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
|
||||||
*/
|
*/
|
||||||
private static final String[] MULTI_HEADERS = { "Accept", "Accept-Charset", "Accept-Encoding",
|
private static final String[] MULTI_HEADERS = { "Accept", "Accept-Charset", "Accept-Encoding",
|
||||||
"Accept-Language", "Allow", "Cache-Control", "Connection", "Content-Encoding",
|
"Accept-Language", "Allow", "Cache-Control", "Connection", "Content-Encoding",
|
||||||
"Content-Language", "Expect", "Pragma", "Proxy-Authenticate", "TE", "Trailer",
|
"Content-Language", "Expect", "Pragma", "Proxy-Authenticate", "TE", "Trailer",
|
||||||
"Transfer-Encoding", "Upgrade", "Via", "Warning", "WWW-Authenticate" };
|
"Transfer-Encoding", "Upgrade", "Via", "Warning", "WWW-Authenticate" };
|
||||||
private static final String[] SINGLE_HEADERS = { "Accept-Ranges", "Age", "Authorization",
|
private static final String[] SINGLE_HEADERS = { "Accept-Ranges", "Age", "Authorization",
|
||||||
"Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type",
|
"Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type",
|
||||||
"Date", "ETag", "Expires", "From", "Host", "If-Match", "If-Modified-Since",
|
"Date", "ETag", "Expires", "From", "Host", "If-Match", "If-Modified-Since",
|
||||||
"If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified", "Location",
|
"If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified", "Location",
|
||||||
"Max-Forwards", "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
|
"Max-Forwards", "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
|
||||||
"User-Agent", "Vary" };
|
"User-Agent", "Vary" };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determines whether the given header name is considered a hop-by-hop
|
* Determines whether the given header name is considered a hop-by-hop
|
||||||
|
@ -150,7 +153,7 @@ public class HttpTestUtils {
|
||||||
public static boolean equivalent(RequestLine l1, RequestLine l2) {
|
public static boolean equivalent(RequestLine l1, RequestLine l2) {
|
||||||
return (l1.getMethod().equals(l2.getMethod())
|
return (l1.getMethod().equals(l2.getMethod())
|
||||||
&& l1.getProtocolVersion().equals(l2.getProtocolVersion()) && l1.getUri().equals(
|
&& l1.getProtocolVersion().equals(l2.getProtocolVersion()) && l1.getUri().equals(
|
||||||
l2.getUri()));
|
l2.getUri()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -202,13 +205,13 @@ public class HttpTestUtils {
|
||||||
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html#sec1.3
|
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html#sec1.3
|
||||||
*/
|
*/
|
||||||
public static boolean semanticallyTransparent(HttpResponse r1, HttpResponse r2)
|
public static boolean semanticallyTransparent(HttpResponse r1, HttpResponse r2)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final boolean entitiesEquivalent = equivalent(r1.getEntity(), r2.getEntity());
|
final boolean entitiesEquivalent = equivalent(r1.getEntity(), r2.getEntity());
|
||||||
if (!entitiesEquivalent) return false;
|
if (!entitiesEquivalent) return false;
|
||||||
final boolean statusLinesEquivalent = semanticallyTransparent(r1.getStatusLine(), r2.getStatusLine());
|
final boolean statusLinesEquivalent = semanticallyTransparent(r1.getStatusLine(), r2.getStatusLine());
|
||||||
if (!statusLinesEquivalent) return false;
|
if (!statusLinesEquivalent) return false;
|
||||||
final boolean e2eHeadersEquivalentSubset = isEndToEndHeaderSubset(
|
final boolean e2eHeadersEquivalentSubset = isEndToEndHeaderSubset(
|
||||||
r1, r2);
|
r1, r2);
|
||||||
return e2eHeadersEquivalentSubset;
|
return e2eHeadersEquivalentSubset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,4 +300,35 @@ public class HttpTestUtils {
|
||||||
out.setEntity(makeBody(128));
|
out.setEntity(makeBody(128));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final HttpResponse make200Response(Date date, String cacheControl) {
|
||||||
|
HttpResponse response = HttpTestUtils.make200Response();
|
||||||
|
response.setHeader("Date", DateUtils.formatDate(date));
|
||||||
|
response.setHeader("Cache-Control",cacheControl);
|
||||||
|
response.setHeader("Etag","\"etag\"");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final void assert110WarningFound(HttpResponse response) {
|
||||||
|
boolean found110Warning = false;
|
||||||
|
for(Header h : response.getHeaders("Warning")) {
|
||||||
|
for(HeaderElement elt : h.getElements()) {
|
||||||
|
String[] parts = elt.getName().split("\\s");
|
||||||
|
if ("110".equals(parts[0])) {
|
||||||
|
found110Warning = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertTrue(found110Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpRequest makeDefaultRequest() {
|
||||||
|
return new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpResponse make500Response() {
|
||||||
|
return new BasicHttpResponse(HttpVersion.HTTP_1_1,
|
||||||
|
HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -26,107 +26,101 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.http.impl.client.cache;
|
package org.apache.http.impl.client.cache;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HttpRequest;
|
||||||
|
import org.apache.http.HttpVersion;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
import org.apache.http.client.cache.HttpCacheEntry;
|
||||||
import org.apache.http.impl.cookie.DateUtils;
|
import org.apache.http.impl.cookie.DateUtils;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicHeader;
|
||||||
import org.junit.Assert;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TestCacheValidityPolicy {
|
public class TestCacheValidityPolicy {
|
||||||
|
|
||||||
|
private CacheValidityPolicy impl;
|
||||||
|
private Date now;
|
||||||
|
private Date oneSecondAgo;
|
||||||
|
private Date sixSecondsAgo;
|
||||||
|
private Date tenSecondsAgo;
|
||||||
|
private Date elevenSecondsAgo;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
impl = new CacheValidityPolicy();
|
||||||
|
now = new Date();
|
||||||
|
oneSecondAgo = new Date(now.getTime() - 1 * 1000L);
|
||||||
|
sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
||||||
|
tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||||
|
elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testApparentAgeIsMaxIntIfDateHeaderNotPresent() {
|
public void testApparentAgeIsMaxIntIfDateHeaderNotPresent() {
|
||||||
Header[] headers = {
|
Header[] headers = {
|
||||||
new BasicHeader("Server", "MockServer/1.0")
|
new BasicHeader("Server", "MockServer/1.0")
|
||||||
};
|
};
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(2147483648L, impl.getApparentAgeSecs(entry));
|
||||||
Assert.assertEquals(2147483648L, impl.getApparentAgeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testApparentAgeIsResponseReceivedTimeLessDateHeader() {
|
public void testApparentAgeIsResponseReceivedTimeLessDateHeader() {
|
||||||
Date now = new Date();
|
|
||||||
Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
|
||||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
|
||||||
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
|
Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
|
||||||
.formatDate(tenSecondsAgo)) };
|
.formatDate(tenSecondsAgo)) };
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo, headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo, headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(4, impl.getApparentAgeSecs(entry));
|
||||||
|
|
||||||
Assert.assertEquals(4, impl.getApparentAgeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNegativeApparentAgeIsBroughtUpToZero() {
|
public void testNegativeApparentAgeIsBroughtUpToZero() {
|
||||||
Date now = new Date();
|
|
||||||
Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
|
||||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
|
||||||
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
|
Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
|
||||||
.formatDate(sixSecondsAgo)) };
|
.formatDate(sixSecondsAgo)) };
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now,tenSecondsAgo,headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now,tenSecondsAgo,headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(0, impl.getApparentAgeSecs(entry));
|
||||||
Assert.assertEquals(0, impl.getApparentAgeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCorrectedReceivedAgeIsAgeHeaderIfLarger() {
|
public void testCorrectedReceivedAgeIsAgeHeaderIfLarger() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Age", "10"), };
|
Header[] headers = new Header[] { new BasicHeader("Age", "10"), };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
|
impl = new CacheValidityPolicy() {
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long getApparentAgeSecs(HttpCacheEntry entry) {
|
protected long getApparentAgeSecs(HttpCacheEntry entry) {
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
assertEquals(10, impl.getCorrectedReceivedAgeSecs(entry));
|
||||||
Assert.assertEquals(10, impl.getCorrectedReceivedAgeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCorrectedReceivedAgeIsApparentAgeIfLarger() {
|
public void testCorrectedReceivedAgeIsApparentAgeIfLarger() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Age", "6"), };
|
Header[] headers = new Header[] { new BasicHeader("Age", "6"), };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
|
impl = new CacheValidityPolicy() {
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long getApparentAgeSecs(HttpCacheEntry entry) {
|
protected long getApparentAgeSecs(HttpCacheEntry entry) {
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
assertEquals(10, impl.getCorrectedReceivedAgeSecs(entry));
|
||||||
Assert.assertEquals(10, impl.getCorrectedReceivedAgeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResponseDelayIsDifferenceBetweenResponseAndRequestTimes() {
|
public void testResponseDelayIsDifferenceBetweenResponseAndRequestTimes() {
|
||||||
Date now = new Date();
|
|
||||||
Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
|
||||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, sixSecondsAgo);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, sixSecondsAgo);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(4, impl.getResponseDelaySecs(entry));
|
||||||
|
|
||||||
Assert.assertEquals(4, impl.getResponseDelaySecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCorrectedInitialAgeIsCorrectedReceivedAgePlusResponseDelay() {
|
public void testCorrectedInitialAgeIsCorrectedReceivedAgePlusResponseDelay() {
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long getCorrectedReceivedAgeSecs(HttpCacheEntry entry) {
|
protected long getCorrectedReceivedAgeSecs(HttpCacheEntry entry) {
|
||||||
return 7;
|
return 7;
|
||||||
|
@ -136,62 +130,50 @@ public class TestCacheValidityPolicy {
|
||||||
protected long getResponseDelaySecs(HttpCacheEntry entry) {
|
protected long getResponseDelaySecs(HttpCacheEntry entry) {
|
||||||
return 13;
|
return 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
Assert.assertEquals(20, impl.getCorrectedInitialAgeSecs(entry));
|
assertEquals(20, impl.getCorrectedInitialAgeSecs(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResidentTimeSecondsIsTimeSinceResponseTime() {
|
public void testResidentTimeSecondsIsTimeSinceResponseTime() {
|
||||||
final Date now = new Date();
|
|
||||||
final Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo);
|
||||||
|
impl = new CacheValidityPolicy() {
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Date getCurrentDate() {
|
protected Date getCurrentDate() {
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
assertEquals(6, impl.getResidentTimeSecs(entry, now));
|
||||||
Assert.assertEquals(6, impl.getResidentTimeSecs(entry, now));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCurrentAgeIsCorrectedInitialAgePlusResidentTime() {
|
public void testCurrentAgeIsCorrectedInitialAgePlusResidentTime() {
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long getCorrectedInitialAgeSecs(HttpCacheEntry entry) {
|
protected long getCorrectedInitialAgeSecs(HttpCacheEntry entry) {
|
||||||
return 11;
|
return 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long getResidentTimeSecs(HttpCacheEntry entry, Date d) {
|
protected long getResidentTimeSecs(HttpCacheEntry entry, Date d) {
|
||||||
return 17;
|
return 17;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Assert.assertEquals(28, impl.getCurrentAgeSecs(entry, new Date()));
|
assertEquals(28, impl.getCurrentAgeSecs(entry, new Date()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFreshnessLifetimeIsSMaxAgeIfPresent() {
|
public void testFreshnessLifetimeIsSMaxAgeIfPresent() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10") };
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
||||||
Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFreshnessLifetimeIsMaxAgeIfPresent() {
|
public void testFreshnessLifetimeIsMaxAgeIfPresent() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10") };
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
||||||
Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -199,312 +181,269 @@ public class TestCacheValidityPolicy {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
|
||||||
new BasicHeader("Cache-Control", "s-maxage=20") };
|
new BasicHeader("Cache-Control", "s-maxage=20") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
||||||
Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
|
||||||
|
|
||||||
headers = new Header[] { new BasicHeader("Cache-Control", "max-age=20"),
|
headers = new Header[] { new BasicHeader("Cache-Control", "max-age=20"),
|
||||||
new BasicHeader("Cache-Control", "s-maxage=10") };
|
new BasicHeader("Cache-Control", "s-maxage=10") };
|
||||||
entry = HttpTestUtils.makeCacheEntry(headers);
|
entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFreshnessLifetimeIsMaxAgeEvenIfExpiresIsPresent() {
|
public void testFreshnessLifetimeIsMaxAgeEvenIfExpiresIsPresent() {
|
||||||
Date now = new Date();
|
|
||||||
Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
|
||||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
|
||||||
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
||||||
Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFreshnessLifetimeIsSMaxAgeEvenIfExpiresIsPresent() {
|
public void testFreshnessLifetimeIsSMaxAgeEvenIfExpiresIsPresent() {
|
||||||
Date now = new Date();
|
|
||||||
Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
|
||||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10"),
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10"),
|
||||||
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
||||||
Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFreshnessLifetimeIsFromExpiresHeaderIfNoMaxAge() {
|
public void testFreshnessLifetimeIsFromExpiresHeaderIfNoMaxAge() {
|
||||||
Date now = new Date();
|
|
||||||
Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
|
||||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
|
||||||
Header[] headers = new Header[] {
|
Header[] headers = new Header[] {
|
||||||
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(4, impl.getFreshnessLifetimeSecs(entry));
|
||||||
Assert.assertEquals(4, impl.getFreshnessLifetimeSecs(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHeuristicFreshnessLifetime() {
|
public void testHeuristicFreshnessLifetime() {
|
||||||
Date now = new Date();
|
|
||||||
Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L);
|
|
||||||
Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L);
|
|
||||||
|
|
||||||
Header[] headers = new Header[] {
|
Header[] headers = new Header[] {
|
||||||
new BasicHeader("Date", DateUtils.formatDate(oneSecondAgo)),
|
new BasicHeader("Date", DateUtils.formatDate(oneSecondAgo)),
|
||||||
new BasicHeader("Last-Modified", DateUtils.formatDate(elevenSecondsAgo))
|
new BasicHeader("Last-Modified", DateUtils.formatDate(elevenSecondsAgo))
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertEquals(1, impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, 0));
|
||||||
Assert.assertEquals(1, impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHeuristicFreshnessLifetimeDefaultsProperly() {
|
public void testHeuristicFreshnessLifetimeDefaultsProperly() {
|
||||||
long defaultFreshness = 10;
|
long defaultFreshness = 10;
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
|
assertEquals(defaultFreshness, impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, defaultFreshness));
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
|
||||||
Assert.assertEquals(defaultFreshness, impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, defaultFreshness));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHeuristicFreshnessLifetimeIsNonNegative() {
|
public void testHeuristicFreshnessLifetimeIsNonNegative() {
|
||||||
Date now = new Date();
|
|
||||||
Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L);
|
|
||||||
Date elevenSecondsAgo = new Date(now.getTime() - 1 * 1000L);
|
|
||||||
|
|
||||||
Header[] headers = new Header[] {
|
Header[] headers = new Header[] {
|
||||||
new BasicHeader("Date", DateUtils.formatDate(elevenSecondsAgo)),
|
new BasicHeader("Date", DateUtils.formatDate(elevenSecondsAgo)),
|
||||||
new BasicHeader("Last-Modified", DateUtils.formatDate(oneSecondAgo))
|
new BasicHeader("Last-Modified", DateUtils.formatDate(oneSecondAgo))
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertTrue(impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, 10) >= 0);
|
||||||
Assert.assertTrue(impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, 10) >= 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResponseIsFreshIfFreshnessLifetimeExceedsCurrentAge() {
|
public void testResponseIsFreshIfFreshnessLifetimeExceedsCurrentAge() {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
final Date now = new Date();
|
impl = new CacheValidityPolicy() {
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentAgeSecs(HttpCacheEntry e, Date d) {
|
public long getCurrentAgeSecs(HttpCacheEntry e, Date d) {
|
||||||
Assert.assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
Assert.assertEquals(now, d);
|
assertEquals(now, d);
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getFreshnessLifetimeSecs(HttpCacheEntry e) {
|
public long getFreshnessLifetimeSecs(HttpCacheEntry e) {
|
||||||
Assert.assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
assertTrue(impl.isResponseFresh(entry, now));
|
||||||
Assert.assertTrue(impl.isResponseFresh(entry, now));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResponseIsNotFreshIfFreshnessLifetimeEqualsCurrentAge() {
|
public void testResponseIsNotFreshIfFreshnessLifetimeEqualsCurrentAge() {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
final Date now = new Date();
|
impl = new CacheValidityPolicy() {
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentAgeSecs(HttpCacheEntry e, Date d) {
|
public long getCurrentAgeSecs(HttpCacheEntry e, Date d) {
|
||||||
Assert.assertEquals(now, d);
|
assertEquals(now, d);
|
||||||
Assert.assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getFreshnessLifetimeSecs(HttpCacheEntry e) {
|
public long getFreshnessLifetimeSecs(HttpCacheEntry e) {
|
||||||
Assert.assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
assertFalse(impl.isResponseFresh(entry, now));
|
||||||
Assert.assertFalse(impl.isResponseFresh(entry, now));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResponseIsNotFreshIfCurrentAgeExceedsFreshnessLifetime() {
|
public void testResponseIsNotFreshIfCurrentAgeExceedsFreshnessLifetime() {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
final Date now = new Date();
|
impl = new CacheValidityPolicy() {
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentAgeSecs(HttpCacheEntry e, Date d) {
|
public long getCurrentAgeSecs(HttpCacheEntry e, Date d) {
|
||||||
Assert.assertEquals(now, d);
|
assertEquals(now, d);
|
||||||
Assert.assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getFreshnessLifetimeSecs(HttpCacheEntry e) {
|
public long getFreshnessLifetimeSecs(HttpCacheEntry e) {
|
||||||
Assert.assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
assertFalse(impl.isResponseFresh(entry, now));
|
||||||
Assert.assertFalse(impl.isResponseFresh(entry, now));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCacheEntryIsRevalidatableIfHeadersIncludeETag() {
|
public void testCacheEntryIsRevalidatableIfHeadersIncludeETag() {
|
||||||
|
|
||||||
Header[] headers = {
|
Header[] headers = {
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(new Date())),
|
new BasicHeader("Expires", DateUtils.formatDate(new Date())),
|
||||||
new BasicHeader("ETag", "somevalue")};
|
new BasicHeader("ETag", "somevalue")};
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertTrue(impl.isRevalidatable(entry));
|
||||||
|
|
||||||
Assert.assertTrue(impl.isRevalidatable(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCacheEntryIsRevalidatableIfHeadersIncludeLastModifiedDate() {
|
public void testCacheEntryIsRevalidatableIfHeadersIncludeLastModifiedDate() {
|
||||||
|
|
||||||
Header[] headers = {
|
Header[] headers = {
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(new Date())),
|
new BasicHeader("Expires", DateUtils.formatDate(new Date())),
|
||||||
new BasicHeader("Last-Modified", DateUtils.formatDate(new Date())) };
|
new BasicHeader("Last-Modified", DateUtils.formatDate(new Date())) };
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertTrue(impl.isRevalidatable(entry));
|
||||||
|
|
||||||
Assert.assertTrue(impl.isRevalidatable(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCacheEntryIsNotRevalidatableIfNoAppropriateHeaders() {
|
public void testCacheEntryIsNotRevalidatableIfNoAppropriateHeaders() {
|
||||||
|
|
||||||
Header[] headers = {
|
Header[] headers = {
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(new Date())),
|
new BasicHeader("Expires", DateUtils.formatDate(new Date())),
|
||||||
new BasicHeader("Cache-Control", "public") };
|
new BasicHeader("Cache-Control", "public") };
|
||||||
|
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertFalse(impl.isRevalidatable(entry));
|
||||||
|
|
||||||
Assert.assertFalse(impl.isRevalidatable(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMalformedDateHeaderIsIgnored() {
|
public void testMalformedDateHeaderIsIgnored() {
|
||||||
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Date", "asdf") };
|
Header[] headers = new Header[] { new BasicHeader("Date", "asdf") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
|
assertNull(impl.getDateValue(entry));
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
|
||||||
Date d = impl.getDateValue(entry);
|
|
||||||
|
|
||||||
Assert.assertNull(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMalformedContentLengthReturnsNegativeOne() {
|
public void testMalformedContentLengthReturnsNegativeOne() {
|
||||||
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Content-Length", "asdf") };
|
Header[] headers = new Header[] { new BasicHeader("Content-Length", "asdf") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
|
assertEquals(-1, impl.getContentLengthValue(entry));
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
|
||||||
long length = impl.getContentLengthValue(entry);
|
|
||||||
|
|
||||||
Assert.assertEquals(-1, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNegativeAgeHeaderValueReturnsMaxAge() {
|
public void testNegativeAgeHeaderValueReturnsMaxAge() {
|
||||||
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Age", "-100") };
|
Header[] headers = new Header[] { new BasicHeader("Age", "-100") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
|
assertEquals(CacheValidityPolicy.MAX_AGE, impl.getAgeValue(entry));
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
|
||||||
long length = impl.getAgeValue(entry);
|
|
||||||
|
|
||||||
Assert.assertEquals(CacheValidityPolicy.MAX_AGE, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMalformedAgeHeaderValueReturnsMaxAge() {
|
public void testMalformedAgeHeaderValueReturnsMaxAge() {
|
||||||
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Age", "asdf") };
|
Header[] headers = new Header[] { new BasicHeader("Age", "asdf") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
|
assertEquals(CacheValidityPolicy.MAX_AGE, impl.getAgeValue(entry));
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
|
||||||
long length = impl.getAgeValue(entry);
|
|
||||||
|
|
||||||
Assert.assertEquals(CacheValidityPolicy.MAX_AGE, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMalformedCacheControlMaxAgeHeaderReturnsZero() {
|
public void testMalformedCacheControlMaxAgeHeaderReturnsZero() {
|
||||||
|
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=asdf") };
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=asdf") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
|
assertEquals(0, impl.getMaxAge(entry));
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
|
||||||
long maxage = impl.getMaxAge(entry);
|
|
||||||
|
|
||||||
Assert.assertEquals(0, maxage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMalformedExpirationDateReturnsNull() {
|
public void testMalformedExpirationDateReturnsNull() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Expires", "asdf") };
|
Header[] headers = new Header[] { new BasicHeader("Expires", "asdf") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
|
assertNull(impl.getExpirationDate(entry));
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
|
||||||
Date expirationDate = impl.getExpirationDate(entry);
|
|
||||||
|
|
||||||
Assert.assertNull(expirationDate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMustRevalidateIsFalseIfDirectiveNotPresent() {
|
public void testMustRevalidateIsFalseIfDirectiveNotPresent() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertFalse(impl.mustRevalidate(entry));
|
||||||
|
|
||||||
Assert.assertFalse(impl.mustRevalidate(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMustRevalidateIsTrueWhenDirectiveIsPresent() {
|
public void testMustRevalidateIsTrueWhenDirectiveIsPresent() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, must-revalidate") };
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, must-revalidate") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertTrue(impl.mustRevalidate(entry));
|
||||||
|
|
||||||
Assert.assertTrue(impl.mustRevalidate(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProxyRevalidateIsFalseIfDirectiveNotPresent() {
|
public void testProxyRevalidateIsFalseIfDirectiveNotPresent() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertFalse(impl.proxyRevalidate(entry));
|
||||||
|
|
||||||
Assert.assertFalse(impl.proxyRevalidate(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProxyRevalidateIsTrueWhenDirectiveIsPresent() {
|
public void testProxyRevalidateIsTrueWhenDirectiveIsPresent() {
|
||||||
Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, proxy-revalidate") };
|
Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, proxy-revalidate") };
|
||||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
assertTrue(impl.proxyRevalidate(entry));
|
||||||
|
|
||||||
Assert.assertTrue(impl.proxyRevalidate(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMayReturnStaleIfErrorInResponseIsTrueWithinStaleness(){
|
||||||
|
Header[] headers = new Header[] {
|
||||||
|
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
||||||
|
new BasicHeader("Cache-Control", "max-age=5, stale-if-error=15")
|
||||||
|
};
|
||||||
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
|
||||||
|
HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
|
||||||
|
assertTrue(impl.mayReturnStaleIfError(req, entry, now));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMayReturnStaleIfErrorInRequestIsTrueWithinStaleness(){
|
||||||
|
Header[] headers = new Header[] {
|
||||||
|
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
||||||
|
new BasicHeader("Cache-Control", "max-age=5")
|
||||||
|
};
|
||||||
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
|
||||||
|
HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
|
||||||
|
req.setHeader("Cache-Control","stale-if-error=15");
|
||||||
|
assertTrue(impl.mayReturnStaleIfError(req, entry, now));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMayNotReturnStaleIfErrorInResponseAndAfterResponseWindow(){
|
||||||
|
Header[] headers = new Header[] {
|
||||||
|
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
||||||
|
new BasicHeader("Cache-Control", "max-age=5, stale-if-error=1")
|
||||||
|
};
|
||||||
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
|
||||||
|
HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
|
||||||
|
assertFalse(impl.mayReturnStaleIfError(req, entry, now));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMayNotReturnStaleIfErrorInResponseAndAfterRequestWindow(){
|
||||||
|
Header[] headers = new Header[] {
|
||||||
|
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
|
||||||
|
new BasicHeader("Cache-Control", "max-age=5")
|
||||||
|
};
|
||||||
|
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
|
||||||
|
HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
|
||||||
|
req.setHeader("Cache-Control","stale-if-error=1");
|
||||||
|
assertFalse(impl.mayReturnStaleIfError(req, entry, now));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
157
httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java
vendored
Normal file
157
httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java
vendored
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This software consists of voluntary contributions made by many
|
||||||
|
* individuals on behalf of the Apache Software Foundation. For more
|
||||||
|
* information on the Apache Software Foundation, please see
|
||||||
|
* <http://www.apache.org/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.apache.http.impl.client.cache;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.apache.http.HttpRequest;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A suite of acceptance tests for compliance with RFC5861, which
|
||||||
|
* describes the stale-if-error and stale-while-revalidate
|
||||||
|
* Cache-Control extensions.
|
||||||
|
*/
|
||||||
|
public class TestRFC5861Compliance extends AbstractProtocolTest {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "The stale-if-error Cache-Control extension indicates that when an
|
||||||
|
* error is encountered, a cached stale response MAY be used to satisfy
|
||||||
|
* the request, regardless of other freshness information.When used as a
|
||||||
|
* request Cache-Control extension, its scope of application is the request
|
||||||
|
* it appears in; when used as a response Cache-Control extension, its
|
||||||
|
* scope is any request applicable to the cached response in which it
|
||||||
|
* occurs.Its value indicates the upper limit to staleness; when the cached
|
||||||
|
* response is more stale than the indicated amount, the cached response
|
||||||
|
* SHOULD NOT be used to satisfy the request, absent other information.
|
||||||
|
* In this context, an error is any situation that would result in a
|
||||||
|
* 500, 502, 503, or 504 HTTP response status code being returned."
|
||||||
|
*
|
||||||
|
* http://tools.ietf.org/html/rfc5861
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testStaleIfErrorInResponseIsTrueReturnsStaleEntryWithWarning()
|
||||||
|
throws Exception{
|
||||||
|
Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
|
||||||
|
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||||
|
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||||
|
"public, max-age=5, stale-if-error=60");
|
||||||
|
|
||||||
|
backendExpectsAnyRequest().andReturn(resp1);
|
||||||
|
|
||||||
|
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||||
|
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||||
|
|
||||||
|
backendExpectsAnyRequest().andReturn(resp2);
|
||||||
|
|
||||||
|
replayMocks();
|
||||||
|
impl.execute(host,req1);
|
||||||
|
HttpResponse result = impl.execute(host,req2);
|
||||||
|
verifyMocks();
|
||||||
|
|
||||||
|
HttpTestUtils.assert110WarningFound(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStaleIfErrorInRequestIsTrueReturnsStaleEntryWithWarning()
|
||||||
|
throws Exception{
|
||||||
|
Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
|
||||||
|
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||||
|
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||||
|
"public, max-age=5");
|
||||||
|
|
||||||
|
backendExpectsAnyRequest().andReturn(resp1);
|
||||||
|
|
||||||
|
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||||
|
req2.setHeader("Cache-Control","public, max-age=5, stale-if-error=60");
|
||||||
|
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||||
|
|
||||||
|
backendExpectsAnyRequest().andReturn(resp2);
|
||||||
|
|
||||||
|
replayMocks();
|
||||||
|
impl.execute(host,req1);
|
||||||
|
HttpResponse result = impl.execute(host,req2);
|
||||||
|
verifyMocks();
|
||||||
|
|
||||||
|
HttpTestUtils.assert110WarningFound(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStaleIfErrorInResponseIsFalseReturnsError()
|
||||||
|
throws Exception{
|
||||||
|
Date now = new Date();
|
||||||
|
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||||
|
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||||
|
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||||
|
"public, max-age=5, stale-if-error=2");
|
||||||
|
|
||||||
|
backendExpectsAnyRequest().andReturn(resp1);
|
||||||
|
|
||||||
|
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||||
|
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||||
|
|
||||||
|
backendExpectsAnyRequest().andReturn(resp2);
|
||||||
|
|
||||||
|
replayMocks();
|
||||||
|
impl.execute(host,req1);
|
||||||
|
HttpResponse result = impl.execute(host,req2);
|
||||||
|
verifyMocks();
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR,
|
||||||
|
result.getStatusLine().getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStaleIfErrorInRequestIsFalseReturnsError()
|
||||||
|
throws Exception{
|
||||||
|
Date now = new Date();
|
||||||
|
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||||
|
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||||
|
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||||
|
"public, max-age=5");
|
||||||
|
|
||||||
|
backendExpectsAnyRequest().andReturn(resp1);
|
||||||
|
|
||||||
|
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||||
|
req2.setHeader("Cache-Control","stale-if-error=2");
|
||||||
|
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||||
|
|
||||||
|
backendExpectsAnyRequest().andReturn(resp2);
|
||||||
|
|
||||||
|
replayMocks();
|
||||||
|
impl.execute(host,req1);
|
||||||
|
HttpResponse result = impl.execute(host,req2);
|
||||||
|
verifyMocks();
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR,
|
||||||
|
result.getStatusLine().getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue