HTTPCLIENT-2036: CacheValidityPolicy should use TimeValue
This closes #201
This commit is contained in:
parent
071fa68a3c
commit
26991b8059
|
@ -39,46 +39,48 @@ import org.apache.hc.core5.http.HttpHeaders;
|
||||||
import org.apache.hc.core5.http.HttpRequest;
|
import org.apache.hc.core5.http.HttpRequest;
|
||||||
import org.apache.hc.core5.http.MessageHeaders;
|
import org.apache.hc.core5.http.MessageHeaders;
|
||||||
import org.apache.hc.core5.http.message.MessageSupport;
|
import org.apache.hc.core5.http.message.MessageSupport;
|
||||||
|
import org.apache.hc.core5.util.TimeValue;
|
||||||
|
|
||||||
class CacheValidityPolicy {
|
class CacheValidityPolicy {
|
||||||
|
|
||||||
public static final long MAX_AGE = 2147483648L;
|
public static final TimeValue MAX_AGE = TimeValue.ofSeconds(Integer.MAX_VALUE + 1L);
|
||||||
|
|
||||||
CacheValidityPolicy() {
|
CacheValidityPolicy() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getCurrentAgeSecs(final HttpCacheEntry entry, final Date now) {
|
public TimeValue getCurrentAge(final HttpCacheEntry entry, final Date now) {
|
||||||
return getCorrectedInitialAgeSecs(entry) + getResidentTimeSecs(entry, now);
|
return TimeValue.ofSeconds(getCorrectedInitialAge(entry).toSeconds() + getResidentTime(entry, now).toSeconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getFreshnessLifetimeSecs(final HttpCacheEntry entry) {
|
public TimeValue getFreshnessLifetime(final HttpCacheEntry entry) {
|
||||||
final long maxAge = getMaxAge(entry);
|
final long maxAge = getMaxAge(entry);
|
||||||
if (maxAge > -1) {
|
if (maxAge > -1) {
|
||||||
return maxAge;
|
return TimeValue.ofSeconds(maxAge);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Date dateValue = entry.getDate();
|
final Date dateValue = entry.getDate();
|
||||||
if (dateValue == null) {
|
if (dateValue == null) {
|
||||||
return 0L;
|
return TimeValue.ZERO_MILLISECONDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Date expiry = DateUtils.parseDate(entry, HeaderConstants.EXPIRES);
|
final Date expiry = DateUtils.parseDate(entry, HeaderConstants.EXPIRES);
|
||||||
if (expiry == null) {
|
if (expiry == null) {
|
||||||
return 0;
|
return TimeValue.ZERO_MILLISECONDS;
|
||||||
}
|
}
|
||||||
final long diff = expiry.getTime() - dateValue.getTime();
|
final long diff = expiry.getTime() - dateValue.getTime();
|
||||||
return (diff / 1000);
|
return TimeValue.ofSeconds(diff / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isResponseFresh(final HttpCacheEntry entry, final Date now) {
|
public boolean isResponseFresh(final HttpCacheEntry entry, final Date now) {
|
||||||
return (getCurrentAgeSecs(entry, now) < getFreshnessLifetimeSecs(entry));
|
return getCurrentAge(entry, now).compareTo(getFreshnessLifetime(entry)) == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decides if this response is fresh enough based Last-Modified and Date, if available.
|
* Decides if this response is fresh enough based Last-Modified and Date, if available.
|
||||||
* This entry is meant to be used when isResponseFresh returns false. The algorithm is as follows:
|
* This entry is meant to be used when isResponseFresh returns false.
|
||||||
*
|
*
|
||||||
|
* The algorithm is as follows:
|
||||||
* if last-modified and date are defined, freshness lifetime is coefficient*(date-lastModified),
|
* if last-modified and date are defined, freshness lifetime is coefficient*(date-lastModified),
|
||||||
* else freshness lifetime is defaultLifetime
|
* else freshness lifetime is defaultLifetime
|
||||||
*
|
*
|
||||||
|
@ -89,21 +91,21 @@ class CacheValidityPolicy {
|
||||||
* @return {@code true} if the response is fresh
|
* @return {@code true} if the response is fresh
|
||||||
*/
|
*/
|
||||||
public boolean isResponseHeuristicallyFresh(final HttpCacheEntry entry,
|
public boolean isResponseHeuristicallyFresh(final HttpCacheEntry entry,
|
||||||
final Date now, final float coefficient, final long defaultLifetime) {
|
final Date now, final float coefficient, final TimeValue defaultLifetime) {
|
||||||
return (getCurrentAgeSecs(entry, now) < getHeuristicFreshnessLifetimeSecs(entry, coefficient, defaultLifetime));
|
return getCurrentAge(entry, now).compareTo(getHeuristicFreshnessLifetime(entry, coefficient, defaultLifetime)) == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getHeuristicFreshnessLifetimeSecs(final HttpCacheEntry entry,
|
public TimeValue getHeuristicFreshnessLifetime(final HttpCacheEntry entry,
|
||||||
final float coefficient, final long defaultLifetime) {
|
final float coefficient, final TimeValue defaultLifetime) {
|
||||||
final Date dateValue = entry.getDate();
|
final Date dateValue = entry.getDate();
|
||||||
final Date lastModifiedValue = DateUtils.parseDate(entry, HeaderConstants.LAST_MODIFIED);
|
final Date lastModifiedValue = DateUtils.parseDate(entry, HeaderConstants.LAST_MODIFIED);
|
||||||
|
|
||||||
if (dateValue != null && lastModifiedValue != null) {
|
if (dateValue != null && lastModifiedValue != null) {
|
||||||
final long diff = dateValue.getTime() - lastModifiedValue.getTime();
|
final long diff = dateValue.getTime() - lastModifiedValue.getTime();
|
||||||
if (diff < 0) {
|
if (diff < 0) {
|
||||||
return 0;
|
return TimeValue.ZERO_MILLISECONDS;
|
||||||
}
|
}
|
||||||
return (long)(coefficient * (diff / 1000));
|
return TimeValue.ofSeconds((long) (coefficient * diff / 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultLifetime;
|
return defaultLifetime;
|
||||||
|
@ -128,8 +130,9 @@ class CacheValidityPolicy {
|
||||||
final HeaderElement elt = it.next();
|
final HeaderElement elt = it.next();
|
||||||
if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) {
|
if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) {
|
||||||
try {
|
try {
|
||||||
|
// in seconds
|
||||||
final int allowedStalenessLifetime = Integer.parseInt(elt.getValue());
|
final int allowedStalenessLifetime = Integer.parseInt(elt.getValue());
|
||||||
if (getStalenessSecs(entry, now) <= allowedStalenessLifetime) {
|
if (getStaleness(entry, now).compareTo(TimeValue.ofSeconds(allowedStalenessLifetime)) <= 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (final NumberFormatException nfe) {
|
} catch (final NumberFormatException nfe) {
|
||||||
|
@ -142,20 +145,21 @@ class CacheValidityPolicy {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean mayReturnStaleIfError(final HttpRequest request, final HttpCacheEntry entry, final Date now) {
|
public boolean mayReturnStaleIfError(final HttpRequest request, final HttpCacheEntry entry, final Date now) {
|
||||||
final long stalenessSecs = getStalenessSecs(entry, now);
|
final TimeValue staleness = getStaleness(entry, now);
|
||||||
return mayReturnStaleIfError(request, HeaderConstants.CACHE_CONTROL, stalenessSecs)
|
return mayReturnStaleIfError(request, HeaderConstants.CACHE_CONTROL, staleness)
|
||||||
|| mayReturnStaleIfError(entry, HeaderConstants.CACHE_CONTROL, stalenessSecs);
|
|| mayReturnStaleIfError(entry, HeaderConstants.CACHE_CONTROL, staleness);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mayReturnStaleIfError(final MessageHeaders headers, final String name, final long stalenessSecs) {
|
private boolean mayReturnStaleIfError(final MessageHeaders headers, final String name, final TimeValue staleness) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
final Iterator<HeaderElement> it = MessageSupport.iterate(headers, name);
|
final Iterator<HeaderElement> it = MessageSupport.iterate(headers, name);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
final HeaderElement elt = it.next();
|
final HeaderElement elt = it.next();
|
||||||
if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) {
|
if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) {
|
||||||
try {
|
try {
|
||||||
final int staleIfErrorSecs = Integer.parseInt(elt.getValue());
|
// in seconds
|
||||||
if (stalenessSecs <= staleIfErrorSecs) {
|
final int staleIfError = Integer.parseInt(elt.getValue());
|
||||||
|
if (staleness.compareTo(TimeValue.ofSeconds(staleIfError)) <= 0) {
|
||||||
result = true;
|
result = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -192,56 +196,58 @@ class CacheValidityPolicy {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getApparentAgeSecs(final HttpCacheEntry entry) {
|
protected TimeValue getApparentAge(final HttpCacheEntry entry) {
|
||||||
final Date dateValue = entry.getDate();
|
final Date dateValue = entry.getDate();
|
||||||
if (dateValue == null) {
|
if (dateValue == null) {
|
||||||
return MAX_AGE;
|
return MAX_AGE;
|
||||||
}
|
}
|
||||||
final long diff = entry.getResponseDate().getTime() - dateValue.getTime();
|
final long diff = entry.getResponseDate().getTime() - dateValue.getTime();
|
||||||
if (diff < 0L) {
|
if (diff < 0L) {
|
||||||
return 0;
|
return TimeValue.ZERO_MILLISECONDS;
|
||||||
}
|
}
|
||||||
return (diff / 1000);
|
return TimeValue.ofSeconds(diff / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getAgeValue(final HttpCacheEntry entry) {
|
protected long getAgeValue(final HttpCacheEntry entry) {
|
||||||
|
// This is a header value, we leave as-is
|
||||||
long ageValue = 0;
|
long ageValue = 0;
|
||||||
for (final Header hdr : entry.getHeaders(HeaderConstants.AGE)) {
|
for (final Header hdr : entry.getHeaders(HeaderConstants.AGE)) {
|
||||||
long hdrAge;
|
long hdrAge;
|
||||||
try {
|
try {
|
||||||
hdrAge = Long.parseLong(hdr.getValue());
|
hdrAge = Long.parseLong(hdr.getValue());
|
||||||
if (hdrAge < 0) {
|
if (hdrAge < 0) {
|
||||||
hdrAge = MAX_AGE;
|
hdrAge = MAX_AGE.toSeconds();
|
||||||
}
|
}
|
||||||
} catch (final NumberFormatException nfe) {
|
} catch (final NumberFormatException nfe) {
|
||||||
hdrAge = MAX_AGE;
|
hdrAge = MAX_AGE.toSeconds();
|
||||||
}
|
}
|
||||||
ageValue = (hdrAge > ageValue) ? hdrAge : ageValue;
|
ageValue = (hdrAge > ageValue) ? hdrAge : ageValue;
|
||||||
}
|
}
|
||||||
return ageValue;
|
return ageValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getCorrectedReceivedAgeSecs(final HttpCacheEntry entry) {
|
protected TimeValue getCorrectedReceivedAge(final HttpCacheEntry entry) {
|
||||||
final long apparentAge = getApparentAgeSecs(entry);
|
final TimeValue apparentAge = getApparentAge(entry);
|
||||||
final long ageValue = getAgeValue(entry);
|
final long ageValue = getAgeValue(entry);
|
||||||
return (apparentAge > ageValue) ? apparentAge : ageValue;
|
return (apparentAge.toSeconds() > ageValue) ? apparentAge : TimeValue.ofSeconds(ageValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getResponseDelaySecs(final HttpCacheEntry entry) {
|
protected TimeValue getResponseDelay(final HttpCacheEntry entry) {
|
||||||
final long diff = entry.getResponseDate().getTime() - entry.getRequestDate().getTime();
|
final long diff = entry.getResponseDate().getTime() - entry.getRequestDate().getTime();
|
||||||
return (diff / 1000L);
|
return TimeValue.ofSeconds(diff / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getCorrectedInitialAgeSecs(final HttpCacheEntry entry) {
|
protected TimeValue getCorrectedInitialAge(final HttpCacheEntry entry) {
|
||||||
return getCorrectedReceivedAgeSecs(entry) + getResponseDelaySecs(entry);
|
return TimeValue.ofSeconds(getCorrectedReceivedAge(entry).toSeconds() + getResponseDelay(entry).toSeconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getResidentTimeSecs(final HttpCacheEntry entry, final Date now) {
|
protected TimeValue getResidentTime(final HttpCacheEntry entry, final Date now) {
|
||||||
final long diff = now.getTime() - entry.getResponseDate().getTime();
|
final long diff = now.getTime() - entry.getResponseDate().getTime();
|
||||||
return (diff / 1000L);
|
return TimeValue.ofSeconds(diff / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getMaxAge(final HttpCacheEntry entry) {
|
protected long getMaxAge(final HttpCacheEntry entry) {
|
||||||
|
// This is a header value, we leave as-is
|
||||||
long maxAge = -1;
|
long maxAge = -1;
|
||||||
final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
|
final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
|
@ -272,13 +278,13 @@ class CacheValidityPolicy {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getStalenessSecs(final HttpCacheEntry entry, final Date now) {
|
public TimeValue getStaleness(final HttpCacheEntry entry, final Date now) {
|
||||||
final long age = getCurrentAgeSecs(entry, now);
|
final TimeValue age = getCurrentAge(entry, now);
|
||||||
final long freshness = getFreshnessLifetimeSecs(entry);
|
final TimeValue freshness = getFreshnessLifetime(entry);
|
||||||
if (age <= freshness) {
|
if (age.compareTo(freshness) <= 0) {
|
||||||
return 0L;
|
return TimeValue.ZERO_MILLISECONDS;
|
||||||
}
|
}
|
||||||
return (age - freshness);
|
return TimeValue.ofSeconds(age.toSeconds() - freshness.toSeconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ import org.apache.hc.core5.http.HttpResponse;
|
||||||
import org.apache.hc.core5.http.HttpStatus;
|
import org.apache.hc.core5.http.HttpStatus;
|
||||||
import org.apache.hc.core5.http.HttpVersion;
|
import org.apache.hc.core5.http.HttpVersion;
|
||||||
import org.apache.hc.core5.http.message.BasicHeader;
|
import org.apache.hc.core5.http.message.BasicHeader;
|
||||||
|
import org.apache.hc.core5.util.TimeValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rebuilds an {@link HttpResponse} from a {@link HttpCacheEntry}
|
* Rebuilds an {@link HttpResponse} from a {@link HttpCacheEntry}
|
||||||
|
@ -78,12 +79,12 @@ class CachedHttpResponseGenerator {
|
||||||
response.setBodyBytes(content, contentType);
|
response.setBodyBytes(content, contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
final long age = this.validityStrategy.getCurrentAgeSecs(entry, now);
|
final TimeValue age = this.validityStrategy.getCurrentAge(entry, now);
|
||||||
if (age > 0) {
|
if (TimeValue.isPositive(age)) {
|
||||||
if (age >= Integer.MAX_VALUE) {
|
if (age.compareTo(CacheValidityPolicy.MAX_AGE) >= 0) {
|
||||||
response.setHeader(HeaderConstants.AGE, "2147483648");
|
response.setHeader(HeaderConstants.AGE, "" + CacheValidityPolicy.MAX_AGE.toSeconds());
|
||||||
} else {
|
} else {
|
||||||
response.setHeader(HeaderConstants.AGE, "" + ((int) age));
|
response.setHeader(HeaderConstants.AGE, "" + age.toSeconds());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class CachedResponseSuitabilityChecker {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (useHeuristicCaching &&
|
if (useHeuristicCaching &&
|
||||||
validityStrategy.isResponseHeuristicallyFresh(entry, now, heuristicCoefficient, heuristicDefaultLifetime.toSeconds())) {
|
validityStrategy.isResponseHeuristicallyFresh(entry, now, heuristicCoefficient, heuristicDefaultLifetime)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (originInsistsOnFreshness(entry)) {
|
if (originInsistsOnFreshness(entry)) {
|
||||||
|
@ -85,7 +85,7 @@ class CachedResponseSuitabilityChecker {
|
||||||
if (maxStale == -1) {
|
if (maxStale == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (maxStale > validityStrategy.getStalenessSecs(entry, now));
|
return (maxStale > validityStrategy.getStaleness(entry, now).toSeconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean originInsistsOnFreshness(final HttpCacheEntry entry) {
|
private boolean originInsistsOnFreshness(final HttpCacheEntry entry) {
|
||||||
|
@ -100,6 +100,7 @@ class CachedResponseSuitabilityChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getMaxStale(final HttpRequest request) {
|
private long getMaxStale(final HttpRequest request) {
|
||||||
|
// This is a header value, we leave as-is
|
||||||
long maxStale = -1;
|
long maxStale = -1;
|
||||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
|
@ -186,8 +187,9 @@ class CachedResponseSuitabilityChecker {
|
||||||
|
|
||||||
if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
|
if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
|
||||||
try {
|
try {
|
||||||
|
// in seconds
|
||||||
final int maxAge = Integer.parseInt(elt.getValue());
|
final int maxAge = Integer.parseInt(elt.getValue());
|
||||||
if (validityStrategy.getCurrentAgeSecs(entry, now) > maxAge) {
|
if (validityStrategy.getCurrentAge(entry, now).toSeconds() > maxAge) {
|
||||||
log.debug("Response from cache was not suitable due to max age");
|
log.debug("Response from cache was not suitable due to max age");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -200,8 +202,9 @@ class CachedResponseSuitabilityChecker {
|
||||||
|
|
||||||
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
|
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
|
||||||
try {
|
try {
|
||||||
|
// in seconds
|
||||||
final int maxStale = Integer.parseInt(elt.getValue());
|
final int maxStale = Integer.parseInt(elt.getValue());
|
||||||
if (validityStrategy.getFreshnessLifetimeSecs(entry) > maxStale) {
|
if (validityStrategy.getFreshnessLifetime(entry).toSeconds() > maxStale) {
|
||||||
log.debug("Response from cache was not suitable due to max stale freshness");
|
log.debug("Response from cache was not suitable due to max stale freshness");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -214,13 +217,14 @@ class CachedResponseSuitabilityChecker {
|
||||||
|
|
||||||
if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
|
if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
|
||||||
try {
|
try {
|
||||||
|
// in seconds
|
||||||
final long minFresh = Long.parseLong(elt.getValue());
|
final long minFresh = Long.parseLong(elt.getValue());
|
||||||
if (minFresh < 0L) {
|
if (minFresh < 0L) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final long age = validityStrategy.getCurrentAgeSecs(entry, now);
|
final TimeValue age = validityStrategy.getCurrentAge(entry, now);
|
||||||
final long freshness = validityStrategy.getFreshnessLifetimeSecs(entry);
|
final TimeValue freshness = validityStrategy.getFreshnessLifetime(entry);
|
||||||
if (freshness - age < minFresh) {
|
if (freshness.toSeconds() - age.toSeconds() < minFresh) {
|
||||||
log.debug("Response from cache was not suitable due to min fresh " +
|
log.debug("Response from cache was not suitable due to min fresh " +
|
||||||
"freshness requirement");
|
"freshness requirement");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -54,6 +54,7 @@ import org.apache.hc.core5.http.ProtocolVersion;
|
||||||
import org.apache.hc.core5.http.URIScheme;
|
import org.apache.hc.core5.http.URIScheme;
|
||||||
import org.apache.hc.core5.http.message.MessageSupport;
|
import org.apache.hc.core5.http.message.MessageSupport;
|
||||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||||
|
import org.apache.hc.core5.util.TimeValue;
|
||||||
import org.apache.hc.core5.util.VersionInfo;
|
import org.apache.hc.core5.util.VersionInfo;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -189,7 +190,7 @@ public class CachingExecBase {
|
||||||
cachedResponse = responseGenerator.generateResponse(request, entry);
|
cachedResponse = responseGenerator.generateResponse(request, entry);
|
||||||
}
|
}
|
||||||
setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
|
setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
|
||||||
if (validityPolicy.getStalenessSecs(entry, now) > 0L) {
|
if (TimeValue.isPositive(validityPolicy.getStaleness(entry, now))) {
|
||||||
cachedResponse.addHeader(HeaderConstants.WARNING,"110 localhost \"Response is stale\"");
|
cachedResponse.addHeader(HeaderConstants.WARNING,"110 localhost \"Response is stale\"");
|
||||||
}
|
}
|
||||||
return cachedResponse;
|
return cachedResponse;
|
||||||
|
@ -247,10 +248,11 @@ public class CachingExecBase {
|
||||||
final HeaderElement elt = it.next();
|
final HeaderElement elt = it.next();
|
||||||
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
|
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
|
||||||
try {
|
try {
|
||||||
|
// in seconds
|
||||||
final int maxStale = Integer.parseInt(elt.getValue());
|
final int maxStale = Integer.parseInt(elt.getValue());
|
||||||
final long age = validityPolicy.getCurrentAgeSecs(entry, now);
|
final TimeValue age = validityPolicy.getCurrentAge(entry, now);
|
||||||
final long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry);
|
final TimeValue lifetime = validityPolicy.getFreshnessLifetime(entry);
|
||||||
if (age - lifetime > maxStale) {
|
if (age.toSeconds() - lifetime.toSeconds() > maxStale) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (final NumberFormatException nfe) {
|
} catch (final NumberFormatException nfe) {
|
||||||
|
|
|
@ -61,6 +61,7 @@ import org.apache.hc.core5.http.message.BasicHttpRequest;
|
||||||
import org.apache.hc.core5.http.message.BasicLineFormatter;
|
import org.apache.hc.core5.http.message.BasicLineFormatter;
|
||||||
import org.apache.hc.core5.http.message.StatusLine;
|
import org.apache.hc.core5.http.message.StatusLine;
|
||||||
import org.apache.hc.core5.util.CharArrayBuffer;
|
import org.apache.hc.core5.util.CharArrayBuffer;
|
||||||
|
import org.apache.hc.core5.util.TimeValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache serializer and deserializer that uses an HTTP-like format.
|
* Cache serializer and deserializer that uses an HTTP-like format.
|
||||||
|
@ -402,15 +403,15 @@ public class HttpByteArrayCacheEntrySerializer implements HttpCacheEntrySerializ
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache validity policy that always returns an age of 0.
|
* Cache validity policy that always returns an age of {@link TimeValue#ZERO_MILLISECONDS}.
|
||||||
*
|
*
|
||||||
* This prevents the Age header from being written to the cache (it does not make sense to cache it),
|
* This prevents the Age header from being written to the cache (it does not make sense to cache it),
|
||||||
* and is the only thing the policy is used for in this case.
|
* and is the only thing the policy is used for in this case.
|
||||||
*/
|
*/
|
||||||
private static class NoAgeCacheValidityPolicy extends CacheValidityPolicy {
|
private static class NoAgeCacheValidityPolicy extends CacheValidityPolicy {
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentAgeSecs(final HttpCacheEntry entry, final Date now) {
|
public TimeValue getCurrentAge(final HttpCacheEntry entry, final Date now) {
|
||||||
return 0L;
|
return TimeValue.ZERO_MILLISECONDS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.apache.hc.core5.http.HttpHeaders;
|
||||||
import org.apache.hc.core5.http.HttpRequest;
|
import org.apache.hc.core5.http.HttpRequest;
|
||||||
import org.apache.hc.core5.http.message.BasicHeader;
|
import org.apache.hc.core5.http.message.BasicHeader;
|
||||||
import org.apache.hc.core5.http.message.BasicHttpRequest;
|
import org.apache.hc.core5.http.message.BasicHttpRequest;
|
||||||
|
import org.apache.hc.core5.util.TimeValue;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ public class TestCacheValidityPolicy {
|
||||||
new BasicHeader("Server", "MockServer/1.0")
|
new BasicHeader("Server", "MockServer/1.0")
|
||||||
};
|
};
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(2147483648L, impl.getApparentAgeSecs(entry));
|
assertEquals(CacheValidityPolicy.MAX_AGE, impl.getApparentAge(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -77,15 +78,15 @@ public class TestCacheValidityPolicy {
|
||||||
.formatDate(tenSecondsAgo)) };
|
.formatDate(tenSecondsAgo)) };
|
||||||
|
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo, headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo, headers);
|
||||||
assertEquals(4, impl.getApparentAgeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(4), impl.getApparentAge(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNegativeApparentAgeIsBroughtUpToZero() {
|
public void testNegativeApparentAgeIsBroughtUpToZero() {
|
||||||
final Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
|
final Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
|
||||||
.formatDate(sixSecondsAgo)) };
|
.formatDate(sixSecondsAgo)) };
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now,tenSecondsAgo,headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, tenSecondsAgo, headers);
|
||||||
assertEquals(0, impl.getApparentAgeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(0), impl.getApparentAge(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -94,11 +95,11 @@ public class TestCacheValidityPolicy {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
@Override
|
@Override
|
||||||
protected long getApparentAgeSecs(final HttpCacheEntry ent) {
|
protected TimeValue getApparentAge(final HttpCacheEntry ent) {
|
||||||
return 6;
|
return TimeValue.ofSeconds(6);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assertEquals(10, impl.getCorrectedReceivedAgeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(10), impl.getCorrectedReceivedAge(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -107,17 +108,17 @@ public class TestCacheValidityPolicy {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
@Override
|
@Override
|
||||||
protected long getApparentAgeSecs(final HttpCacheEntry ent) {
|
protected TimeValue getApparentAge(final HttpCacheEntry ent) {
|
||||||
return 10;
|
return TimeValue.ofSeconds(10);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assertEquals(10, impl.getCorrectedReceivedAgeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(10), impl.getCorrectedReceivedAge(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResponseDelayIsDifferenceBetweenResponseAndRequestTimes() {
|
public void testResponseDelayIsDifferenceBetweenResponseAndRequestTimes() {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, sixSecondsAgo);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, sixSecondsAgo);
|
||||||
assertEquals(4, impl.getResponseDelaySecs(entry));
|
assertEquals(TimeValue.ofSeconds(4), impl.getResponseDelay(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -125,22 +126,22 @@ public class TestCacheValidityPolicy {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
@Override
|
@Override
|
||||||
protected long getCorrectedReceivedAgeSecs(final HttpCacheEntry ent) {
|
protected TimeValue getCorrectedReceivedAge(final HttpCacheEntry ent) {
|
||||||
return 7;
|
return TimeValue.ofSeconds(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long getResponseDelaySecs(final HttpCacheEntry ent) {
|
protected TimeValue getResponseDelay(final HttpCacheEntry ent) {
|
||||||
return 13;
|
return TimeValue.ofSeconds(13);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assertEquals(20, impl.getCorrectedInitialAgeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(20), impl.getCorrectedInitialAge(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResidentTimeSecondsIsTimeSinceResponseTime() {
|
public void testResidentTimeSecondsIsTimeSinceResponseTime() {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo);
|
||||||
assertEquals(6, impl.getResidentTimeSecs(entry, now));
|
assertEquals(TimeValue.ofSeconds(6), impl.getResidentTime(entry, now));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -148,29 +149,29 @@ public class TestCacheValidityPolicy {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
@Override
|
@Override
|
||||||
protected long getCorrectedInitialAgeSecs(final HttpCacheEntry ent) {
|
protected TimeValue getCorrectedInitialAge(final HttpCacheEntry ent) {
|
||||||
return 11;
|
return TimeValue.ofSeconds(11);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected long getResidentTimeSecs(final HttpCacheEntry ent, final Date d) {
|
protected TimeValue getResidentTime(final HttpCacheEntry ent, final Date d) {
|
||||||
return 17;
|
return TimeValue.ofSeconds(17);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assertEquals(28, impl.getCurrentAgeSecs(entry, new Date()));
|
assertEquals(TimeValue.ofSeconds(28), impl.getCurrentAge(entry, new Date()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFreshnessLifetimeIsSMaxAgeIfPresent() {
|
public void testFreshnessLifetimeIsSMaxAgeIfPresent() {
|
||||||
final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10") };
|
final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10") };
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFreshnessLifetimeIsMaxAgeIfPresent() {
|
public void testFreshnessLifetimeIsMaxAgeIfPresent() {
|
||||||
final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10") };
|
final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10") };
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -178,12 +179,12 @@ 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);
|
||||||
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(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);
|
||||||
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -193,7 +194,7 @@ public class TestCacheValidityPolicy {
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
||||||
|
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -203,7 +204,7 @@ public class TestCacheValidityPolicy {
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
||||||
|
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -213,7 +214,7 @@ public class TestCacheValidityPolicy {
|
||||||
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
|
||||||
|
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(4, impl.getFreshnessLifetimeSecs(entry));
|
assertEquals(TimeValue.ofSeconds(4), impl.getFreshnessLifetime(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -223,14 +224,14 @@ public class TestCacheValidityPolicy {
|
||||||
new BasicHeader("Last-Modified", DateUtils.formatDate(elevenSecondsAgo))
|
new BasicHeader("Last-Modified", DateUtils.formatDate(elevenSecondsAgo))
|
||||||
};
|
};
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(1, impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, 0));
|
assertEquals(TimeValue.ofSeconds(1), impl.getHeuristicFreshnessLifetime(entry, 0.1f, TimeValue.ZERO_MILLISECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHeuristicFreshnessLifetimeDefaultsProperly() {
|
public void testHeuristicFreshnessLifetimeDefaultsProperly() {
|
||||||
final long defaultFreshness = 10;
|
final TimeValue defaultFreshness = TimeValue.ofSeconds(10);
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
assertEquals(defaultFreshness, impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, defaultFreshness));
|
assertEquals(defaultFreshness, impl.getHeuristicFreshnessLifetime(entry, 0.1f, defaultFreshness));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -241,7 +242,7 @@ public class TestCacheValidityPolicy {
|
||||||
};
|
};
|
||||||
|
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertTrue(impl.getHeuristicFreshnessLifetimeSecs(entry, 0.1f, 10) >= 0);
|
assertTrue(TimeValue.isNonNegative(impl.getHeuristicFreshnessLifetime(entry, 0.1f, TimeValue.ofSeconds(10))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -249,15 +250,15 @@ public class TestCacheValidityPolicy {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentAgeSecs(final HttpCacheEntry e, final Date d) {
|
public TimeValue getCurrentAge(final HttpCacheEntry e, final Date d) {
|
||||||
assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
assertEquals(now, d);
|
assertEquals(now, d);
|
||||||
return 6;
|
return TimeValue.ofSeconds(6);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public long getFreshnessLifetimeSecs(final HttpCacheEntry e) {
|
public TimeValue getFreshnessLifetime(final HttpCacheEntry e) {
|
||||||
assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 10;
|
return TimeValue.ofSeconds(10);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assertTrue(impl.isResponseFresh(entry, now));
|
assertTrue(impl.isResponseFresh(entry, now));
|
||||||
|
@ -268,15 +269,15 @@ public class TestCacheValidityPolicy {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentAgeSecs(final HttpCacheEntry e, final Date d) {
|
public TimeValue getCurrentAge(final HttpCacheEntry e, final Date d) {
|
||||||
assertEquals(now, d);
|
assertEquals(now, d);
|
||||||
assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 6;
|
return TimeValue.ofSeconds(6);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public long getFreshnessLifetimeSecs(final HttpCacheEntry e) {
|
public TimeValue getFreshnessLifetime(final HttpCacheEntry e) {
|
||||||
assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 6;
|
return TimeValue.ofSeconds(6);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assertFalse(impl.isResponseFresh(entry, now));
|
assertFalse(impl.isResponseFresh(entry, now));
|
||||||
|
@ -287,15 +288,15 @@ public class TestCacheValidityPolicy {
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
|
||||||
impl = new CacheValidityPolicy() {
|
impl = new CacheValidityPolicy() {
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentAgeSecs(final HttpCacheEntry e, final Date d) {
|
public TimeValue getCurrentAge(final HttpCacheEntry e, final Date d) {
|
||||||
assertEquals(now, d);
|
assertEquals(now, d);
|
||||||
assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 10;
|
return TimeValue.ofSeconds(10);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public long getFreshnessLifetimeSecs(final HttpCacheEntry e) {
|
public TimeValue getFreshnessLifetime(final HttpCacheEntry e) {
|
||||||
assertSame(entry, e);
|
assertSame(entry, e);
|
||||||
return 6;
|
return TimeValue.ofSeconds(6);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assertFalse(impl.isResponseFresh(entry, now));
|
assertFalse(impl.isResponseFresh(entry, now));
|
||||||
|
@ -364,21 +365,24 @@ public class TestCacheValidityPolicy {
|
||||||
public void testNegativeAgeHeaderValueReturnsMaxAge() {
|
public void testNegativeAgeHeaderValueReturnsMaxAge() {
|
||||||
final Header[] headers = new Header[] { new BasicHeader("Age", "-100") };
|
final Header[] headers = new Header[] { new BasicHeader("Age", "-100") };
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(CacheValidityPolicy.MAX_AGE, impl.getAgeValue(entry));
|
// in seconds
|
||||||
|
assertEquals(CacheValidityPolicy.MAX_AGE.toSeconds(), impl.getAgeValue(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMalformedAgeHeaderValueReturnsMaxAge() {
|
public void testMalformedAgeHeaderValueReturnsMaxAge() {
|
||||||
final Header[] headers = new Header[] { new BasicHeader("Age", "asdf") };
|
final Header[] headers = new Header[] { new BasicHeader("Age", "asdf") };
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(CacheValidityPolicy.MAX_AGE, impl.getAgeValue(entry));
|
// in seconds
|
||||||
|
assertEquals(CacheValidityPolicy.MAX_AGE.toSeconds(), impl.getAgeValue(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMalformedCacheControlMaxAgeHeaderReturnsZero() {
|
public void testMalformedCacheControlMaxAgeHeaderReturnsZero() {
|
||||||
final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=asdf") };
|
final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=asdf") };
|
||||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||||
assertEquals(0, impl.getMaxAge(entry));
|
// in seconds
|
||||||
|
assertEquals(0L, impl.getMaxAge(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||||
import org.apache.hc.core5.http.ClassicHttpRequest;
|
import org.apache.hc.core5.http.ClassicHttpRequest;
|
||||||
import org.apache.hc.core5.http.Header;
|
import org.apache.hc.core5.http.Header;
|
||||||
import org.apache.hc.core5.http.message.BasicHeader;
|
import org.apache.hc.core5.http.message.BasicHeader;
|
||||||
|
import org.apache.hc.core5.util.TimeValue;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -108,11 +109,11 @@ public class TestCachedHttpResponseGenerator {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() throws Exception {
|
public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() throws Exception {
|
||||||
currentAge(10L);
|
currentAge(TimeValue.ofSeconds(10L));
|
||||||
|
|
||||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||||
|
|
||||||
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
|
verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Date.class));
|
||||||
|
|
||||||
final Header ageHdr = response.getFirstHeader("Age");
|
final Header ageHdr = response.getFirstHeader("Age");
|
||||||
Assert.assertNotNull(ageHdr);
|
Assert.assertNotNull(ageHdr);
|
||||||
|
@ -121,11 +122,11 @@ public class TestCachedHttpResponseGenerator {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() throws Exception {
|
public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() throws Exception {
|
||||||
currentAge(0L);
|
currentAge(TimeValue.ofSeconds(0L));
|
||||||
|
|
||||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||||
|
|
||||||
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
|
verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Date.class));
|
||||||
|
|
||||||
final Header ageHdr = response.getFirstHeader("Age");
|
final Header ageHdr = response.getFirstHeader("Age");
|
||||||
Assert.assertNull(ageHdr);
|
Assert.assertNull(ageHdr);
|
||||||
|
@ -133,21 +134,21 @@ public class TestCachedHttpResponseGenerator {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() throws Exception {
|
public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() throws Exception {
|
||||||
currentAge(CacheValidityPolicy.MAX_AGE + 1L);
|
currentAge(TimeValue.ofSeconds(CacheValidityPolicy.MAX_AGE.toSeconds() + 1L));
|
||||||
|
|
||||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||||
|
|
||||||
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
|
verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Date.class));
|
||||||
|
|
||||||
final Header ageHdr = response.getFirstHeader("Age");
|
final Header ageHdr = response.getFirstHeader("Age");
|
||||||
Assert.assertNotNull(ageHdr);
|
Assert.assertNotNull(ageHdr);
|
||||||
Assert.assertEquals(CacheValidityPolicy.MAX_AGE, Long.parseLong(ageHdr.getValue()));
|
Assert.assertEquals(CacheValidityPolicy.MAX_AGE.toSeconds(), Long.parseLong(ageHdr.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void currentAge(final long sec) {
|
private void currentAge(final TimeValue age) {
|
||||||
when(
|
when(
|
||||||
mockValidityPolicy.getCurrentAgeSecs(same(entry),
|
mockValidityPolicy.getCurrentAge(same(entry),
|
||||||
isA(Date.class))).thenReturn(sec);
|
isA(Date.class))).thenReturn(age);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -79,6 +79,7 @@ import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
|
||||||
import org.apache.hc.core5.http.message.BasicHeader;
|
import org.apache.hc.core5.http.message.BasicHeader;
|
||||||
import org.apache.hc.core5.net.URIAuthority;
|
import org.apache.hc.core5.net.URIAuthority;
|
||||||
import org.apache.hc.core5.util.ByteArrayBuffer;
|
import org.apache.hc.core5.util.ByteArrayBuffer;
|
||||||
|
import org.apache.hc.core5.util.TimeValue;
|
||||||
import org.easymock.Capture;
|
import org.easymock.Capture;
|
||||||
import org.easymock.EasyMock;
|
import org.easymock.EasyMock;
|
||||||
import org.easymock.IExpectationSetters;
|
import org.easymock.IExpectationSetters;
|
||||||
|
@ -316,7 +317,7 @@ public abstract class TestCachingExecChain {
|
||||||
cacheEntrySuitable(true);
|
cacheEntrySuitable(true);
|
||||||
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
||||||
requestIsFatallyNonCompliant(null);
|
requestIsFatallyNonCompliant(null);
|
||||||
entryHasStaleness(0L);
|
entryHasStaleness(TimeValue.ZERO_MILLISECONDS);
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
final ClassicHttpResponse result = execute(request);
|
final ClassicHttpResponse result = execute(request);
|
||||||
|
@ -353,7 +354,7 @@ public abstract class TestCachingExecChain {
|
||||||
cacheEntrySuitable(true);
|
cacheEntrySuitable(true);
|
||||||
getCacheEntryReturns(mockCacheEntry);
|
getCacheEntryReturns(mockCacheEntry);
|
||||||
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
||||||
entryHasStaleness(0L);
|
entryHasStaleness(TimeValue.ZERO_MILLISECONDS);
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
execute(request);
|
execute(request);
|
||||||
|
@ -1348,7 +1349,7 @@ public abstract class TestCachingExecChain {
|
||||||
getCacheEntryReturns(entry);
|
getCacheEntryReturns(entry);
|
||||||
cacheEntrySuitable(true);
|
cacheEntrySuitable(true);
|
||||||
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
||||||
entryHasStaleness(0);
|
entryHasStaleness(TimeValue.ZERO_MILLISECONDS);
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
final ClassicHttpResponse resp = execute(request);
|
final ClassicHttpResponse resp = execute(request);
|
||||||
|
@ -1675,9 +1676,9 @@ public abstract class TestCachingExecChain {
|
||||||
.andReturn(suitable);
|
.andReturn(suitable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void entryHasStaleness(final long staleness) {
|
private void entryHasStaleness(final TimeValue staleness) {
|
||||||
expect(
|
expect(
|
||||||
mockValidityPolicy.getStalenessSecs((HttpCacheEntry) anyObject(), (Date) anyObject()))
|
mockValidityPolicy.getStaleness((HttpCacheEntry) anyObject(), (Date) anyObject()))
|
||||||
.andReturn(staleness);
|
.andReturn(staleness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue