* Caching protocol classes to use CacheControlHeaderParser to parse request and response cache control directives
* Several protocol recommendations related to Cache-Control header composition no longer mentioned by RFC 7234 have been removed * Cleanup of header constants
This commit is contained in:
parent
3f81f21cab
commit
cd2930af1f
|
@ -27,7 +27,7 @@
|
|||
package org.apache.hc.client5.http.cache;
|
||||
|
||||
/**
|
||||
* Records static constants for various HTTP header names.
|
||||
* Records static constants for caching directives.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
|
@ -41,20 +41,75 @@ public class HeaderConstants {
|
|||
public static final String TRACE_METHOD = "TRACE";
|
||||
public static final String POST_METHOD = "POST";
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String LAST_MODIFIED = "Last-Modified";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String IF_MATCH = "If-Match";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String IF_RANGE = "If-Range";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String IF_NONE_MATCH = "If-None-Match";
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String PRAGMA = "Pragma";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String MAX_FORWARDS = "Max-Forwards";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String ETAG = "ETag";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String EXPIRES = "Expires";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String AGE = "Age";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String VARY = "Vary";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String ALLOW = "Allow";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String VIA = "Via";
|
||||
/**
|
||||
* @deprecated Use {@link #CACHE_CONTROL_PUBLIC}
|
||||
|
@ -92,11 +147,35 @@ public class HeaderConstants {
|
|||
@Deprecated
|
||||
public static final String STALE_WHILE_REVALIDATE = "stale-while-revalidate";
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String WARNING = "Warning";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String RANGE = "Range";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String CONTENT_RANGE = "Content-Range";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
|
||||
/**
|
||||
* @deprecated Use {@link org.apache.hc.core5.http.HttpHeaders}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String AUTHORIZATION = "Authorization";
|
||||
|
||||
}
|
||||
|
|
|
@ -352,7 +352,7 @@ public class HttpCacheEntry implements MessageHeaders, Serializable {
|
|||
* @return {@code true} if this cached response was a variant
|
||||
*/
|
||||
public boolean hasVariants() {
|
||||
return getFirstHeader(HeaderConstants.VARY) != null;
|
||||
return getFirstHeader(HttpHeaders.VARY) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.apache.hc.client5.http.async.AsyncExecChainHandler;
|
|||
import org.apache.hc.client5.http.async.methods.SimpleBody;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.client5.http.cache.CacheResponseStatus;
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpAsyncCacheStorage;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.cache.ResourceFactory;
|
||||
|
@ -238,7 +237,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
|
|||
}
|
||||
|
||||
requestCompliance.makeRequestCompliant(request);
|
||||
request.addHeader("Via",via);
|
||||
request.addHeader(HttpHeaders.VIA,via);
|
||||
|
||||
if (!cacheableRequestPolicy.isServableFromCache(request)) {
|
||||
LOG.debug("Request is not servable from cache");
|
||||
|
@ -318,7 +317,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
|
|||
final HttpResponse backendResponse,
|
||||
final EntityDetails entityDetails) throws HttpException, IOException {
|
||||
final Instant responseDate = getCurrentDate();
|
||||
backendResponse.addHeader("Via", generateViaHeader(backendResponse));
|
||||
backendResponse.addHeader(HttpHeaders.VIA, generateViaHeader(backendResponse));
|
||||
|
||||
final AsyncExecCallback callback = new BackendResponseHandler(target, request, requestDate, responseDate, scope, asyncExecCallback);
|
||||
callbackRef.set(callback);
|
||||
|
@ -774,7 +773,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
|
|||
void triggerResponseStaleCacheEntry() {
|
||||
try {
|
||||
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, cacheEntry);
|
||||
cacheResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
|
||||
cacheResponse.addHeader(HttpHeaders.WARNING, "110 localhost \"Response is stale\"");
|
||||
triggerResponse(cacheResponse, scope, asyncExecCallback);
|
||||
} catch (final ResourceIOException ex) {
|
||||
asyncExecCallback.failed(ex);
|
||||
|
@ -782,7 +781,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
|
|||
}
|
||||
|
||||
AsyncExecCallback evaluateResponse(final HttpResponse backendResponse, final Instant responseDate) {
|
||||
backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse));
|
||||
backendResponse.addHeader(HttpHeaders.VIA, generateViaHeader(backendResponse));
|
||||
|
||||
final int statusCode = backendResponse.getCode();
|
||||
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
|
||||
|
@ -1022,7 +1021,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
|
|||
final HttpResponse backendResponse,
|
||||
final EntityDetails entityDetails) throws HttpException, IOException {
|
||||
final Instant responseDate = getCurrentDate();
|
||||
backendResponse.addHeader("Via", generateViaHeader(backendResponse));
|
||||
backendResponse.addHeader(HttpHeaders.VIA, generateViaHeader(backendResponse));
|
||||
|
||||
final AsyncExecCallback callback;
|
||||
// Handle 304 Not Modified responses
|
||||
|
@ -1090,7 +1089,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
|
|||
if (backendResponse.getCode() != HttpStatus.SC_NOT_MODIFIED) {
|
||||
callback = new BackendResponseHandler(target, request, requestDate, responseDate, scope, asyncExecCallback);
|
||||
} else {
|
||||
final Header resultEtagHeader = backendResponse.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header resultEtagHeader = backendResponse.getFirstHeader(HttpHeaders.ETAG);
|
||||
if (resultEtagHeader == null) {
|
||||
LOG.warn("304 response did not contain ETag");
|
||||
callback = new AsyncExecCallbackWrapper(asyncExecCallback, () -> callBackend(target, request, entityProducer, scope, chain, asyncExecCallback));
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpAsyncCacheInvalidator;
|
||||
import org.apache.hc.client5.http.cache.HttpAsyncCacheStorage;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
|
@ -43,6 +42,7 @@ import org.apache.hc.core5.concurrent.Cancellable;
|
|||
import org.apache.hc.core5.concurrent.ComplexCancellable;
|
||||
import org.apache.hc.core5.concurrent.FutureCallback;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.HttpResponse;
|
||||
|
@ -540,7 +540,7 @@ class BasicHttpAsyncCache implements HttpAsyncCache {
|
|||
for (final Map.Entry<String, HttpCacheEntry> resultMapEntry : resultMap.entrySet()) {
|
||||
final String cacheKey = resultMapEntry.getKey();
|
||||
final HttpCacheEntry cacheEntry = resultMapEntry.getValue();
|
||||
final Header etagHeader = cacheEntry.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header etagHeader = cacheEntry.getFirstHeader(HttpHeaders.ETAG);
|
||||
if (etagHeader != null) {
|
||||
variants.put(etagHeader.getValue(), new Variant(cacheKey, cacheEntry));
|
||||
}
|
||||
|
|
|
@ -28,10 +28,8 @@ package org.apache.hc.client5.http.impl.cache;
|
|||
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheInvalidator;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheStorage;
|
||||
|
@ -39,13 +37,11 @@ import org.apache.hc.client5.http.cache.HttpCacheUpdateException;
|
|||
import org.apache.hc.client5.http.cache.ResourceFactory;
|
||||
import org.apache.hc.client5.http.cache.ResourceIOException;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.HttpResponse;
|
||||
import org.apache.hc.core5.http.Method;
|
||||
import org.apache.hc.core5.http.message.MessageSupport;
|
||||
import org.apache.hc.core5.http.message.RequestLine;
|
||||
import org.apache.hc.core5.http.message.StatusLine;
|
||||
import org.apache.hc.core5.util.ByteArrayBuffer;
|
||||
|
@ -326,8 +322,7 @@ class BasicHttpCache implements HttpCache {
|
|||
continue;
|
||||
}
|
||||
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(variant, HttpHeaders.DATE);
|
||||
if (!it.hasNext()) {
|
||||
if (!variant.containsHeader(HttpHeaders.DATE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -360,7 +355,7 @@ class BasicHttpCache implements HttpCache {
|
|||
try {
|
||||
final HttpCacheEntry entry = storage.getEntry(variantCacheKey);
|
||||
if (entry != null) {
|
||||
final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header etagHeader = entry.getFirstHeader(HttpHeaders.ETAG);
|
||||
if (etagHeader != null) {
|
||||
variants.put(etagHeader.getValue(), new Variant(variantCacheKey, entry));
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Set;
|
|||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.core5.annotation.Contract;
|
||||
import org.apache.hc.core5.annotation.Internal;
|
||||
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
||||
|
@ -204,6 +205,10 @@ class CacheControlHeaderParser {
|
|||
return parseResponse(response.headerIterator(HttpHeaders.CACHE_CONTROL));
|
||||
}
|
||||
|
||||
public final ResponseCacheControl parse(final HttpCacheEntry cacheEntry) {
|
||||
return parseResponse(cacheEntry.headerIterator(HttpHeaders.CACHE_CONTROL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the specified request header and returns a new {@link RequestCacheControl} instance containing
|
||||
* the relevant caching directives.
|
||||
|
|
|
@ -89,8 +89,8 @@ class CacheInvalidatorBase {
|
|||
|
||||
static boolean responseAndEntryEtagsDiffer(final HttpResponse response,
|
||||
final HttpCacheEntry entry) {
|
||||
final Header entryEtag = entry.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header responseEtag = response.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header entryEtag = entry.getFirstHeader(HttpHeaders.ETAG);
|
||||
final Header responseEtag = response.getFirstHeader(HttpHeaders.ETAG);
|
||||
if (entryEtag == null || responseEtag == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -36,13 +36,13 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.core5.annotation.Contract;
|
||||
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
||||
import org.apache.hc.core5.function.Resolver;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.message.MessageSupport;
|
||||
|
@ -137,7 +137,7 @@ public class CacheKeyGenerator implements Resolver<URI, String> {
|
|||
*/
|
||||
public String generateVariantKey(final HttpRequest req, final HttpCacheEntry entry) {
|
||||
final List<String> variantHeaderNames = new ArrayList<>();
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.VARY);
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HttpHeaders.VARY);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
variantHeaderNames.add(elt.getName());
|
||||
|
|
|
@ -37,10 +37,10 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.schedule.ConcurrentCountMap;
|
||||
import org.apache.hc.client5.http.schedule.SchedulingStrategy;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpResponse;
|
||||
import org.apache.hc.core5.util.Args;
|
||||
import org.apache.hc.core5.util.TimeValue;
|
||||
|
@ -173,7 +173,7 @@ class CacheRevalidatorBase implements Closeable {
|
|||
* @return whether the response is stale or not
|
||||
*/
|
||||
boolean isStale(final HttpResponse httpResponse) {
|
||||
for (final Iterator<Header> it = httpResponse.headerIterator(HeaderConstants.WARNING); it.hasNext(); ) {
|
||||
for (final Iterator<Header> it = httpResponse.headerIterator(HttpHeaders.WARNING); it.hasNext(); ) {
|
||||
/*
|
||||
* warn-codes
|
||||
* 110 = Response is stale
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.util.HashMap;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.cache.Resource;
|
||||
import org.apache.hc.client5.http.cache.ResourceFactory;
|
||||
|
@ -149,7 +148,7 @@ class CacheUpdateHandler {
|
|||
// remove cache entry 1xx warnings
|
||||
for (final Iterator<Header> it = headerGroup.headerIterator(); it.hasNext(); ) {
|
||||
final Header cacheHeader = it.next();
|
||||
if (HeaderConstants.WARNING.equalsIgnoreCase(cacheHeader.getName())) {
|
||||
if (HttpHeaders.WARNING.equalsIgnoreCase(cacheHeader.getName())) {
|
||||
final String warningValue = cacheHeader.getValue();
|
||||
if (warningValue != null && warningValue.startsWith("1")) {
|
||||
it.remove();
|
||||
|
|
|
@ -28,18 +28,13 @@ package org.apache.hc.client5.http.impl.cache;
|
|||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.cache.Resource;
|
||||
import org.apache.hc.client5.http.utils.DateUtils;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.MessageHeaders;
|
||||
import org.apache.hc.core5.http.message.MessageSupport;
|
||||
import org.apache.hc.core5.util.TimeValue;
|
||||
|
||||
class CacheValidityPolicy {
|
||||
|
@ -66,7 +61,7 @@ class CacheValidityPolicy {
|
|||
return TimeValue.ZERO_MILLISECONDS;
|
||||
}
|
||||
|
||||
final Instant expiry = DateUtils.parseStandardDate(entry, HeaderConstants.EXPIRES);
|
||||
final Instant expiry = DateUtils.parseStandardDate(entry, HttpHeaders.EXPIRES);
|
||||
if (expiry == null) {
|
||||
return TimeValue.ZERO_MILLISECONDS;
|
||||
}
|
||||
|
@ -100,7 +95,7 @@ class CacheValidityPolicy {
|
|||
public TimeValue getHeuristicFreshnessLifetime(final HttpCacheEntry entry,
|
||||
final float coefficient, final TimeValue defaultLifetime) {
|
||||
final Instant dateValue = entry.getInstant();
|
||||
final Instant lastModifiedValue = DateUtils.parseStandardDate(entry, HeaderConstants.LAST_MODIFIED);
|
||||
final Instant lastModifiedValue = DateUtils.parseStandardDate(entry, HttpHeaders.LAST_MODIFIED);
|
||||
|
||||
if (dateValue != null && lastModifiedValue != null) {
|
||||
final Duration diff = Duration.between(lastModifiedValue, dateValue);
|
||||
|
@ -115,63 +110,40 @@ class CacheValidityPolicy {
|
|||
}
|
||||
|
||||
public boolean isRevalidatable(final HttpCacheEntry entry) {
|
||||
return entry.getFirstHeader(HeaderConstants.ETAG) != null
|
||||
|| entry.getFirstHeader(HeaderConstants.LAST_MODIFIED) != null;
|
||||
return entry.getFirstHeader(HttpHeaders.ETAG) != null
|
||||
|| entry.getFirstHeader(HttpHeaders.LAST_MODIFIED) != null;
|
||||
}
|
||||
|
||||
public boolean mustRevalidate(final HttpCacheEntry entry) {
|
||||
return hasCacheControlDirective(entry, HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE);
|
||||
final ResponseCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(entry);
|
||||
return cacheControl.isMustRevalidate();
|
||||
}
|
||||
|
||||
public boolean proxyRevalidate(final HttpCacheEntry entry) {
|
||||
return hasCacheControlDirective(entry, HeaderConstants.CACHE_CONTROL_PROXY_REVALIDATE);
|
||||
final ResponseCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(entry);
|
||||
return cacheControl.isProxyRevalidate();
|
||||
}
|
||||
|
||||
public boolean mayReturnStaleWhileRevalidating(final HttpCacheEntry entry, final Instant now) {
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) {
|
||||
try {
|
||||
// in seconds
|
||||
final int allowedStalenessLifetime = Integer.parseInt(elt.getValue());
|
||||
if (getStaleness(entry, now).compareTo(TimeValue.ofSeconds(allowedStalenessLifetime)) <= 0) {
|
||||
return true;
|
||||
}
|
||||
} catch (final NumberFormatException nfe) {
|
||||
// skip malformed directive
|
||||
}
|
||||
final ResponseCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(entry);
|
||||
if (cacheControl.getStaleWhileRevalidate() >= 0) {
|
||||
final TimeValue staleness = getStaleness(entry, now);
|
||||
if (staleness.compareTo(TimeValue.ofSeconds(cacheControl.getStaleWhileRevalidate())) <= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean mayReturnStaleIfError(final HttpRequest request, final HttpCacheEntry entry, final Instant now) {
|
||||
final RequestCacheControl requestCacheControl = CacheControlHeaderParser.INSTANCE.parse(request);
|
||||
final ResponseCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(entry);
|
||||
final TimeValue staleness = getStaleness(entry, now);
|
||||
return mayReturnStaleIfError(request, HeaderConstants.CACHE_CONTROL, staleness)
|
||||
|| mayReturnStaleIfError(entry, HeaderConstants.CACHE_CONTROL, staleness);
|
||||
return mayReturnStaleIfError(requestCacheControl, staleness) || mayReturnStaleIfError(cacheControl, staleness);
|
||||
}
|
||||
|
||||
private boolean mayReturnStaleIfError(final MessageHeaders headers, final String name, final TimeValue staleness) {
|
||||
boolean result = false;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(headers, name);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) {
|
||||
try {
|
||||
// in seconds
|
||||
final int staleIfError = Integer.parseInt(elt.getValue());
|
||||
if (staleness.compareTo(TimeValue.ofSeconds(staleIfError)) <= 0) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
} catch (final NumberFormatException nfe) {
|
||||
// skip malformed directive
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
private boolean mayReturnStaleIfError(final CacheControl cacheControl, final TimeValue staleness) {
|
||||
return cacheControl.getStaleIfError() >= 0 && staleness.compareTo(TimeValue.ofSeconds(cacheControl.getStaleIfError())) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -214,7 +186,7 @@ class CacheValidityPolicy {
|
|||
protected long getAgeValue(final HttpCacheEntry entry) {
|
||||
// This is a header value, we leave as-is
|
||||
long ageValue = 0;
|
||||
for (final Header hdr : entry.getHeaders(HeaderConstants.AGE)) {
|
||||
for (final Header hdr : entry.getHeaders(HttpHeaders.AGE)) {
|
||||
long hdrAge;
|
||||
try {
|
||||
hdrAge = Long.parseLong(hdr.getValue());
|
||||
|
@ -251,35 +223,16 @@ class CacheValidityPolicy {
|
|||
|
||||
|
||||
protected long getMaxAge(final HttpCacheEntry entry) {
|
||||
// This is a header value, we leave as-is
|
||||
long maxAge = -1;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName()) || "s-maxage".equals(elt.getName())) {
|
||||
try {
|
||||
final long currMaxAge = Long.parseLong(elt.getValue());
|
||||
if (maxAge == -1 || currMaxAge < maxAge) {
|
||||
maxAge = currMaxAge;
|
||||
}
|
||||
} catch (final NumberFormatException nfe) {
|
||||
// be conservative if can't parse
|
||||
maxAge = 0;
|
||||
}
|
||||
}
|
||||
final ResponseCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(entry);
|
||||
final long maxAge = cacheControl.getMaxAge();
|
||||
final long sharedMaxAge = cacheControl.getSharedMaxAge();
|
||||
if (sharedMaxAge == -1) {
|
||||
return maxAge;
|
||||
} else if (maxAge == -1) {
|
||||
return sharedMaxAge;
|
||||
} else {
|
||||
return Math.min(maxAge, sharedMaxAge);
|
||||
}
|
||||
return maxAge;
|
||||
}
|
||||
|
||||
public boolean hasCacheControlDirective(final HttpCacheEntry entry, final String directive) {
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (directive.equalsIgnoreCase(elt.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public TimeValue getStaleness(final HttpCacheEntry entry, final Instant now) {
|
||||
|
|
|
@ -26,14 +26,11 @@
|
|||
*/
|
||||
package org.apache.hc.client5.http.impl.cache;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.HttpVersion;
|
||||
import org.apache.hc.core5.http.ProtocolVersion;
|
||||
import org.apache.hc.core5.http.message.MessageSupport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -67,24 +64,20 @@ class CacheableRequestPolicy {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (request.countHeaders(HeaderConstants.PRAGMA) > 0) {
|
||||
if (request.countHeaders(HttpHeaders.PRAGMA) > 0) {
|
||||
LOG.debug("request with Pragma header is not serveable from cache");
|
||||
return false;
|
||||
}
|
||||
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement cacheControlElement = it.next();
|
||||
if (HeaderConstants.CACHE_CONTROL_NO_STORE.equalsIgnoreCase(cacheControlElement.getName())) {
|
||||
LOG.debug("Request with no-store is not serveable from cache");
|
||||
return false;
|
||||
}
|
||||
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(cacheControlElement.getName())) {
|
||||
LOG.debug("Request with no-cache is not serveable from cache");
|
||||
return false;
|
||||
}
|
||||
final RequestCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(request);
|
||||
if (cacheControl.isNoStore()) {
|
||||
LOG.debug("Request with no-store is not serveable from cache");
|
||||
return false;
|
||||
}
|
||||
if (cacheControl.isNoCache()) {
|
||||
LOG.debug("Request with no-cache is not serveable from cache");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG.debug("Request is serveable from cache");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -82,9 +82,9 @@ class CachedHttpResponseGenerator {
|
|||
final TimeValue age = this.validityStrategy.getCurrentAge(entry, now);
|
||||
if (TimeValue.isPositive(age)) {
|
||||
if (age.compareTo(CacheValidityPolicy.MAX_AGE) >= 0) {
|
||||
response.setHeader(HeaderConstants.AGE, "" + CacheValidityPolicy.MAX_AGE.toSeconds());
|
||||
response.setHeader(HttpHeaders.AGE, Long.toString(CacheValidityPolicy.MAX_AGE.toSeconds()));
|
||||
} else {
|
||||
response.setHeader(HeaderConstants.AGE, "" + age.toSeconds());
|
||||
response.setHeader(HttpHeaders.AGE, Long.toString(age.toSeconds()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ class CachedHttpResponseGenerator {
|
|||
|
||||
// - ETag and/or Content-Location, if the header would have been sent
|
||||
// in a 200 response to the same request
|
||||
final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header etagHeader = entry.getFirstHeader(HttpHeaders.ETAG);
|
||||
if (etagHeader != null) {
|
||||
response.addHeader(etagHeader);
|
||||
}
|
||||
|
@ -124,17 +124,17 @@ class CachedHttpResponseGenerator {
|
|||
// - Expires, Cache-Control, and/or Vary, if the field-value might
|
||||
// differ from that sent in any previous response for the same
|
||||
// variant
|
||||
final Header expiresHeader = entry.getFirstHeader(HeaderConstants.EXPIRES);
|
||||
final Header expiresHeader = entry.getFirstHeader(HttpHeaders.EXPIRES);
|
||||
if (expiresHeader != null) {
|
||||
response.addHeader(expiresHeader);
|
||||
}
|
||||
|
||||
final Header cacheControlHeader = entry.getFirstHeader(HeaderConstants.CACHE_CONTROL);
|
||||
final Header cacheControlHeader = entry.getFirstHeader(HttpHeaders.CACHE_CONTROL);
|
||||
if (cacheControlHeader != null) {
|
||||
response.addHeader(cacheControlHeader);
|
||||
}
|
||||
|
||||
final Header varyHeader = entry.getFirstHeader(HeaderConstants.VARY);
|
||||
final Header varyHeader = entry.getFirstHeader(HttpHeaders.VARY);
|
||||
if (varyHeader != null) {
|
||||
response.addHeader(varyHeader);
|
||||
}
|
||||
|
@ -192,10 +192,6 @@ class CachedHttpResponseGenerator {
|
|||
return SimpleHttpResponse.create(HttpStatus.SC_BAD_REQUEST,
|
||||
"Weak eTag not compatible with PUT or DELETE requests");
|
||||
|
||||
case NO_CACHE_DIRECTIVE_WITH_FIELD_NAME:
|
||||
return SimpleHttpResponse.create(HttpStatus.SC_BAD_REQUEST,
|
||||
"No-Cache directive MUST NOT include a field name");
|
||||
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"The request was compliant, therefore no error can be generated for it.");
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
|||
import org.apache.hc.client5.http.utils.DateUtils;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.apache.hc.core5.http.message.MessageSupport;
|
||||
|
@ -80,11 +81,11 @@ class CachedResponseSuitabilityChecker {
|
|||
if (originInsistsOnFreshness(entry)) {
|
||||
return false;
|
||||
}
|
||||
final long maxStale = getMaxStale(request);
|
||||
if (maxStale == -1) {
|
||||
final RequestCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(request);
|
||||
if (cacheControl.getMaxStale() == -1) {
|
||||
return false;
|
||||
}
|
||||
return (maxStale > validityStrategy.getStaleness(entry, now).toSeconds());
|
||||
return (cacheControl.getMaxStale() > validityStrategy.getStaleness(entry, now).toSeconds());
|
||||
}
|
||||
|
||||
private boolean originInsistsOnFreshness(final HttpCacheEntry entry) {
|
||||
|
@ -94,36 +95,8 @@ class CachedResponseSuitabilityChecker {
|
|||
if (!sharedCache) {
|
||||
return false;
|
||||
}
|
||||
return validityStrategy.proxyRevalidate(entry) ||
|
||||
validityStrategy.hasCacheControlDirective(entry, "s-maxage");
|
||||
}
|
||||
|
||||
private long getMaxStale(final HttpRequest request) {
|
||||
// This is a header value, we leave as-is
|
||||
long maxStale = -1;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
|
||||
if ((elt.getValue() == null || elt.getValue().trim().isEmpty()) && maxStale == -1) {
|
||||
maxStale = Long.MAX_VALUE;
|
||||
} else {
|
||||
try {
|
||||
long val = Long.parseLong(elt.getValue());
|
||||
if (val < 0) {
|
||||
val = 0;
|
||||
}
|
||||
if (maxStale == -1 || val < maxStale) {
|
||||
maxStale = val;
|
||||
}
|
||||
} catch (final NumberFormatException nfe) {
|
||||
// err on the side of preserving semantic transparency
|
||||
maxStale = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxStale;
|
||||
final ResponseCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(entry);
|
||||
return cacheControl.isProxyRevalidate() || cacheControl.getSharedMaxAge() >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,68 +149,41 @@ class CachedResponseSuitabilityChecker {
|
|||
"request method, entity or a 204 response");
|
||||
return false;
|
||||
}
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) {
|
||||
LOG.debug("Response contained NO CACHE directive, cache was not suitable");
|
||||
final RequestCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(request);
|
||||
if (cacheControl.isNoCache()) {
|
||||
LOG.debug("Response contained NO CACHE directive, cache was not suitable");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cacheControl.isNoStore()) {
|
||||
LOG.debug("Response contained NO STORE directive, cache was not suitable");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cacheControl.getMaxAge() >= 0) {
|
||||
if (validityStrategy.getCurrentAge(entry, now).toSeconds() > cacheControl.getMaxAge()) {
|
||||
LOG.debug("Response from cache was not suitable due to max age");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elt.getName())) {
|
||||
LOG.debug("Response contained NO STORE directive, cache was not suitable");
|
||||
if (cacheControl.getMaxStale() >= 0) {
|
||||
if (validityStrategy.getFreshnessLifetime(entry).toSeconds() > cacheControl.getMaxStale()) {
|
||||
LOG.debug("Response from cache was not suitable due to max stale freshness");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
|
||||
try {
|
||||
// in seconds
|
||||
final int maxAge = Integer.parseInt(elt.getValue());
|
||||
if (validityStrategy.getCurrentAge(entry, now).toSeconds() > maxAge) {
|
||||
LOG.debug("Response from cache was not suitable due to max age");
|
||||
return false;
|
||||
}
|
||||
} catch (final NumberFormatException ex) {
|
||||
// err conservatively
|
||||
LOG.debug("Response from cache was malformed: {}", ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
if (cacheControl.getMinFresh() >= 0) {
|
||||
if (cacheControl.getMinFresh() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
|
||||
try {
|
||||
// in seconds
|
||||
final int maxStale = Integer.parseInt(elt.getValue());
|
||||
if (validityStrategy.getFreshnessLifetime(entry).toSeconds() > maxStale) {
|
||||
LOG.debug("Response from cache was not suitable due to max stale freshness");
|
||||
return false;
|
||||
}
|
||||
} catch (final NumberFormatException ex) {
|
||||
// err conservatively
|
||||
LOG.debug("Response from cache was malformed: {}", ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
|
||||
try {
|
||||
// in seconds
|
||||
final long minFresh = Long.parseLong(elt.getValue());
|
||||
if (minFresh < 0L) {
|
||||
return false;
|
||||
}
|
||||
final TimeValue age = validityStrategy.getCurrentAge(entry, now);
|
||||
final TimeValue freshness = validityStrategy.getFreshnessLifetime(entry);
|
||||
if (freshness.toSeconds() - age.toSeconds() < minFresh) {
|
||||
LOG.debug("Response from cache was not suitable due to min fresh " +
|
||||
"freshness requirement");
|
||||
return false;
|
||||
}
|
||||
} catch (final NumberFormatException ex) {
|
||||
// err conservatively
|
||||
LOG.debug("Response from cache was malformed: {}", ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
final TimeValue age = validityStrategy.getCurrentAge(entry, now);
|
||||
final TimeValue freshness = validityStrategy.getFreshnessLifetime(entry);
|
||||
if (freshness.toSeconds() - age.toSeconds() < cacheControl.getMinFresh()) {
|
||||
LOG.debug("Response from cache was not suitable due to min fresh " +
|
||||
"freshness requirement");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,17 +256,17 @@ class CachedResponseSuitabilityChecker {
|
|||
}
|
||||
|
||||
private boolean hasUnsupportedConditionalHeaders(final HttpRequest request) {
|
||||
return (request.getFirstHeader(HeaderConstants.IF_RANGE) != null
|
||||
|| request.getFirstHeader(HeaderConstants.IF_MATCH) != null
|
||||
|| hasValidDateField(request, HeaderConstants.IF_UNMODIFIED_SINCE));
|
||||
return (request.getFirstHeader(HttpHeaders.IF_RANGE) != null
|
||||
|| request.getFirstHeader(HttpHeaders.IF_MATCH) != null
|
||||
|| hasValidDateField(request, HttpHeaders.IF_UNMODIFIED_SINCE));
|
||||
}
|
||||
|
||||
private boolean hasSupportedEtagValidator(final HttpRequest request) {
|
||||
return request.containsHeader(HeaderConstants.IF_NONE_MATCH);
|
||||
return request.containsHeader(HttpHeaders.IF_NONE_MATCH);
|
||||
}
|
||||
|
||||
private boolean hasSupportedLastModifiedValidator(final HttpRequest request) {
|
||||
return hasValidDateField(request, HeaderConstants.IF_MODIFIED_SINCE);
|
||||
return hasValidDateField(request, HttpHeaders.IF_MODIFIED_SINCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -330,9 +276,9 @@ class CachedResponseSuitabilityChecker {
|
|||
* @return boolean does the etag validator match
|
||||
*/
|
||||
private boolean etagValidatorMatches(final HttpRequest request, final HttpCacheEntry entry) {
|
||||
final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header etagHeader = entry.getFirstHeader(HttpHeaders.ETAG);
|
||||
final String etag = (etagHeader != null) ? etagHeader.getValue() : null;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.IF_NONE_MATCH);
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HttpHeaders.IF_NONE_MATCH);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
final String reqEtag = elt.toString();
|
||||
|
@ -344,20 +290,19 @@ class CachedResponseSuitabilityChecker {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check entry against If-Modified-Since, if If-Modified-Since is in the future it is invalid as per
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
||||
* Check entry against If-Modified-Since, if If-Modified-Since is in the future it is invalid
|
||||
* @param request The current httpRequest being made
|
||||
* @param entry the cache entry
|
||||
* @param now right NOW in time
|
||||
* @return boolean Does the last modified header match
|
||||
*/
|
||||
private boolean lastModifiedValidatorMatches(final HttpRequest request, final HttpCacheEntry entry, final Instant now) {
|
||||
final Instant lastModified = DateUtils.parseStandardDate(entry, HeaderConstants.LAST_MODIFIED);
|
||||
final Instant lastModified = DateUtils.parseStandardDate(entry, HttpHeaders.LAST_MODIFIED);
|
||||
if (lastModified == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (final Header h : request.getHeaders(HeaderConstants.IF_MODIFIED_SINCE)) {
|
||||
for (final Header h : request.getHeaders(HttpHeaders.IF_MODIFIED_SINCE)) {
|
||||
final Instant ifModifiedSince = DateUtils.parseStandardDate(h.getValue());
|
||||
if (ifModifiedSince != null) {
|
||||
if (ifModifiedSince.isAfter(now) || lastModified.isAfter(ifModifiedSince)) {
|
||||
|
|
|
@ -37,7 +37,6 @@ import org.apache.hc.client5.http.HttpRoute;
|
|||
import org.apache.hc.client5.http.async.methods.SimpleBody;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.client5.http.cache.CacheResponseStatus;
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheStorage;
|
||||
import org.apache.hc.client5.http.cache.ResourceFactory;
|
||||
|
@ -216,7 +215,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
|
|||
}
|
||||
|
||||
requestCompliance.makeRequestCompliant(request);
|
||||
request.addHeader("Via",via);
|
||||
request.addHeader(HttpHeaders.VIA, via);
|
||||
|
||||
if (!cacheableRequestPolicy.isServableFromCache(request)) {
|
||||
LOG.debug("Request is not servable from cache");
|
||||
|
@ -268,7 +267,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
|
|||
LOG.debug("Calling the backend");
|
||||
final ClassicHttpResponse backendResponse = chain.proceed(request, scope);
|
||||
try {
|
||||
backendResponse.addHeader("Via", generateViaHeader(backendResponse));
|
||||
backendResponse.addHeader(HttpHeaders.VIA, generateViaHeader(backendResponse));
|
||||
return handleBackendResponse(target, request, scope, requestDate, getCurrentDate(), backendResponse);
|
||||
} catch (final IOException | RuntimeException ex) {
|
||||
backendResponse.close();
|
||||
|
@ -377,7 +376,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
|
|||
responseDate = getCurrentDate();
|
||||
}
|
||||
|
||||
backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse));
|
||||
backendResponse.addHeader(HttpHeaders.VIA, generateViaHeader(backendResponse));
|
||||
|
||||
final int statusCode = backendResponse.getCode();
|
||||
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
|
||||
|
@ -399,7 +398,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
|
|||
&& validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
|
||||
try {
|
||||
final SimpleHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry);
|
||||
cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
|
||||
cachedResponse.addHeader(HttpHeaders.WARNING, "110 localhost \"Response is stale\"");
|
||||
return convert(cachedResponse, scope);
|
||||
} finally {
|
||||
backendResponse.close();
|
||||
|
@ -528,13 +527,13 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
|
|||
try {
|
||||
final Instant responseDate = getCurrentDate();
|
||||
|
||||
backendResponse.addHeader("Via", generateViaHeader(backendResponse));
|
||||
backendResponse.addHeader(HttpHeaders.VIA, generateViaHeader(backendResponse));
|
||||
|
||||
if (backendResponse.getCode() != HttpStatus.SC_NOT_MODIFIED) {
|
||||
return handleBackendResponse(target, request, scope, requestDate, responseDate, backendResponse);
|
||||
}
|
||||
|
||||
final Header resultEtagHeader = backendResponse.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header resultEtagHeader = backendResponse.getFirstHeader(HttpHeaders.ETAG);
|
||||
if (resultEtagHeader == null) {
|
||||
LOG.warn("304 response did not contain ETag");
|
||||
EntityUtils.consume(backendResponse.getEntity());
|
||||
|
|
|
@ -42,7 +42,6 @@ import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
|||
import org.apache.hc.client5.http.cache.ResourceIOException;
|
||||
import org.apache.hc.client5.http.utils.DateUtils;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.HttpMessage;
|
||||
|
@ -52,7 +51,6 @@ import org.apache.hc.core5.http.HttpStatus;
|
|||
import org.apache.hc.core5.http.HttpVersion;
|
||||
import org.apache.hc.core5.http.ProtocolVersion;
|
||||
import org.apache.hc.core5.http.URIScheme;
|
||||
import org.apache.hc.core5.http.message.MessageSupport;
|
||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||
import org.apache.hc.core5.util.TimeValue;
|
||||
import org.apache.hc.core5.util.VersionInfo;
|
||||
|
@ -191,26 +189,26 @@ public class CachingExecBase {
|
|||
final HttpCacheEntry entry,
|
||||
final Instant now) throws ResourceIOException {
|
||||
final SimpleHttpResponse cachedResponse;
|
||||
if (request.containsHeader(HeaderConstants.IF_NONE_MATCH)
|
||||
|| request.containsHeader(HeaderConstants.IF_MODIFIED_SINCE)) {
|
||||
if (request.containsHeader(HttpHeaders.IF_NONE_MATCH)
|
||||
|| request.containsHeader(HttpHeaders.IF_MODIFIED_SINCE)) {
|
||||
cachedResponse = responseGenerator.generateNotModifiedResponse(entry);
|
||||
} else {
|
||||
cachedResponse = responseGenerator.generateResponse(request, entry);
|
||||
}
|
||||
setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
|
||||
if (TimeValue.isPositive(validityPolicy.getStaleness(entry, now))) {
|
||||
cachedResponse.addHeader(HeaderConstants.WARNING,"110 localhost \"Response is stale\"");
|
||||
cachedResponse.addHeader(HttpHeaders.WARNING,"110 localhost \"Response is stale\"");
|
||||
}
|
||||
|
||||
// Adding Warning: 113 - "Heuristic Expiration"
|
||||
if (!entry.containsHeader(HeaderConstants.WARNING)) {
|
||||
if (!entry.containsHeader(HttpHeaders.WARNING)) {
|
||||
final Header header = entry.getFirstHeader(HttpHeaders.DATE);
|
||||
if (header != null) {
|
||||
final Instant responseDate = DateUtils.parseStandardDate(header.getValue());
|
||||
final TimeValue freshnessLifetime = validityPolicy.getFreshnessLifetime(entry);
|
||||
final TimeValue currentAge = validityPolicy.getCurrentAge(entry, responseDate);
|
||||
if (freshnessLifetime.compareTo(ONE_DAY) > 0 && currentAge.compareTo(ONE_DAY) > 0) {
|
||||
cachedResponse.addHeader(HeaderConstants.WARNING,"113 localhost \"Heuristic expiration\"");
|
||||
cachedResponse.addHeader(HttpHeaders.WARNING,"113 localhost \"Heuristic expiration\"");
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Added Warning 113 - Heuristic expiration to the response header.");
|
||||
}
|
||||
|
@ -245,7 +243,7 @@ public class CachingExecBase {
|
|||
final HttpCacheEntry entry) throws IOException {
|
||||
final SimpleHttpResponse cachedResponse = responseGenerator.generateResponse(request, entry);
|
||||
setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
|
||||
cachedResponse.addHeader(HeaderConstants.WARNING, "111 localhost \"Revalidation failed\"");
|
||||
cachedResponse.addHeader(HttpHeaders.WARNING, "111 localhost \"Revalidation failed\"");
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
|
@ -256,37 +254,24 @@ public class CachingExecBase {
|
|||
}
|
||||
|
||||
boolean mayCallBackend(final HttpRequest request) {
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if ("only-if-cached".equals(elt.getName())) {
|
||||
LOG.debug("Request marked only-if-cached");
|
||||
return false;
|
||||
}
|
||||
final RequestCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(request);
|
||||
if (cacheControl.isOnlyIfCached()) {
|
||||
LOG.debug("Request marked only-if-cached");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean explicitFreshnessRequest(final HttpRequest request, final HttpCacheEntry entry, final Instant now) {
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
|
||||
try {
|
||||
// in seconds
|
||||
final int maxStale = Integer.parseInt(elt.getValue());
|
||||
final TimeValue age = validityPolicy.getCurrentAge(entry, now);
|
||||
final TimeValue lifetime = validityPolicy.getFreshnessLifetime(entry);
|
||||
if (age.toSeconds() - lifetime.toSeconds() > maxStale) {
|
||||
return true;
|
||||
}
|
||||
} catch (final NumberFormatException nfe) {
|
||||
return true;
|
||||
}
|
||||
} else if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())
|
||||
|| HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
|
||||
final RequestCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(request);
|
||||
if (cacheControl.getMaxStale() >= 0) {
|
||||
final TimeValue age = validityPolicy.getCurrentAge(entry, now);
|
||||
final TimeValue lifetime = validityPolicy.getFreshnessLifetime(entry);
|
||||
if (age.toSeconds() - lifetime.toSeconds() > cacheControl.getMaxStale()) {
|
||||
return true;
|
||||
}
|
||||
} else if (cacheControl.getMinFresh() >= 0 || cacheControl.getMaxAge() >= 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -349,7 +334,7 @@ public class CachingExecBase {
|
|||
return false;
|
||||
}
|
||||
|
||||
final Header h = request.getFirstHeader(HeaderConstants.MAX_FORWARDS);
|
||||
final Header h = request.getFirstHeader(HttpHeaders.MAX_FORWARDS);
|
||||
return "0".equals(h != null ? h.getValue() : null);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,16 +26,14 @@
|
|||
*/
|
||||
package org.apache.hc.client5.http.impl.cache;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.core5.function.Factory;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.message.MessageSupport;
|
||||
|
||||
class ConditionalRequestBuilder<T extends HttpRequest> {
|
||||
|
||||
|
@ -58,26 +56,17 @@ class ConditionalRequestBuilder<T extends HttpRequest> {
|
|||
public T buildConditionalRequest(final T request, final HttpCacheEntry cacheEntry) {
|
||||
final T newRequest = messageCopier.create(request);
|
||||
|
||||
final Header eTag = cacheEntry.getFirstHeader(HeaderConstants.ETAG);
|
||||
final Header eTag = cacheEntry.getFirstHeader(HttpHeaders.ETAG);
|
||||
if (eTag != null) {
|
||||
newRequest.setHeader(HeaderConstants.IF_NONE_MATCH, eTag.getValue());
|
||||
newRequest.setHeader(HttpHeaders.IF_NONE_MATCH, eTag.getValue());
|
||||
}
|
||||
final Header lastModified = cacheEntry.getFirstHeader(HeaderConstants.LAST_MODIFIED);
|
||||
final Header lastModified = cacheEntry.getFirstHeader(HttpHeaders.LAST_MODIFIED);
|
||||
if (lastModified != null) {
|
||||
newRequest.setHeader(HeaderConstants.IF_MODIFIED_SINCE, lastModified.getValue());
|
||||
newRequest.setHeader(HttpHeaders.IF_MODIFIED_SINCE, lastModified.getValue());
|
||||
}
|
||||
boolean mustRevalidate = false;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(cacheEntry, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE.equalsIgnoreCase(elt.getName())
|
||||
|| HeaderConstants.CACHE_CONTROL_PROXY_REVALIDATE.equalsIgnoreCase(elt.getName())) {
|
||||
mustRevalidate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mustRevalidate) {
|
||||
newRequest.addHeader(HeaderConstants.CACHE_CONTROL, HeaderConstants.CACHE_CONTROL_MAX_AGE + "=0");
|
||||
final ResponseCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(cacheEntry);
|
||||
if (cacheControl.isMustRevalidate() || cacheControl.isProxyRevalidate()) {
|
||||
newRequest.addHeader(HttpHeaders.CACHE_CONTROL, HeaderConstants.CACHE_CONTROL_MAX_AGE + "=0");
|
||||
}
|
||||
return newRequest;
|
||||
|
||||
|
@ -108,7 +97,7 @@ class ConditionalRequestBuilder<T extends HttpRequest> {
|
|||
etags.append(etag);
|
||||
}
|
||||
|
||||
newRequest.setHeader(HeaderConstants.IF_NONE_MATCH, etags.toString());
|
||||
newRequest.setHeader(HttpHeaders.IF_NONE_MATCH, etags.toString());
|
||||
return newRequest;
|
||||
}
|
||||
|
||||
|
@ -124,13 +113,13 @@ class ConditionalRequestBuilder<T extends HttpRequest> {
|
|||
*/
|
||||
public T buildUnconditionalRequest(final T request) {
|
||||
final T newRequest = messageCopier.create(request);
|
||||
newRequest.addHeader(HeaderConstants.CACHE_CONTROL,HeaderConstants.CACHE_CONTROL_NO_CACHE);
|
||||
newRequest.addHeader(HeaderConstants.PRAGMA,HeaderConstants.CACHE_CONTROL_NO_CACHE);
|
||||
newRequest.removeHeaders(HeaderConstants.IF_RANGE);
|
||||
newRequest.removeHeaders(HeaderConstants.IF_MATCH);
|
||||
newRequest.removeHeaders(HeaderConstants.IF_NONE_MATCH);
|
||||
newRequest.removeHeaders(HeaderConstants.IF_UNMODIFIED_SINCE);
|
||||
newRequest.removeHeaders(HeaderConstants.IF_MODIFIED_SINCE);
|
||||
newRequest.addHeader(HttpHeaders.CACHE_CONTROL,HeaderConstants.CACHE_CONTROL_NO_CACHE);
|
||||
newRequest.addHeader(HttpHeaders.PRAGMA,HeaderConstants.CACHE_CONTROL_NO_CACHE);
|
||||
newRequest.removeHeaders(HttpHeaders.IF_RANGE);
|
||||
newRequest.removeHeaders(HttpHeaders.IF_MATCH);
|
||||
newRequest.removeHeaders(HttpHeaders.IF_NONE_MATCH);
|
||||
newRequest.removeHeaders(HttpHeaders.IF_UNMODIFIED_SINCE);
|
||||
newRequest.removeHeaders(HttpHeaders.IF_MODIFIED_SINCE);
|
||||
return newRequest;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,17 +27,14 @@
|
|||
package org.apache.hc.client5.http.impl.cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.HttpVersion;
|
||||
import org.apache.hc.core5.http.ProtocolVersion;
|
||||
import org.apache.hc.core5.http.message.MessageSupport;
|
||||
|
||||
class RequestProtocolCompliance {
|
||||
private final boolean weakETagOnPutDeleteAllowed;
|
||||
|
@ -52,9 +49,6 @@ class RequestProtocolCompliance {
|
|||
this.weakETagOnPutDeleteAllowed = weakETagOnPutDeleteAllowed;
|
||||
}
|
||||
|
||||
private static final List<String> disallowedWithNoCache =
|
||||
Arrays.asList(HeaderConstants.CACHE_CONTROL_MIN_FRESH, HeaderConstants.CACHE_CONTROL_MAX_STALE, HeaderConstants.CACHE_CONTROL_MAX_AGE);
|
||||
|
||||
/**
|
||||
* Test to see if the {@link HttpRequest} is HTTP1.1 compliant or not
|
||||
* and if not, we can not continue.
|
||||
|
@ -77,11 +71,6 @@ class RequestProtocolCompliance {
|
|||
}
|
||||
}
|
||||
|
||||
anError = requestContainsNoCacheDirectiveWithFieldName(request);
|
||||
if (anError != null) {
|
||||
theErrors.add(anError);
|
||||
}
|
||||
|
||||
return theErrors;
|
||||
}
|
||||
|
||||
|
@ -93,61 +82,26 @@ class RequestProtocolCompliance {
|
|||
*/
|
||||
public void makeRequestCompliant(final HttpRequest request) {
|
||||
decrementOPTIONSMaxForwardsIfGreaterThen0(request);
|
||||
stripOtherFreshnessDirectivesWithNoCache(request);
|
||||
|
||||
if (requestVersionIsTooLow(request) || requestMinorVersionIsTooHighMajorVersionsMatch(request)) {
|
||||
request.setVersion(HttpVersion.HTTP_1_1);
|
||||
}
|
||||
}
|
||||
|
||||
private void stripOtherFreshnessDirectivesWithNoCache(final HttpRequest request) {
|
||||
final List<HeaderElement> outElts = new ArrayList<>();
|
||||
boolean shouldStrip = false;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (!disallowedWithNoCache.contains(elt.getName())) {
|
||||
outElts.add(elt);
|
||||
}
|
||||
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) {
|
||||
shouldStrip = true;
|
||||
}
|
||||
}
|
||||
if (!shouldStrip) {
|
||||
return;
|
||||
}
|
||||
request.removeHeaders(HeaderConstants.CACHE_CONTROL);
|
||||
request.setHeader(HeaderConstants.CACHE_CONTROL, buildHeaderFromElements(outElts));
|
||||
}
|
||||
|
||||
private String buildHeaderFromElements(final List<HeaderElement> outElts) {
|
||||
final StringBuilder newHdr = new StringBuilder();
|
||||
boolean first = true;
|
||||
for(final HeaderElement elt : outElts) {
|
||||
if (!first) {
|
||||
newHdr.append(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
newHdr.append(elt);
|
||||
}
|
||||
return newHdr.toString();
|
||||
}
|
||||
|
||||
private void decrementOPTIONSMaxForwardsIfGreaterThen0(final HttpRequest request) {
|
||||
if (!HeaderConstants.OPTIONS_METHOD.equals(request.getMethod())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Header maxForwards = request.getFirstHeader(HeaderConstants.MAX_FORWARDS);
|
||||
final Header maxForwards = request.getFirstHeader(HttpHeaders.MAX_FORWARDS);
|
||||
if (maxForwards == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
request.removeHeaders(HeaderConstants.MAX_FORWARDS);
|
||||
request.removeHeaders(HttpHeaders.MAX_FORWARDS);
|
||||
final int currentMaxForwards = Integer.parseInt(maxForwards.getValue());
|
||||
|
||||
request.setHeader(HeaderConstants.MAX_FORWARDS, Integer.toString(currentMaxForwards - 1));
|
||||
request.setHeader(HttpHeaders.MAX_FORWARDS, Integer.toString(currentMaxForwards - 1));
|
||||
}
|
||||
|
||||
protected boolean requestMinorVersionIsTooHighMajorVersionsMatch(final HttpRequest request) {
|
||||
|
@ -174,12 +128,12 @@ class RequestProtocolCompliance {
|
|||
return null;
|
||||
}
|
||||
|
||||
final Header range = request.getFirstHeader(HeaderConstants.RANGE);
|
||||
final Header range = request.getFirstHeader(HttpHeaders.RANGE);
|
||||
if (range == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Header ifRange = request.getFirstHeader(HeaderConstants.IF_RANGE);
|
||||
final Header ifRange = request.getFirstHeader(HttpHeaders.IF_RANGE);
|
||||
if (ifRange == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -200,14 +154,14 @@ class RequestProtocolCompliance {
|
|||
return null;
|
||||
}
|
||||
|
||||
final Header ifMatch = request.getFirstHeader(HeaderConstants.IF_MATCH);
|
||||
final Header ifMatch = request.getFirstHeader(HttpHeaders.IF_MATCH);
|
||||
if (ifMatch != null) {
|
||||
final String val = ifMatch.getValue();
|
||||
if (val.startsWith("W/")) {
|
||||
return RequestProtocolError.WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR;
|
||||
}
|
||||
} else {
|
||||
final Header ifNoneMatch = request.getFirstHeader(HeaderConstants.IF_NONE_MATCH);
|
||||
final Header ifNoneMatch = request.getFirstHeader(HttpHeaders.IF_NONE_MATCH);
|
||||
if (ifNoneMatch == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -221,14 +175,4 @@ class RequestProtocolCompliance {
|
|||
return null;
|
||||
}
|
||||
|
||||
private RequestProtocolError requestContainsNoCacheDirectiveWithFieldName(final HttpRequest request) {
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(elt.getName()) && elt.getValue() != null) {
|
||||
return RequestProtocolError.NO_CACHE_DIRECTIVE_WITH_FIELD_NAME;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ enum RequestProtocolError {
|
|||
UNKNOWN,
|
||||
BODY_BUT_NO_LENGTH_ERROR,
|
||||
WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR,
|
||||
WEAK_ETAG_AND_RANGE_ERROR,
|
||||
NO_CACHE_DIRECTIVE_WITH_FIELD_NAME
|
||||
WEAK_ETAG_AND_RANGE_ERROR
|
||||
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ import org.apache.hc.client5.http.utils.DateUtils;
|
|||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpMessage;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.HttpResponse;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
|
@ -206,12 +205,12 @@ class ResponseCachingPolicy {
|
|||
}
|
||||
}
|
||||
|
||||
if (response.countHeaders(HeaderConstants.AGE) > 1) {
|
||||
if (response.countHeaders(HttpHeaders.AGE) > 1) {
|
||||
LOG.debug("Multiple Age headers");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.countHeaders(HeaderConstants.EXPIRES) > 1) {
|
||||
if (response.countHeaders(HttpHeaders.EXPIRES) > 1) {
|
||||
LOG.debug("Multiple Expires headers");
|
||||
return false;
|
||||
}
|
||||
|
@ -227,7 +226,7 @@ class ResponseCachingPolicy {
|
|||
return false;
|
||||
}
|
||||
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(response, HeaderConstants.VARY);
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(response, HttpHeaders.VARY);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elem = it.next();
|
||||
if ("*".equals(elem.getName())) {
|
||||
|
@ -296,25 +295,8 @@ class ResponseCachingPolicy {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated As of version 5.0, use {@link ResponseCachingPolicy#parseCacheControlHeader(MessageHeaders)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean hasCacheControlParameterFrom(final HttpMessage msg, final String[] params) {
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(msg, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elem = it.next();
|
||||
for (final String param : params) {
|
||||
if (param.equalsIgnoreCase(elem.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isExplicitlyCacheable(final HttpResponse response, final ResponseCacheControl cacheControl ) {
|
||||
if (response.getFirstHeader(HeaderConstants.EXPIRES) != null) {
|
||||
if (response.getFirstHeader(HttpHeaders.EXPIRES) != null) {
|
||||
return true;
|
||||
}
|
||||
if (cacheControl == null) {
|
||||
|
@ -392,7 +374,7 @@ class ResponseCachingPolicy {
|
|||
}
|
||||
|
||||
if (sharedCache) {
|
||||
if (request.countHeaders(HeaderConstants.AUTHORIZATION) > 0
|
||||
if (request.countHeaders(HttpHeaders.AUTHORIZATION) > 0
|
||||
&& cacheControl != null && !(cacheControl.getSharedMaxAge() > -1 || cacheControl.isMustRevalidate() || cacheControl.isPublic())) {
|
||||
LOG.debug("Request contains private credentials");
|
||||
return false;
|
||||
|
@ -407,7 +389,7 @@ class ResponseCachingPolicy {
|
|||
if (cacheControl != null) {
|
||||
return false;
|
||||
}
|
||||
final Header expiresHdr = response.getFirstHeader(HeaderConstants.EXPIRES);
|
||||
final Header expiresHdr = response.getFirstHeader(HttpHeaders.EXPIRES);
|
||||
final Header dateHdr = response.getFirstHeader(HttpHeaders.DATE);
|
||||
if (expiresHdr == null || dateHdr == null) {
|
||||
return false;
|
||||
|
@ -421,7 +403,7 @@ class ResponseCachingPolicy {
|
|||
}
|
||||
|
||||
private boolean from1_0Origin(final HttpResponse response) {
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(response, HeaderConstants.VIA);
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(response, HttpHeaders.VIA);
|
||||
if (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
final String proto = elt.toString().split("\\s")[0];
|
||||
|
|
|
@ -90,7 +90,7 @@ class ResponseProtocolCompliance {
|
|||
return;
|
||||
}
|
||||
|
||||
final Header[] warningHeaders = response.getHeaders(HeaderConstants.WARNING);
|
||||
final Header[] warningHeaders = response.getHeaders(HttpHeaders.WARNING);
|
||||
|
||||
if (warningHeaders == null || warningHeaders.length == 0) {
|
||||
return;
|
||||
|
@ -102,14 +102,14 @@ class ResponseProtocolCompliance {
|
|||
for(final WarningValue wv : WarningValue.getWarningValues(h)) {
|
||||
final Instant warnInstant = wv.getWarnDate();
|
||||
if (warnInstant == null || warnInstant.equals(responseDate)) {
|
||||
newWarningHeaders.add(new BasicHeader(HeaderConstants.WARNING,wv.toString()));
|
||||
newWarningHeaders.add(new BasicHeader(HttpHeaders.WARNING,wv.toString()));
|
||||
} else {
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modified) {
|
||||
response.removeHeaders(HeaderConstants.WARNING);
|
||||
response.removeHeaders(HttpHeaders.WARNING);
|
||||
for(final Header h : newWarningHeaders) {
|
||||
response.addHeader(h);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ class ResponseProtocolCompliance {
|
|||
|
||||
private void ensurePartialContentIsNotSentToAClientThatDidNotRequestIt(final HttpRequest request,
|
||||
final HttpResponse response) throws IOException {
|
||||
if (request.getFirstHeader(HeaderConstants.RANGE) != null
|
||||
if (request.getFirstHeader(HttpHeaders.RANGE) != null
|
||||
|| response.getCode() != HttpStatus.SC_PARTIAL_CONTENT) {
|
||||
return;
|
||||
}
|
||||
|
@ -183,9 +183,9 @@ class ResponseProtocolCompliance {
|
|||
}
|
||||
|
||||
private void ensure304DoesNotContainExtraEntityHeaders(final HttpResponse response) {
|
||||
final String[] disallowedEntityHeaders = { HeaderConstants.ALLOW, HttpHeaders.CONTENT_ENCODING,
|
||||
final String[] disallowedEntityHeaders = { HttpHeaders.ALLOW, HttpHeaders.CONTENT_ENCODING,
|
||||
"Content-Language", HttpHeaders.CONTENT_LENGTH, "Content-MD5",
|
||||
"Content-Range", HttpHeaders.CONTENT_TYPE, HeaderConstants.LAST_MODIFIED
|
||||
"Content-Range", HttpHeaders.CONTENT_TYPE, HttpHeaders.LAST_MODIFIED
|
||||
};
|
||||
if (response.getCode() == HttpStatus.SC_NOT_MODIFIED) {
|
||||
for(final String hdr : disallowedEntityHeaders) {
|
||||
|
|
|
@ -36,7 +36,6 @@ import static org.junit.jupiter.api.Assertions.assertSame;
|
|||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpDelete;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||
|
@ -131,7 +130,7 @@ public class TestBasicHttpCache {
|
|||
final HttpRequest req = new HttpPost("/foo");
|
||||
final HttpResponse resp = HttpTestUtils.make200Response();
|
||||
resp.setHeader("Content-Location", "/bar");
|
||||
resp.setHeader(HeaderConstants.ETAG, "\"etag\"");
|
||||
resp.setHeader(HttpHeaders.ETAG, "\"etag\"");
|
||||
final String key = CacheKeyGenerator.INSTANCE.generateKey(host, new HttpGet("/bar"));
|
||||
|
||||
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
|
@ -295,7 +294,7 @@ public class TestBasicHttpCache {
|
|||
// Retrieve the ETag header value from the original response and assert that
|
||||
// the returned cache entry has the same ETag value
|
||||
final String expectedEtag = origResponse2.getFirstHeader(HttpHeaders.ETAG).getValue();
|
||||
final String actualEtag = result.getFirstHeader(HeaderConstants.ETAG).getValue();
|
||||
final String actualEtag = result.getFirstHeader(HttpHeaders.ETAG).getValue();
|
||||
|
||||
assertEquals(expectedEtag, actualEtag);
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.schedule.SchedulingStrategy;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpResponse;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.apache.hc.core5.http.message.BasicHttpResponse;
|
||||
|
@ -127,15 +127,15 @@ public class TestCacheRevalidatorBase {
|
|||
@Test
|
||||
public void testStaleResponse() {
|
||||
final HttpResponse response1 = new BasicHttpResponse(HttpStatus.SC_OK);
|
||||
response1.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
|
||||
response1.addHeader(HttpHeaders.WARNING, "110 localhost \"Response is stale\"");
|
||||
assertThat(impl.isStale(response1), CoreMatchers.equalTo(true));
|
||||
|
||||
final HttpResponse response2 = new BasicHttpResponse(HttpStatus.SC_OK);
|
||||
response2.addHeader(HeaderConstants.WARNING, "111 localhost \"Revalidation failed\"");
|
||||
response2.addHeader(HttpHeaders.WARNING, "111 localhost \"Revalidation failed\"");
|
||||
assertThat(impl.isStale(response2), CoreMatchers.equalTo(true));
|
||||
|
||||
final HttpResponse response3 = new BasicHttpResponse(HttpStatus.SC_OK);
|
||||
response3.addHeader(HeaderConstants.WARNING, "xxx localhost \"Huh?\"");
|
||||
response3.addHeader(HttpHeaders.WARNING, "xxx localhost \"Huh?\"");
|
||||
assertThat(impl.isStale(response3), CoreMatchers.equalTo(false));
|
||||
|
||||
final HttpResponse response4 = new BasicHttpResponse(HttpStatus.SC_OK);
|
||||
|
|
|
@ -188,31 +188,6 @@ public class TestCachedResponseSuitabilityChecker {
|
|||
Assertions.assertFalse(impl.canCachedResponseBeUsed(request, entry, now));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMalformedCacheControlMaxAgeRequestHeaderCausesUnsuitableEntry() {
|
||||
request.addHeader(new BasicHeader("Cache-Control", "max-age=foo"));
|
||||
final Header[] headers = {
|
||||
new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
|
||||
new BasicHeader("Cache-Control", "max-age=3600"),
|
||||
new BasicHeader("Content-Length","128")
|
||||
};
|
||||
entry = getEntry(headers);
|
||||
Assertions.assertFalse(impl.canCachedResponseBeUsed(request, entry, now));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMalformedCacheControlMinFreshRequestHeaderCausesUnsuitableEntry() {
|
||||
request.addHeader(new BasicHeader("Cache-Control", "min-fresh=foo"));
|
||||
final Header[] headers = {
|
||||
new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
|
||||
new BasicHeader("Cache-Control", "max-age=3600"),
|
||||
new BasicHeader("Content-Length","128")
|
||||
};
|
||||
entry = getEntry(headers);
|
||||
Assertions.assertFalse(impl.canCachedResponseBeUsed(request, entry, now));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuitableIfCacheEntryIsHeuristicallyFreshEnough() {
|
||||
final Instant oneSecondAgo = now.minusSeconds(1);
|
||||
|
|
|
@ -31,11 +31,11 @@ import java.util.HashMap;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.utils.DateUtils;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HeaderElement;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.message.BasicHeader;
|
||||
import org.apache.hc.core5.http.message.BasicHttpRequest;
|
||||
|
@ -151,16 +151,8 @@ public class TestConditionalRequestBuilder {
|
|||
|
||||
final HttpRequest result = impl.buildConditionalRequest(basicRequest, cacheEntry);
|
||||
|
||||
boolean foundMaxAge0 = false;
|
||||
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if ("max-age".equalsIgnoreCase(elt.getName()) && "0".equals(elt.getValue())) {
|
||||
foundMaxAge0 = true;
|
||||
}
|
||||
}
|
||||
Assertions.assertTrue(foundMaxAge0);
|
||||
final RequestCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(result);
|
||||
Assertions.assertEquals(0, cacheControl.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -179,15 +171,8 @@ public class TestConditionalRequestBuilder {
|
|||
|
||||
final HttpRequest result = impl.buildConditionalRequest(basicRequest, cacheEntry);
|
||||
|
||||
boolean foundMaxAge0 = false;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if ("max-age".equalsIgnoreCase(elt.getName()) && "0".equals(elt.getValue())) {
|
||||
foundMaxAge0 = true;
|
||||
}
|
||||
}
|
||||
Assertions.assertTrue(foundMaxAge0);
|
||||
final RequestCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(result);
|
||||
Assertions.assertEquals(0, cacheControl.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -210,15 +195,8 @@ public class TestConditionalRequestBuilder {
|
|||
public void testBuildUnconditionalRequestAddsCacheControlNoCache()
|
||||
throws Exception {
|
||||
final HttpRequest result = impl.buildUnconditionalRequest(request);
|
||||
boolean ccNoCacheFound = false;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if ("no-cache".equals(elt.getName())) {
|
||||
ccNoCacheFound = true;
|
||||
}
|
||||
}
|
||||
Assertions.assertTrue(ccNoCacheFound);
|
||||
final RequestCacheControl cacheControl = CacheControlHeaderParser.INSTANCE.parse(result);
|
||||
Assertions.assertTrue(cacheControl.isNoCache());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -226,7 +204,7 @@ public class TestConditionalRequestBuilder {
|
|||
throws Exception {
|
||||
final HttpRequest result = impl.buildUnconditionalRequest(request);
|
||||
boolean ccNoCacheFound = false;
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.PRAGMA);
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(result, HttpHeaders.PRAGMA);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if ("no-cache".equals(elt.getName())) {
|
||||
|
@ -292,14 +270,14 @@ public class TestConditionalRequestBuilder {
|
|||
final String etag3 = "\"789\"";
|
||||
|
||||
final Map<String,Variant> variantEntries = new HashMap<>();
|
||||
variantEntries.put(etag1, new Variant("A", HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag1) })));
|
||||
variantEntries.put(etag2, new Variant("B", HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag2) })));
|
||||
variantEntries.put(etag3, new Variant("C", HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag3) })));
|
||||
variantEntries.put(etag1, new Variant("A", HttpTestUtils.makeCacheEntry(new BasicHeader("ETag", etag1))));
|
||||
variantEntries.put(etag2, new Variant("B", HttpTestUtils.makeCacheEntry(new BasicHeader("ETag", etag2))));
|
||||
variantEntries.put(etag3, new Variant("C", HttpTestUtils.makeCacheEntry(new BasicHeader("ETag", etag3))));
|
||||
|
||||
final HttpRequest conditional = impl.buildConditionalRequestFromVariants(request, variantEntries);
|
||||
|
||||
// seems like a lot of work, but necessary, check for existence and exclusiveness
|
||||
String ifNoneMatch = conditional.getFirstHeader(HeaderConstants.IF_NONE_MATCH).getValue();
|
||||
String ifNoneMatch = conditional.getFirstHeader(HttpHeaders.IF_NONE_MATCH).getValue();
|
||||
Assertions.assertTrue(ifNoneMatch.contains(etag1));
|
||||
Assertions.assertTrue(ifNoneMatch.contains(etag2));
|
||||
Assertions.assertTrue(ifNoneMatch.contains(etag3));
|
||||
|
|
|
@ -37,7 +37,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -1301,7 +1300,7 @@ public class TestProtocolRecommendations {
|
|||
resp2.setEntity(HttpTestUtils.makeBody(200));
|
||||
resp2.setHeader("Content-Length","200");
|
||||
resp2.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
resp2.setHeader("Via","1.0 someproxy");
|
||||
resp2.setHeader(HttpHeaders.VIA,"1.0 someproxy");
|
||||
|
||||
Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2);
|
||||
|
||||
|
@ -1487,42 +1486,6 @@ public class TestProtocolRecommendations {
|
|||
assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result));
|
||||
}
|
||||
|
||||
/*
|
||||
* "If a request includes the no-cache directive, it SHOULD NOT
|
||||
* include min-fresh, max-stale, or max-age."
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
|
||||
*/
|
||||
@Test
|
||||
public void otherFreshnessRequestDirectivesNotAllowedWithNoCache() throws Exception {
|
||||
final ClassicHttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
req1.setHeader("Cache-Control", "min-fresh=10, no-cache");
|
||||
req1.addHeader("Cache-Control", "max-stale=0, max-age=0");
|
||||
|
||||
execute(req1);
|
||||
|
||||
final ArgumentCaptor<ClassicHttpRequest> reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class);
|
||||
Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any());
|
||||
|
||||
final ClassicHttpRequest captured = reqCapture.getValue();
|
||||
boolean foundNoCache = false;
|
||||
boolean foundDisallowedDirective = false;
|
||||
final List<String> disallowed =
|
||||
Arrays.asList("min-fresh", "max-stale", "max-age");
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(captured, HttpHeaders.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if (disallowed.contains(elt.getName())) {
|
||||
foundDisallowedDirective = true;
|
||||
}
|
||||
if ("no-cache".equals(elt.getName())) {
|
||||
foundNoCache = true;
|
||||
}
|
||||
}
|
||||
assertTrue(foundNoCache);
|
||||
assertFalse(foundDisallowedDirective);
|
||||
}
|
||||
|
||||
/*
|
||||
* "To do this, the client may include the only-if-cached directive in
|
||||
* a request. If it receives this directive, a cache SHOULD either
|
||||
|
|
|
@ -404,9 +404,9 @@ public class TestProtocolRequirements {
|
|||
|
||||
@Test
|
||||
public void testOrderOfMultipleViaHeadersIsPreservedOnRequests() throws Exception {
|
||||
request.addHeader("Via", "1.0 fred, 1.1 nowhere.com (Apache/1.1)");
|
||||
request.addHeader("Via", "1.0 ricky, 1.1 mertz, 1.0 lucy");
|
||||
testOrderOfMultipleHeadersIsPreservedOnRequests("Via", request);
|
||||
request.addHeader(HttpHeaders.VIA, "1.0 fred, 1.1 nowhere.com (Apache/1.1)");
|
||||
request.addHeader(HttpHeaders.VIA, "1.0 ricky, 1.1 mertz, 1.0 lucy");
|
||||
testOrderOfMultipleHeadersIsPreservedOnRequests(HttpHeaders.VIA, request);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -465,9 +465,9 @@ public class TestProtocolRequirements {
|
|||
|
||||
@Test
|
||||
public void testOrderOfMultipleViaHeadersIsPreservedOnResponses() throws Exception {
|
||||
originResponse.addHeader("Via", "1.0 fred, 1.1 nowhere.com (Apache/1.1)");
|
||||
originResponse.addHeader("Via", "1.0 ricky, 1.1 mertz, 1.0 lucy");
|
||||
testOrderOfMultipleHeadersIsPreservedOnResponses("Via");
|
||||
originResponse.addHeader(HttpHeaders.VIA, "1.0 fred, 1.1 nowhere.com (Apache/1.1)");
|
||||
originResponse.addHeader(HttpHeaders.VIA, "1.0 ricky, 1.1 mertz, 1.0 lucy");
|
||||
testOrderOfMultipleHeadersIsPreservedOnResponses(HttpHeaders.VIA);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1980,7 +1980,7 @@ public class TestProtocolRequirements {
|
|||
resp1.setHeader("ETag", "\"etag\"");
|
||||
resp1.setHeader("Cache-Control", "max-age=5");
|
||||
resp1.setHeader("Warning", "110 squid \"stale stuff\"");
|
||||
resp1.setHeader("Via", "1.1 fred");
|
||||
resp1.setHeader(HttpHeaders.VIA, "1.1 fred");
|
||||
|
||||
final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/");
|
||||
|
||||
|
@ -1992,7 +1992,7 @@ public class TestProtocolRequirements {
|
|||
resp2.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
resp2.setHeader("Server", "MockServer/1.0");
|
||||
resp2.setHeader("ETag", "\"etag\"");
|
||||
resp2.setHeader("Via", "1.1 fred");
|
||||
resp2.setHeader(HttpHeaders.VIA, "1.1 fred");
|
||||
|
||||
Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1);
|
||||
Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(validate), Mockito.any())).thenReturn(resp2);
|
||||
|
@ -2040,7 +2040,7 @@ public class TestProtocolRequirements {
|
|||
resp1.setHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo));
|
||||
resp1.setHeader("ETag", "\"etag\"");
|
||||
resp1.setHeader("Cache-Control", "max-age=5");
|
||||
resp1.setHeader("Via", "1.1 xproxy");
|
||||
resp1.setHeader(HttpHeaders.VIA, "1.1 xproxy");
|
||||
resp1.setHeader("Warning", "214 xproxy \"transformed stuff\"");
|
||||
|
||||
final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/");
|
||||
|
@ -2053,7 +2053,7 @@ public class TestProtocolRequirements {
|
|||
resp2.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
resp2.setHeader("Server", "MockServer/1.0");
|
||||
resp2.setHeader("ETag", "\"etag\"");
|
||||
resp1.setHeader("Via", "1.1 xproxy");
|
||||
resp1.setHeader(HttpHeaders.VIA, "1.1 xproxy");
|
||||
|
||||
final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/");
|
||||
|
||||
|
@ -4223,37 +4223,6 @@ public class TestProtocolRequirements {
|
|||
}
|
||||
}
|
||||
|
||||
/* "Field names MUST NOT be included with the no-cache directive in a
|
||||
* request."
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
|
||||
*/
|
||||
@Test
|
||||
public void testDoesNotTransmitNoCacheDirectivesWithFieldsDownstream() throws Exception {
|
||||
request.setHeader("Cache-Control","no-cache=\"X-Field\"");
|
||||
|
||||
try {
|
||||
execute(request);
|
||||
} catch (final ClientProtocolException acceptable) {
|
||||
}
|
||||
|
||||
final ArgumentCaptor<ClassicHttpRequest> reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class);
|
||||
Mockito.verify(mockExecChain, Mockito.atMostOnce()).proceed(reqCapture.capture(), Mockito.any());
|
||||
|
||||
final List<ClassicHttpRequest> allRequests = reqCapture.getAllValues();
|
||||
|
||||
if (!allRequests.isEmpty()) {
|
||||
final ClassicHttpRequest captured = reqCapture.getValue();
|
||||
final Iterator<HeaderElement> it = MessageSupport.iterate(captured, HttpHeaders.CACHE_CONTROL);
|
||||
while (it.hasNext()) {
|
||||
final HeaderElement elt = it.next();
|
||||
if ("no-cache".equals(elt.getName())) {
|
||||
Assertions.assertNull(elt.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* "The request includes a "no-cache" cache-control directive or, for
|
||||
* compatibility with HTTP/1.0 clients, "Pragma: no-cache".... The
|
||||
* server MUST NOT use a cached copy when responding to such a request."
|
||||
|
@ -4883,7 +4852,7 @@ public class TestProtocolRequirements {
|
|||
*/
|
||||
@Test
|
||||
public void testProperlyFormattedViaHeaderIsAddedToRequests() throws Exception {
|
||||
request.removeHeaders("Via");
|
||||
request.removeHeaders(HttpHeaders.VIA);
|
||||
Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse);
|
||||
|
||||
execute(request);
|
||||
|
@ -4892,21 +4861,21 @@ public class TestProtocolRequirements {
|
|||
Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any());
|
||||
|
||||
final ClassicHttpRequest captured = reqCapture.getValue();
|
||||
final String via = captured.getFirstHeader("Via").getValue();
|
||||
final String via = captured.getFirstHeader(HttpHeaders.VIA).getValue();
|
||||
assertValidViaHeader(via);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProperlyFormattedViaHeaderIsAddedToResponses() throws Exception {
|
||||
originResponse.removeHeaders("Via");
|
||||
originResponse.removeHeaders(HttpHeaders.VIA);
|
||||
Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse);
|
||||
final ClassicHttpResponse result = execute(request);
|
||||
assertValidViaHeader(result.getFirstHeader("Via").getValue());
|
||||
assertValidViaHeader(result.getFirstHeader(HttpHeaders.VIA).getValue());
|
||||
}
|
||||
|
||||
|
||||
private void assertValidViaHeader(final String via) {
|
||||
// Via = "Via" ":" 1#( received-protocol received-by [ comment ] )
|
||||
// Via = HttpHeaders.VIA ":" 1#( received-protocol received-by [ comment ] )
|
||||
// received-protocol = [ protocol-name "/" ] protocol-version
|
||||
// protocol-name = token
|
||||
// protocol-version = token
|
||||
|
@ -4978,7 +4947,7 @@ public class TestProtocolRequirements {
|
|||
final ClassicHttpRequest originalRequest = new BasicClassicHttpRequest("GET", "/");
|
||||
originalRequest.setVersion(HttpVersion.HTTP_1_0);
|
||||
request = originalRequest;
|
||||
request.removeHeaders("Via");
|
||||
request.removeHeaders(HttpHeaders.VIA);
|
||||
|
||||
Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse);
|
||||
|
||||
|
@ -4988,7 +4957,7 @@ public class TestProtocolRequirements {
|
|||
Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any());
|
||||
|
||||
final ClassicHttpRequest captured = reqCapture.getValue();
|
||||
final String via = captured.getFirstHeader("Via").getValue();
|
||||
final String via = captured.getFirstHeader(HttpHeaders.VIA).getValue();
|
||||
final String protocol = via.split("\\s+")[0];
|
||||
final String[] protoParts = protocol.split("/");
|
||||
if (protoParts.length > 1) {
|
||||
|
@ -5007,7 +4976,7 @@ public class TestProtocolRequirements {
|
|||
|
||||
final ClassicHttpResponse result = execute(request);
|
||||
|
||||
final String via = result.getFirstHeader("Via").getValue();
|
||||
final String via = result.getFirstHeader(HttpHeaders.VIA).getValue();
|
||||
final String protocol = via.split("\\s+")[0];
|
||||
final String[] protoParts = protocol.split("/");
|
||||
Assertions.assertTrue(protoParts.length >= 1);
|
||||
|
|
|
@ -72,13 +72,6 @@ public class TestRequestProtocolCompliance {
|
|||
assertEquals(Collections.emptyList(), impl.requestIsFatallyNonCompliant(req));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestContainsNoCacheDirectiveWithFieldName() throws Exception {
|
||||
final HttpRequest req = new BasicHttpRequest("GET", "/");
|
||||
req.setHeader("Cache-Control", "no-cache=false");
|
||||
assertEquals(1, impl.requestIsFatallyNonCompliant(req).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotModifyACompliantRequest() throws Exception {
|
||||
final HttpRequest req = new BasicHttpRequest("GET", "/");
|
||||
|
@ -105,59 +98,4 @@ public class TestRequestProtocolCompliance {
|
|||
assertEquals(HttpVersion.HTTP_1_1, wrapper.getVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stripsMinFreshFromRequestIfNoCachePresent()
|
||||
throws Exception {
|
||||
final HttpRequest req = new BasicHttpRequest("GET", "/");
|
||||
req.setHeader("Cache-Control", "no-cache, min-fresh=10");
|
||||
final HttpRequest wrapper = BasicRequestBuilder.copy(req).build();
|
||||
impl.makeRequestCompliant(wrapper);
|
||||
assertEquals("no-cache",
|
||||
wrapper.getFirstHeader("Cache-Control").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stripsMaxFreshFromRequestIfNoCachePresent()
|
||||
throws Exception {
|
||||
final HttpRequest req = new BasicHttpRequest("GET", "/");
|
||||
req.setHeader("Cache-Control", "no-cache, max-stale=10");
|
||||
final HttpRequest wrapper = BasicRequestBuilder.copy(req).build();
|
||||
impl.makeRequestCompliant(wrapper);
|
||||
assertEquals("no-cache",
|
||||
wrapper.getFirstHeader("Cache-Control").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stripsMaxAgeFromRequestIfNoCachePresent()
|
||||
throws Exception {
|
||||
final HttpRequest req = new BasicHttpRequest("GET", "/");
|
||||
req.setHeader("Cache-Control", "no-cache, max-age=10");
|
||||
final HttpRequest wrapper = BasicRequestBuilder.copy(req).build();
|
||||
impl.makeRequestCompliant(wrapper);
|
||||
assertEquals("no-cache",
|
||||
wrapper.getFirstHeader("Cache-Control").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotStripMinFreshFromRequestWithoutNoCache()
|
||||
throws Exception {
|
||||
final HttpRequest req = new BasicHttpRequest("GET", "/");
|
||||
req.setHeader("Cache-Control", "min-fresh=10");
|
||||
final HttpRequest wrapper = BasicRequestBuilder.copy(req).build();
|
||||
impl.makeRequestCompliant(wrapper);
|
||||
assertEquals("min-fresh=10",
|
||||
wrapper.getFirstHeader("Cache-Control").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctlyStripsMinFreshFromMiddleIfNoCache()
|
||||
throws Exception {
|
||||
final HttpRequest req = new BasicHttpRequest("GET", "/");
|
||||
req.setHeader("Cache-Control", "no-cache,min-fresh=10,no-store");
|
||||
final HttpRequest wrapper = BasicRequestBuilder.copy(req).build();
|
||||
impl.makeRequestCompliant(wrapper);
|
||||
assertEquals("no-cache,no-store",
|
||||
wrapper.getFirstHeader("Cache-Control").getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -738,14 +738,14 @@ public class TestResponseCachingPolicy {
|
|||
@Test
|
||||
public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheable() {
|
||||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
response.setHeader("Via", "1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
|
||||
Assertions.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheable() {
|
||||
request = new BasicHttpRequest("HEAD", "/foo?s=bar");
|
||||
response.setHeader("Via", "1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
|
||||
Assertions.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -754,7 +754,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
|
||||
Assertions.assertTrue(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -764,7 +764,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("HEAD", "/foo?s=bar");
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
|
||||
Assertions.assertTrue(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -774,7 +774,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
|
||||
Assertions.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -784,7 +784,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("HEAD", "/foo?s=bar");
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "1.0 someproxy");
|
||||
Assertions.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -793,7 +793,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "HTTP/1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "HTTP/1.0 someproxy");
|
||||
Assertions.assertTrue(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -803,7 +803,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("HEAD", "/foo?s=bar");
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "HTTP/1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "HTTP/1.0 someproxy");
|
||||
Assertions.assertTrue(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -813,7 +813,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "HTTP/1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "HTTP/1.0 someproxy");
|
||||
Assertions.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -823,7 +823,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("HEAD", "/foo?s=bar");
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "HTTP/1.0 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "HTTP/1.0 someproxy");
|
||||
Assertions.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -834,7 +834,7 @@ public class TestResponseCachingPolicy {
|
|||
response.setVersion(HttpVersion.HTTP_1_0);
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "1.1 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "1.1 someproxy");
|
||||
Assertions.assertTrue(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
@ -846,7 +846,7 @@ public class TestResponseCachingPolicy {
|
|||
response.setVersion(HttpVersion.HTTP_1_0);
|
||||
response.setHeader("Date", DateUtils.formatStandardDate(now));
|
||||
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "1.1 someproxy");
|
||||
response.setHeader(HttpHeaders.VIA, "1.1 someproxy");
|
||||
Assertions.assertTrue(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue