TABS -> SPACES
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1172301 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f5cb5f9e19
commit
e5ea32b76d
|
@ -28,7 +28,7 @@ package org.apache.http.client.cache;
|
|||
|
||||
/**
|
||||
* This enumeration represents the various ways a response can be generated
|
||||
* by the {@link org.apache.http.impl.client.cache.CachingHttpClient};
|
||||
* by the {@link org.apache.http.impl.client.cache.CachingHttpClient};
|
||||
* if a request is executed with an {@link org.apache.http.protocol.HttpContext}
|
||||
* then a parameter with one of these values will be registered in the
|
||||
* context under the key
|
||||
|
|
|
@ -110,7 +110,7 @@ public class HttpCacheEntry implements Serializable {
|
|||
? new HashMap<String,String>(variantMap)
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link HttpCacheEntry}.
|
||||
*
|
||||
|
@ -207,7 +207,7 @@ public class HttpCacheEntry implements Serializable {
|
|||
public Resource getResource() {
|
||||
return this.resource;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether the origin response indicated the associated
|
||||
* resource had variants (i.e. that the Vary header was set on the
|
||||
|
|
|
@ -33,7 +33,7 @@ import java.io.OutputStream;
|
|||
/**
|
||||
* Used by some {@link HttpCacheStorage} implementations to serialize
|
||||
* {@link HttpCacheEntry} instances to a byte representation before
|
||||
* storage.
|
||||
* storage.
|
||||
*/
|
||||
public interface HttpCacheEntrySerializer {
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import java.io.IOException;
|
|||
* interface. They can then be plugged into the existing
|
||||
* {@link org.apache.http.impl.client.cache.CachingHttpClient}
|
||||
* implementation.
|
||||
*
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public interface HttpCacheStorage {
|
||||
|
@ -68,7 +68,7 @@ public interface HttpCacheStorage {
|
|||
* Atomically applies the given callback to update an existing cache
|
||||
* entry under a given key.
|
||||
* @param key indicates which entry to modify
|
||||
* @param callback performs the update; see
|
||||
* @param callback performs the update; see
|
||||
* {@link HttpCacheUpdateCallback} for details, but roughly the
|
||||
* callback expects to be handed the current entry and will return
|
||||
* the new value for the entry.
|
||||
|
|
|
@ -49,4 +49,4 @@ public interface HttpCacheUpdateCallback {
|
|||
*/
|
||||
HttpCacheEntry update(HttpCacheEntry existing) throws IOException;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,4 +45,4 @@ public class HttpCacheUpdateException extends Exception {
|
|||
initCause(cause);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.apache.http.annotation.NotThreadSafe;
|
|||
/**
|
||||
* Used to limiting the size of an incoming response body of
|
||||
* unknown size that is optimistically being read in anticipation
|
||||
* of caching it.
|
||||
* of caching it.
|
||||
* @since 4.1
|
||||
*/
|
||||
@NotThreadSafe // reached
|
||||
|
|
|
@ -12,7 +12,7 @@ to you under the Apache License, Version 2.0 (the
|
|||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
|
@ -51,7 +51,7 @@ the {@code CachingHttpClient} to indicate how the request was
|
|||
processed by the caching module itself.
|
||||
</p>
|
||||
<p>
|
||||
New storage backends will need to implement the
|
||||
New storage backends will need to implement the
|
||||
{@link org.apache.http.client.cache.HttpCacheStorage}
|
||||
interface; they can then be passed to one of the {@code CachingHttpClient}
|
||||
constructors, which will happily make use of the new storage mechanism.
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.apache.http.protocol.HttpContext;
|
|||
|
||||
/**
|
||||
* Class used to represent an asynchronous revalidation event, such as with
|
||||
* "stale-while-revalidate"
|
||||
* "stale-while-revalidate"
|
||||
*/
|
||||
class AsynchronousValidationRequest implements Runnable {
|
||||
private final AsynchronousValidator parent;
|
||||
|
@ -47,12 +47,12 @@ class AsynchronousValidationRequest implements Runnable {
|
|||
private final HttpContext context;
|
||||
private final HttpCacheEntry cacheEntry;
|
||||
private final String identifier;
|
||||
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
|
||||
/**
|
||||
* Used internally by {@link AsynchronousValidator} to schedule a
|
||||
* revalidation.
|
||||
* revalidation.
|
||||
* @param cachingClient
|
||||
* @param target
|
||||
* @param request
|
||||
|
@ -74,7 +74,7 @@ class AsynchronousValidationRequest implements Runnable {
|
|||
this.cacheEntry = cacheEntry;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
cachingClient.revalidateCacheEntry(target, request, context, cacheEntry);
|
||||
|
@ -90,5 +90,5 @@ class AsynchronousValidationRequest implements Runnable {
|
|||
String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -51,20 +51,20 @@ class AsynchronousValidator {
|
|||
private final ExecutorService executor;
|
||||
private final Set<String> queued;
|
||||
private final CacheKeyGenerator cacheKeyGenerator;
|
||||
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
|
||||
/**
|
||||
* Create AsynchronousValidator which will make revalidation requests
|
||||
* using the supplied {@link CachingHttpClient}, and
|
||||
* using the supplied {@link CachingHttpClient}, and
|
||||
* a {@link ThreadPoolExecutor} generated according to the thread
|
||||
* pool settings provided in the given {@link CacheConfig}.
|
||||
* pool settings provided in the given {@link CacheConfig}.
|
||||
* @param cachingClient used to execute asynchronous requests
|
||||
* @param config specifies thread pool settings. See
|
||||
* {@link CacheConfig#getAsynchronousWorkersMax()},
|
||||
* {@link CacheConfig#getAsynchronousWorkersCore()},
|
||||
* {@link CacheConfig#getAsynchronousWorkerIdleLifetimeSecs()},
|
||||
* and {@link CacheConfig#getRevalidationQueueSize()}.
|
||||
* and {@link CacheConfig#getRevalidationQueueSize()}.
|
||||
*/
|
||||
public AsynchronousValidator(CachingHttpClient cachingClient,
|
||||
CacheConfig config) {
|
||||
|
@ -76,7 +76,7 @@ class AsynchronousValidator {
|
|||
new ArrayBlockingQueue<Runnable>(config.getRevalidationQueueSize()))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create AsynchronousValidator which will make revalidation requests
|
||||
* using the supplied {@link CachingHttpClient} and
|
||||
|
@ -91,10 +91,10 @@ class AsynchronousValidator {
|
|||
this.queued = new HashSet<String>();
|
||||
this.cacheKeyGenerator = new CacheKeyGenerator();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Schedules an asynchronous revalidation
|
||||
*
|
||||
*
|
||||
* @param target
|
||||
* @param request
|
||||
* @param context
|
||||
|
@ -104,7 +104,7 @@ class AsynchronousValidator {
|
|||
HttpRequest request, HttpContext context, HttpCacheEntry entry) {
|
||||
// getVariantURI will fall back on getURI if no variants exist
|
||||
String uri = cacheKeyGenerator.getVariantURI(target, request, entry);
|
||||
|
||||
|
||||
if (!queued.contains(uri)) {
|
||||
AsynchronousValidationRequest revalidationRequest =
|
||||
new AsynchronousValidationRequest(this, cachingClient, target,
|
||||
|
@ -121,7 +121,7 @@ class AsynchronousValidator {
|
|||
|
||||
/**
|
||||
* Removes an identifier from the internal list of revalidation jobs in
|
||||
* progress. This is meant to be called by
|
||||
* progress. This is meant to be called by
|
||||
* {@link AsynchronousValidationRequest#run()} once the revalidation is
|
||||
* complete, using the identifier passed in during constructions.
|
||||
* @param identifier
|
||||
|
@ -129,11 +129,11 @@ class AsynchronousValidator {
|
|||
synchronized void markComplete(String identifier) {
|
||||
queued.remove(identifier);
|
||||
}
|
||||
|
||||
|
||||
Set<String> getScheduledIdentifiers() {
|
||||
return Collections.unmodifiableSet(queued);
|
||||
}
|
||||
|
||||
|
||||
ExecutorService getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ class BasicHttpCache implements HttpCache {
|
|||
String uri = uriExtractor.getURI(host, request);
|
||||
storage.removeEntry(uri);
|
||||
}
|
||||
|
||||
|
||||
public void flushInvalidatedCacheEntriesFor(HttpHost host, HttpRequest request, HttpResponse response) {
|
||||
cacheInvalidator.flushInvalidatedCacheEntries(host, request, response);
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ class BasicHttpCache implements HttpCache {
|
|||
if (src == null) {
|
||||
src = entry;
|
||||
}
|
||||
|
||||
|
||||
Resource resource = resourceFactory.copy(requestId, src.getResource());
|
||||
Map<String,String> variantMap = new HashMap<String,String>(src.getVariantMap());
|
||||
variantMap.put(variantKey, variantCacheKey);
|
||||
|
@ -231,7 +231,7 @@ class BasicHttpCache implements HttpCache {
|
|||
storage.putEntry(cacheKey, updatedEntry);
|
||||
return updatedEntry;
|
||||
}
|
||||
|
||||
|
||||
public HttpResponse cacheAndReturnResponse(HttpHost host, HttpRequest request,
|
||||
HttpResponse originResponse, Date requestSent, Date responseReceived)
|
||||
throws IOException {
|
||||
|
@ -300,4 +300,4 @@ class BasicHttpCache implements HttpCache {
|
|||
variants.put(etagHeader.getValue(), new Variant(variantKey, variantCacheKey, entry));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,4 +82,4 @@ class BasicIdGenerator {
|
|||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,19 +33,19 @@ package org.apache.http.impl.client.cache;
|
|||
* {@code CacheConfig} instance has sane and conservative defaults, so the
|
||||
* easiest way to specify options is to get an instance and then set just
|
||||
* the options you want to modify from their defaults.</p>
|
||||
*
|
||||
*
|
||||
* <p><b>N.B.</b> This class is only for caching-specific configuration; to
|
||||
* configure the behavior of the rest of the client, configure the
|
||||
* configure the behavior of the rest of the client, configure the
|
||||
* {@link org.apache.http.client.HttpClient} used as the "backend"
|
||||
* for the {@code CachingHttpClient}.</p>
|
||||
*
|
||||
*
|
||||
* <p>Cache configuration can be grouped into the following categories:</p>
|
||||
*
|
||||
*
|
||||
* <p><b>Cache size.</b> If the backend storage supports these limits, you
|
||||
* can specify the {@link CacheConfig#setMaxCacheEntries maximum number of
|
||||
* cache entries} as well as the {@link CacheConfig#setMaxObjectSizeBytes
|
||||
* maximum cacheable response body size}.</p>
|
||||
*
|
||||
*
|
||||
* <p><b>Public/private caching.</b> By default, the caching module considers
|
||||
* itself to be a shared (public) cache, and will not, for example, cache
|
||||
* responses to requests with {@code Authorization} headers or responses
|
||||
|
@ -53,7 +53,7 @@ package org.apache.http.impl.client.cache;
|
|||
* is only going to be used by one logical "user" (behaving similarly to a
|
||||
* browser cache), then you will want to {@link
|
||||
* CacheConfig#setSharedCache(boolean) turn off the shared cache setting}.</p>
|
||||
*
|
||||
*
|
||||
* <p><b>Heuristic caching</b>. Per RFC2616, a cache may cache certain cache
|
||||
* entries even if no explicit cache control headers are set by the origin.
|
||||
* This behavior is off by default, but you may want to turn this on if you
|
||||
|
@ -67,7 +67,7 @@ package org.apache.http.impl.client.cache;
|
|||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.2">
|
||||
* 13.2.2</a> and <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.4">
|
||||
* 13.2.4</a> of the HTTP/1.1 RFC for more details on heuristic caching.</p>
|
||||
*
|
||||
*
|
||||
* <p><b>Background validation</b>. The cache module supports the
|
||||
* {@code stale-while-revalidate} directive of
|
||||
* <a href="http://tools.ietf.org/html/rfc5861">RFC5861</a>, which allows
|
||||
|
@ -79,7 +79,7 @@ package org.apache.http.impl.client.cache;
|
|||
* CacheConfig#setAsynchronousWorkerIdleLifetimeSecs(int) maximum time they
|
||||
* can be idle before being reclaimed}. You can also control the {@link
|
||||
* CacheConfig#setRevalidationQueueSize(int) size of the queue} used for
|
||||
* revalidations when there aren't enough workers to keep up with demand.</b>
|
||||
* revalidations when there aren't enough workers to keep up with demand.</b>
|
||||
*/
|
||||
public class CacheConfig {
|
||||
|
||||
|
@ -115,22 +115,22 @@ public class CacheConfig {
|
|||
/** Default number of worker threads to allow for background revalidations
|
||||
* resulting from the stale-while-revalidate directive.
|
||||
*/
|
||||
public static final int DEFAULT_ASYNCHRONOUS_WORKERS_MAX = 1;
|
||||
public static final int DEFAULT_ASYNCHRONOUS_WORKERS_MAX = 1;
|
||||
|
||||
/** Default minimum number of worker threads to allow for background
|
||||
* revalidations resulting from the stale-while-revalidate directive.
|
||||
*/
|
||||
public static final int DEFAULT_ASYNCHRONOUS_WORKERS_CORE = 1;
|
||||
|
||||
|
||||
/** Default maximum idle lifetime for a background revalidation thread
|
||||
* before it gets reclaimed.
|
||||
*/
|
||||
public static final int DEFAULT_ASYNCHRONOUS_WORKER_IDLE_LIFETIME_SECS = 60;
|
||||
|
||||
/** Default maximum queue length for background revalidation requests.
|
||||
|
||||
/** Default maximum queue length for background revalidation requests.
|
||||
*/
|
||||
public static final int DEFAULT_REVALIDATION_QUEUE_SIZE = 100;
|
||||
|
||||
|
||||
private int maxObjectSizeBytes = DEFAULT_MAX_OBJECT_SIZE_BYTES;
|
||||
private int maxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
|
||||
private int maxUpdateRetries = DEFAULT_MAX_UPDATE_RETRIES;
|
||||
|
@ -236,7 +236,7 @@ public class CacheConfig {
|
|||
* and {@code Date} headers of a cached response during which the cached
|
||||
* response will be considered heuristically fresh.
|
||||
* @param heuristicCoefficient should be between {@code 0.0} and
|
||||
* {@code 1.0}.
|
||||
* {@code 1.0}.
|
||||
*/
|
||||
public void setHeuristicCoefficient(float heuristicCoefficient) {
|
||||
this.heuristicCoefficient = heuristicCoefficient;
|
||||
|
@ -255,7 +255,7 @@ public class CacheConfig {
|
|||
* calculation is not possible. Explicit cache control directives on
|
||||
* either the request or origin response will override this, as will
|
||||
* the heuristic {@code Last-Modified} freshness calculation if it is
|
||||
* available.
|
||||
* available.
|
||||
* @param heuristicDefaultLifetimeSecs is the number of seconds to
|
||||
* consider a cache-eligible response fresh in the absence of other
|
||||
* information. Set this to {@code 0} to disable this style of
|
||||
|
@ -276,9 +276,9 @@ public class CacheConfig {
|
|||
|
||||
/**
|
||||
* Sets the maximum number of threads to allow for background
|
||||
* revalidations due to the {@code stale-while-revalidate} directive.
|
||||
* revalidations due to the {@code stale-while-revalidate} directive.
|
||||
* @param max number of threads; a value of 0 disables background
|
||||
* revalidations.
|
||||
* revalidations.
|
||||
*/
|
||||
public void setAsynchronousWorkersMax(int max) {
|
||||
this.asynchronousWorkersMax = max;
|
||||
|
@ -286,7 +286,7 @@ public class CacheConfig {
|
|||
|
||||
/**
|
||||
* Returns the minimum number of threads to keep alive for background
|
||||
* revalidations due to the {@code stale-while-revalidate} directive.
|
||||
* revalidations due to the {@code stale-while-revalidate} directive.
|
||||
*/
|
||||
public int getAsynchronousWorkersCore() {
|
||||
return asynchronousWorkersCore;
|
||||
|
@ -296,7 +296,7 @@ public class CacheConfig {
|
|||
* Sets the minimum number of threads to keep alive for background
|
||||
* revalidations due to the {@code stale-while-revalidate} directive.
|
||||
* @param min should be greater than zero and less than or equal
|
||||
* to <code>getAsynchronousWorkersMax()</code>
|
||||
* to <code>getAsynchronousWorkersMax()</code>
|
||||
*/
|
||||
public void setAsynchronousWorkersCore(int min) {
|
||||
this.asynchronousWorkersCore = min;
|
||||
|
@ -337,5 +337,5 @@ public class CacheConfig {
|
|||
this.revalidationQueueSize = size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -172,7 +172,7 @@ class CacheInvalidator {
|
|||
}
|
||||
return relURL;
|
||||
}
|
||||
|
||||
|
||||
protected boolean requestShouldNotBeCached(HttpRequest req) {
|
||||
String method = req.getRequestLine().getMethod();
|
||||
return notGetOrHeadRequest(method);
|
||||
|
@ -184,7 +184,7 @@ class CacheInvalidator {
|
|||
}
|
||||
|
||||
/** Flushes entries that were invalidated by the given response
|
||||
* received for the given host/request pair.
|
||||
* received for the given host/request pair.
|
||||
*/
|
||||
public void flushInvalidatedCacheEntries(HttpHost host,
|
||||
HttpRequest request, HttpResponse response) {
|
||||
|
@ -200,7 +200,7 @@ class CacheInvalidator {
|
|||
|
||||
if (!responseDateNewerThanEntryDate(response, entry)) return;
|
||||
if (!responseAndEntryEtagsDiffer(response, entry)) return;
|
||||
|
||||
|
||||
flushUriIfSameHost(reqURL, canonURL);
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ class CacheInvalidator {
|
|||
String contentLocation = clHeader.getValue();
|
||||
URL canonURL = getAbsoluteURL(contentLocation);
|
||||
if (canonURL != null) return canonURL;
|
||||
return getRelativeURL(reqURL, contentLocation);
|
||||
return getRelativeURL(reqURL, contentLocation);
|
||||
}
|
||||
|
||||
private boolean responseAndEntryEtagsDiffer(HttpResponse response,
|
||||
|
|
|
@ -144,7 +144,7 @@ class CacheKeyGenerator {
|
|||
* Compute a "variant key" from the headers of a given request that are
|
||||
* covered by the Vary header of a given cache entry. Any request whose
|
||||
* varying headers match those of this request should have the same
|
||||
* variant key.
|
||||
* variant key.
|
||||
* @param req originating request
|
||||
* @param entry cache entry in question that has variants
|
||||
* @return a <code>String</code> variant key
|
||||
|
@ -179,4 +179,4 @@ class CacheKeyGenerator {
|
|||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,4 +47,4 @@ final class CacheMap extends LinkedHashMap<String, HttpCacheEntry> {
|
|||
return size() > this.maxEntries;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ class CacheValidityPolicy {
|
|||
public boolean proxyRevalidate(final HttpCacheEntry entry) {
|
||||
return hasCacheControlDirective(entry, "proxy-revalidate");
|
||||
}
|
||||
|
||||
|
||||
public boolean mayReturnStaleWhileRevalidating(final HttpCacheEntry entry, Date now) {
|
||||
for (Header h : entry.getHeaders("Cache-Control")) {
|
||||
for(HeaderElement elt : h.getElements()) {
|
||||
|
@ -135,10 +135,10 @@ class CacheValidityPolicy {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean mayReturnStaleIfError(HttpRequest request,
|
||||
HttpCacheEntry entry, Date now) {
|
||||
long stalenessSecs = getStalenessSecs(entry, now);
|
||||
|
@ -147,7 +147,7 @@ class CacheValidityPolicy {
|
|||
|| mayReturnStaleIfError(entry.getHeaders("Cache-Control"),
|
||||
stalenessSecs);
|
||||
}
|
||||
|
||||
|
||||
private boolean mayReturnStaleIfError(Header[] headers, long stalenessSecs) {
|
||||
boolean result = false;
|
||||
for(Header h : headers) {
|
||||
|
@ -206,8 +206,8 @@ class CacheValidityPolicy {
|
|||
|
||||
protected boolean hasContentLengthHeader(HttpCacheEntry entry) {
|
||||
return null != entry.getFirstHeader(HTTP.CONTENT_LEN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This matters for deciding whether the cache entry is valid to serve as a
|
||||
* response. If these values do not match, we might have a partial response
|
||||
|
|
|
@ -79,7 +79,7 @@ import org.apache.http.util.VersionInfo;
|
|||
* related configuration you want to do vis-a-vis timeouts and connection
|
||||
* pools should be done on this backend client before constructing a {@code
|
||||
* CachingHttpClient} from it.</p>
|
||||
*
|
||||
*
|
||||
* <p>Generally speaking, the {@code CachingHttpClient} is implemented as a
|
||||
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">Decorator</a>
|
||||
* of the backend client; for any incoming request it attempts to satisfy
|
||||
|
@ -92,7 +92,7 @@ import org.apache.http.util.VersionInfo;
|
|||
* This notion of "semantic transparency" means you should be able to drop
|
||||
* a {@link CachingHttpClient} into an existing application without breaking
|
||||
* anything.</p>
|
||||
*
|
||||
*
|
||||
* <p>Folks that would like to experiment with alternative storage backends
|
||||
* should look at the {@link HttpCacheStorage} interface and the related
|
||||
* package documentation there. You may also be interested in the provided
|
||||
|
@ -137,7 +137,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
private final RequestProtocolCompliance requestCompliance;
|
||||
|
||||
private final AsynchronousValidator asynchRevalidator;
|
||||
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
CachingHttpClient(
|
||||
|
@ -226,7 +226,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
* response bodies are managed using the given {@link ResourceFactory}.
|
||||
* @param client used to make origin requests
|
||||
* @param resourceFactory how to manage cached response bodies
|
||||
* @param storage where to store cache entries
|
||||
* @param storage where to store cache entries
|
||||
* @param config cache module options
|
||||
*/
|
||||
public CachingHttpClient(
|
||||
|
@ -244,7 +244,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
* that stores cache entries in the provided storage backend and uses
|
||||
* the given {@link HttpClient} for backend requests.
|
||||
* @param client used to make origin requests
|
||||
* @param storage where to store cache entries
|
||||
* @param storage where to store cache entries
|
||||
* @param config cache module options
|
||||
*/
|
||||
public CachingHttpClient(
|
||||
|
@ -282,7 +282,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
this.requestCompliance = requestCompliance;
|
||||
this.asynchRevalidator = makeAsynchronousValidator(config);
|
||||
}
|
||||
|
||||
|
||||
private AsynchronousValidator makeAsynchronousValidator(
|
||||
CacheConfig config) {
|
||||
if (config.getAsynchronousWorkersMax() > 0) {
|
||||
|
@ -292,7 +292,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
}
|
||||
|
||||
/**
|
||||
* Reports the number of times that the cache successfully responded
|
||||
* Reports the number of times that the cache successfully responded
|
||||
* to an {@link HttpRequest} without contacting the origin server.
|
||||
* @return the number of cache hits
|
||||
*/
|
||||
|
@ -395,7 +395,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
return handleCacheMiss(target, request, context);
|
||||
}
|
||||
|
||||
return handleCacheHit(target, request, context, entry);
|
||||
return handleCacheHit(target, request, context, entry);
|
||||
}
|
||||
|
||||
private HttpResponse handleCacheHit(HttpHost target, HttpRequest request,
|
||||
|
@ -428,9 +428,9 @@ public class CachingHttpClient implements HttpClient {
|
|||
&& !staleResponseNotAllowed(request, entry, now)
|
||||
&& validityPolicy.mayReturnStaleWhileRevalidating(entry, now)) {
|
||||
final HttpResponse resp = generateCachedResponse(request, context, entry, now);
|
||||
|
||||
|
||||
asynchRevalidator.revalidateCacheEntry(target, request, context, entry);
|
||||
|
||||
|
||||
return resp;
|
||||
}
|
||||
return revalidateCacheEntry(target, request, context, entry);
|
||||
|
@ -468,12 +468,12 @@ public class CachingHttpClient implements HttpClient {
|
|||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
private HttpResponse getFatallyNoncompliantResponse(HttpRequest request,
|
||||
HttpContext context) {
|
||||
HttpResponse fatalErrorResponse = null;
|
||||
List<RequestProtocolError> fatalError = requestCompliance.requestIsFatallyNonCompliant(request);
|
||||
|
||||
|
||||
for (RequestProtocolError error : fatalError) {
|
||||
setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
|
||||
fatalErrorResponse = requestCompliance.getErrorForRequest(error);
|
||||
|
@ -507,7 +507,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
log.trace("Cache hit [host: " + target + "; uri: " + rl.getUri() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void recordCacheUpdate(HttpContext context) {
|
||||
cacheUpdates.getAndIncrement();
|
||||
setResponseStatus(context, CacheResponseStatus.VALIDATED);
|
||||
|
@ -599,7 +599,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private String generateViaHeader(HttpMessage msg) {
|
||||
final VersionInfo vi = VersionInfo.loadVersionInfo("org.apache.http.client", getClass().getClassLoader());
|
||||
final String release = (vi != null) ? vi.getRelease() : VersionInfo.UNAVAILABLE;
|
||||
|
@ -690,7 +690,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
HttpResponse negotiateResponseFromVariants(HttpHost target,
|
||||
HttpRequest request, HttpContext context,
|
||||
Map<String, Variant> variants) throws IOException {
|
||||
|
@ -720,12 +720,12 @@ public class CachingHttpClient implements HttpClient {
|
|||
}
|
||||
|
||||
HttpCacheEntry matchedEntry = matchingVariant.getEntry();
|
||||
|
||||
|
||||
if (revalidationResponseIsTooOld(backendResponse, matchedEntry)) {
|
||||
return retryRequestUnconditionally(target, request, context,
|
||||
matchedEntry);
|
||||
}
|
||||
|
||||
|
||||
recordCacheUpdate(context);
|
||||
|
||||
HttpCacheEntry responseEntry = getUpdatedVariantEntry(target,
|
||||
|
@ -815,13 +815,13 @@ public class CachingHttpClient implements HttpClient {
|
|||
}
|
||||
return responseGenerator.generateResponse(updatedEntry);
|
||||
}
|
||||
|
||||
|
||||
if (staleIfErrorAppliesTo(statusCode)
|
||||
&& !staleResponseNotAllowed(request, cacheEntry, getCurrentDate())
|
||||
&& validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
|
||||
final HttpResponse cachedResponse = responseGenerator.generateResponse(cacheEntry);
|
||||
cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
|
||||
return cachedResponse;
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
return handleBackendResponse(target, conditionalRequest, requestDate, responseDate,
|
||||
|
@ -829,9 +829,9 @@ public class CachingHttpClient implements HttpClient {
|
|||
}
|
||||
|
||||
private boolean staleIfErrorAppliesTo(int statusCode) {
|
||||
return statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR
|
||||
|| statusCode == HttpStatus.SC_BAD_GATEWAY
|
||||
|| statusCode == HttpStatus.SC_SERVICE_UNAVAILABLE
|
||||
return statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR
|
||||
|| statusCode == HttpStatus.SC_BAD_GATEWAY
|
||||
|| statusCode == HttpStatus.SC_SERVICE_UNAVAILABLE
|
||||
|| statusCode == HttpStatus.SC_GATEWAY_TIMEOUT;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ import org.apache.http.impl.client.RequestWrapper;
|
|||
class ConditionalRequestBuilder {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ConditionalRequestBuilder.class);
|
||||
|
||||
|
||||
/**
|
||||
* When a {@link HttpCacheEntry} is stale but 'might' be used as a response
|
||||
* to an {@link HttpRequest} we will attempt to revalidate the entry with
|
||||
|
@ -117,7 +117,7 @@ class ConditionalRequestBuilder {
|
|||
first = false;
|
||||
etags.append(etag);
|
||||
}
|
||||
|
||||
|
||||
wrapperRequest.setHeader(HeaderConstants.IF_NONE_MATCH, etags.toString());
|
||||
return wrapperRequest;
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class ConditionalRequestBuilder {
|
|||
* @return an unconditional validation request
|
||||
*/
|
||||
public HttpRequest buildUnconditionalRequest(HttpRequest request,
|
||||
HttpCacheEntry entry) {
|
||||
HttpCacheEntry entry) {
|
||||
RequestWrapper wrapped;
|
||||
try {
|
||||
wrapped = new RequestWrapper(request);
|
||||
|
|
|
@ -56,9 +56,9 @@ interface HttpCache {
|
|||
*/
|
||||
void flushInvalidatedCacheEntriesFor(HttpHost host, HttpRequest request)
|
||||
throws IOException;
|
||||
|
||||
|
||||
/** Clear any entries that may be invalidated by the given response to
|
||||
* a particular request.
|
||||
* a particular request.
|
||||
* @param host
|
||||
* @param request
|
||||
* @param response
|
||||
|
@ -122,7 +122,7 @@ interface HttpCache {
|
|||
* Update a specific {@link HttpCacheEntry} representing a cached variant
|
||||
* using a 304 {@link HttpResponse}.
|
||||
* @param target host for client request
|
||||
* @param request actual request from upstream client
|
||||
* @param request actual request from upstream client
|
||||
* @param stale current variant cache entry
|
||||
* @param originResponse 304 response received from origin
|
||||
* @param requestSent when the validating request was sent
|
||||
|
|
|
@ -96,7 +96,7 @@ class RequestProtocolCompliance {
|
|||
*/
|
||||
public HttpRequest makeRequestCompliant(HttpRequest request)
|
||||
throws ClientProtocolException {
|
||||
|
||||
|
||||
if (requestMustNotHaveEntity(request)) {
|
||||
((HttpEntityEnclosingRequest) request).setEntity(null);
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ class RequestProtocolCompliance {
|
|||
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
private void stripOtherFreshnessDirectivesWithNoCache(HttpRequest request) {
|
||||
List<HeaderElement> outElts = new ArrayList<HeaderElement>();
|
||||
boolean shouldStrip = false;
|
||||
|
|
|
@ -198,13 +198,13 @@ class ResponseCachingPolicy {
|
|||
log.debug("Response was not cacheable.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
String[] uncacheableRequestDirectives = { "no-store" };
|
||||
if (hasCacheControlParameterFrom(request,uncacheableRequestDirectives)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.getRequestLine().getUri().contains("?") &&
|
||||
if (request.getRequestLine().getUri().contains("?") &&
|
||||
(!isExplicitlyCacheable(response) || from1_0Origin(response))) {
|
||||
log.debug("Response was not cacheable.");
|
||||
return false;
|
||||
|
@ -213,7 +213,7 @@ class ResponseCachingPolicy {
|
|||
if (expiresHeaderLessOrEqualToDateHeaderAndNoCacheControl(response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (sharedCache) {
|
||||
Header[] authNHeaders = request.getHeaders("Authorization");
|
||||
if (authNHeaders != null && authNHeaders.length > 0) {
|
||||
|
@ -249,7 +249,7 @@ class ResponseCachingPolicy {
|
|||
for(HeaderElement elt : via.getElements()) {
|
||||
String proto = elt.toString().split("\\s")[0];
|
||||
if (proto.contains("/")) {
|
||||
return proto.equals("HTTP/1.0");
|
||||
return proto.equals("HTTP/1.0");
|
||||
} else {
|
||||
return proto.equals("1.0");
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ class ResponseProtocolCompliance {
|
|||
*
|
||||
* @param request The {@link HttpRequest} that generated an origin hit and response
|
||||
* @param response The {@link HttpResponse} from the origin server
|
||||
* @throws IOException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void ensureProtocolCompliance(HttpRequest request, HttpResponse response)
|
||||
throws IOException {
|
||||
|
@ -85,7 +85,7 @@ class ResponseProtocolCompliance {
|
|||
ensure200ForOPTIONSRequestWithNoBodyHasContentLengthZero(request, response);
|
||||
|
||||
ensure206ContainsDateHeader(response);
|
||||
|
||||
|
||||
ensure304DoesNotContainExtraEntityHeaders(response);
|
||||
|
||||
identityIsNotUsedInContentEncoding(response);
|
||||
|
@ -167,9 +167,9 @@ class ResponseProtocolCompliance {
|
|||
private void ensurePartialContentIsNotSentToAClientThatDidNotRequestIt(HttpRequest request,
|
||||
HttpResponse response) throws IOException {
|
||||
if (request.getFirstHeader(HeaderConstants.RANGE) != null
|
||||
|| response.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT)
|
||||
|| response.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT)
|
||||
return;
|
||||
|
||||
|
||||
consumeBody(response);
|
||||
throw new ClientProtocolException(UNEXPECTED_PARTIAL_CONTENT);
|
||||
}
|
||||
|
@ -213,8 +213,8 @@ class ResponseProtocolCompliance {
|
|||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_CONTINUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
HttpRequest originalRequest = requestWasWrapped(request) ?
|
||||
|
||||
HttpRequest originalRequest = requestWasWrapped(request) ?
|
||||
((RequestWrapper)request).getOriginal() : request;
|
||||
if (originalRequest instanceof HttpEntityEnclosingRequest) {
|
||||
if (((HttpEntityEnclosingRequest)originalRequest).expectContinue()) return;
|
||||
|
|
|
@ -44,11 +44,11 @@ class Variant {
|
|||
public String getVariantKey() {
|
||||
return variantKey;
|
||||
}
|
||||
|
||||
|
||||
public String getCacheKey() {
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
|
||||
public HttpCacheEntry getEntry() {
|
||||
return entry;
|
||||
}
|
||||
|
|
|
@ -47,12 +47,12 @@ import org.apache.http.impl.client.cache.DefaultHttpCacheEntrySerializer;
|
|||
* In particular, this backend allows for spillover to disk, where the
|
||||
* cache can be effectively larger than memory, and cached responses are
|
||||
* paged into and out of memory from disk as needed.</p>
|
||||
*
|
||||
*
|
||||
* <p><b>N.B.</b> Since the Ehcache is configured ahead of time with a
|
||||
* maximum number of cache entries, this effectively ignores the
|
||||
* {@link CacheConfig#setMaxCacheEntries(int) maximum cache entries}
|
||||
* specified by a provided {@link CacheConfig}.</p>
|
||||
*
|
||||
*
|
||||
* <p>Please refer to the <a href="http://ehcache.org/documentation/index.html">
|
||||
* Ehcache documentation</a> for details on how to configure the Ehcache
|
||||
* itself.</p>
|
||||
|
@ -154,4 +154,4 @@ public class EhcacheHttpCacheStorage implements HttpCacheStorage {
|
|||
}while(numRetries <= maxUpdateRetries);
|
||||
throw new HttpCacheUpdateException("Failed to update");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ to you under the Apache License, Version 2.0 (the
|
|||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
|
@ -31,7 +31,7 @@ information on the Apache Software Foundation, please see
|
|||
|
||||
<p>
|
||||
This package contains a storage backend based on
|
||||
<a href="http://ehcache.org/">Ehcache</a>
|
||||
<a href="http://ehcache.org/">Ehcache</a>
|
||||
that can be plugged into
|
||||
a {@link org.apache.http.impl.client.cache.CachingHttpClient} and
|
||||
used for storing cache entries.
|
||||
|
|
|
@ -58,18 +58,18 @@ import org.apache.http.impl.client.cache.DefaultHttpCacheEntrySerializer;
|
|||
* peering of a sort</li>
|
||||
* </ol>
|
||||
* Note that in a shared memcached pool setting you may wish to make use
|
||||
* of the Ketama consistent hashing algorithm to reduce the number of
|
||||
* of the Ketama consistent hashing algorithm to reduce the number of
|
||||
* cache misses that might result if one of the memcached cluster members
|
||||
* fails (see the <a href="http://dustin.github.com/java-memcached-client/apidocs/net/spy/memcached/KetamaConnectionFactory.html">
|
||||
* KetamaConnectionFactory</a>).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>Please refer to the <a href="http://code.google.com/p/memcached/wiki/NewStart">
|
||||
* memcached documentation</a> and in particular to the documentation for
|
||||
* the <a href="http://code.google.com/p/spymemcached/">spymemcached
|
||||
* documentation</a> for details about how to set up and configure memcached
|
||||
* and the Java client used here, respectively.</p>
|
||||
*
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public class MemcachedHttpCacheStorage implements HttpCacheStorage {
|
||||
|
@ -166,4 +166,4 @@ public class MemcachedHttpCacheStorage implements HttpCacheStorage {
|
|||
} while(numRetries <= maxUpdateRetries);
|
||||
throw new HttpCacheUpdateException("Failed to update");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ to you under the Apache License, Version 2.0 (the
|
|||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
|
@ -31,7 +31,7 @@ information on the Apache Software Foundation, please see
|
|||
|
||||
<p>
|
||||
This package contains a storage backend based on
|
||||
<a href="http://memcached.org/">memcached</a>
|
||||
<a href="http://memcached.org/">memcached</a>
|
||||
that can be plugged into
|
||||
a {@link org.apache.http.impl.client.cache.CachingHttpClient} and
|
||||
used for storing cache entries.
|
||||
|
|
|
@ -12,7 +12,7 @@ to you under the Apache License, Version 2.0 (the
|
|||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
|
|
|
@ -199,21 +199,21 @@ public class TestHttpCacheEntry {
|
|||
entry = new HttpCacheEntry(new Date(), new Date(), statusLine,
|
||||
new Header[]{}, mockResource);
|
||||
assertSame(statusLine.getProtocolVersion(),
|
||||
entry.getProtocolVersion());
|
||||
entry.getProtocolVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reasonPhraseComesFromOriginalStatusLine() {
|
||||
entry = new HttpCacheEntry(new Date(), new Date(), statusLine,
|
||||
new Header[]{}, mockResource);
|
||||
assertSame(statusLine.getReasonPhrase(), entry.getReasonPhrase());
|
||||
assertSame(statusLine.getReasonPhrase(), entry.getReasonPhrase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeComesFromOriginalStatusLine() {
|
||||
entry = new HttpCacheEntry(new Date(), new Date(), statusLine,
|
||||
new Header[]{}, mockResource);
|
||||
assertEquals(statusLine.getStatusCode(), entry.getStatusCode());
|
||||
assertEquals(statusLine.getStatusCode(), entry.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -221,7 +221,7 @@ public class TestHttpCacheEntry {
|
|||
final Date requestDate = new Date();
|
||||
entry = new HttpCacheEntry(requestDate, new Date(), statusLine,
|
||||
new Header[]{}, mockResource);
|
||||
assertSame(requestDate, entry.getRequestDate());
|
||||
assertSame(requestDate, entry.getRequestDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -229,14 +229,14 @@ public class TestHttpCacheEntry {
|
|||
final Date responseDate = new Date();
|
||||
entry = new HttpCacheEntry(new Date(), responseDate, statusLine,
|
||||
new Header[]{}, mockResource);
|
||||
assertSame(responseDate, entry.getResponseDate());
|
||||
assertSame(responseDate, entry.getResponseDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetOriginalResource() {
|
||||
entry = new HttpCacheEntry(new Date(), new Date(), statusLine,
|
||||
new Header[]{}, mockResource);
|
||||
assertSame(mockResource, entry.getResource());
|
||||
assertSame(mockResource, entry.getResource());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -253,7 +253,7 @@ public class TestHttpCacheEntry {
|
|||
assertEquals(headers[i], result[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void canConstructWithoutVariants() {
|
||||
new HttpCacheEntry(new Date(), new Date(), statusLine,
|
||||
|
@ -266,7 +266,7 @@ public class TestHttpCacheEntry {
|
|||
new Header[]{}, mockResource,
|
||||
new HashMap<String,String>());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void canRetrieveOriginalVariantMap() {
|
||||
Map<String,String> variantMap = new HashMap<String,String>();
|
||||
|
@ -280,7 +280,7 @@ public class TestHttpCacheEntry {
|
|||
assertEquals("B", result.get("A"));
|
||||
assertEquals("D", result.get("C"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void retrievedVariantMapIsNotModifiable() {
|
||||
Map<String,String> variantMap = new HashMap<String,String>();
|
||||
|
@ -301,7 +301,7 @@ public class TestHttpCacheEntry {
|
|||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void canConvertToString() {
|
||||
entry = new HttpCacheEntry(new Date(), new Date(), statusLine,
|
||||
|
|
|
@ -113,7 +113,7 @@ public abstract class AbstractProtocolTest {
|
|||
|
||||
mockCache.flushInvalidatedCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class));
|
||||
EasyMock.expectLastCall().anyTimes();
|
||||
|
||||
|
||||
mockCache.flushInvalidatedCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), EasyMock.isA(HttpResponse.class));
|
||||
EasyMock.expectLastCall().anyTimes();
|
||||
}
|
||||
|
@ -127,4 +127,4 @@ public abstract class AbstractProtocolTest {
|
|||
super();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,4 +38,4 @@ public class Counter {
|
|||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,11 +76,11 @@ public class HttpTestUtils {
|
|||
"If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified", "Location",
|
||||
"Max-Forwards", "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
|
||||
"User-Agent", "Vary" };
|
||||
|
||||
|
||||
/*
|
||||
* "Entity-header fields define metainformation about the entity-body or,
|
||||
* if no body is present, about the resource identified by the request."
|
||||
*
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.1
|
||||
*/
|
||||
public static final String[] ENTITY_HEADERS = { "Allow", "Content-Encoding",
|
||||
|
@ -341,4 +341,4 @@ public class HttpTestUtils {
|
|||
return new BasicHttpResponse(HttpVersion.HTTP_1_1,
|
||||
HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,4 +38,4 @@ public class OKStatus extends BasicStatusLine {
|
|||
super(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,4 +50,4 @@ public class RequestEquivalent implements IArgumentMatcher {
|
|||
buf.append(")");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class TestAsynchronousValidationRequest {
|
|||
private HttpRequest request;
|
||||
private HttpContext mockContext;
|
||||
private HttpCacheEntry mockCacheEntry;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mockParent = EasyMock.createMock(AsynchronousValidator.class);
|
||||
|
@ -56,68 +56,68 @@ public class TestAsynchronousValidationRequest {
|
|||
mockContext = EasyMock.createMock(HttpContext.class);
|
||||
mockCacheEntry = EasyMock.createMock(HttpCacheEntry.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRunCallsCachingClientAndRemovesIdentifier() throws ProtocolException, IOException {
|
||||
String identifier = "foo";
|
||||
|
||||
|
||||
AsynchronousValidationRequest asynchRequest = new AsynchronousValidationRequest(
|
||||
mockParent, mockClient, target, request, mockContext, mockCacheEntry,
|
||||
identifier);
|
||||
|
||||
|
||||
// response not used
|
||||
EasyMock.expect(mockClient.revalidateCacheEntry(target, request, mockContext, mockCacheEntry)).andReturn(null);
|
||||
mockParent.markComplete(identifier);
|
||||
|
||||
|
||||
replayMocks();
|
||||
asynchRequest.run();
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRunGracefullyHandlesProtocolException() throws IOException, ProtocolException {
|
||||
String identifier = "foo";
|
||||
|
||||
|
||||
AsynchronousValidationRequest impl = new AsynchronousValidationRequest(
|
||||
mockParent, mockClient, target, request, mockContext, mockCacheEntry,
|
||||
identifier);
|
||||
|
||||
|
||||
// response not used
|
||||
EasyMock.expect(
|
||||
mockClient.revalidateCacheEntry(target, request, mockContext,
|
||||
mockCacheEntry)).andThrow(new ProtocolException());
|
||||
mockParent.markComplete(identifier);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.run();
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRunGracefullyHandlesIOException() throws IOException, ProtocolException {
|
||||
String identifier = "foo";
|
||||
|
||||
|
||||
AsynchronousValidationRequest impl = new AsynchronousValidationRequest(
|
||||
mockParent, mockClient, target, request, mockContext, mockCacheEntry,
|
||||
identifier);
|
||||
|
||||
|
||||
// response not used
|
||||
EasyMock.expect(
|
||||
mockClient.revalidateCacheEntry(target, request, mockContext,
|
||||
mockCacheEntry)).andThrow(new IOException());
|
||||
mockParent.markComplete(identifier);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.run();
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
public void replayMocks() {
|
||||
EasyMock.replay(mockClient);
|
||||
EasyMock.replay(mockContext);
|
||||
EasyMock.replay(mockCacheEntry);
|
||||
}
|
||||
|
||||
|
||||
public void verifyMocks() {
|
||||
EasyMock.verify(mockClient);
|
||||
EasyMock.verify(mockContext);
|
||||
|
|
|
@ -48,17 +48,17 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
public class TestAsynchronousValidator {
|
||||
|
||||
|
||||
private AsynchronousValidator impl;
|
||||
|
||||
|
||||
private CachingHttpClient mockClient;
|
||||
private HttpHost target;
|
||||
private HttpRequest request;
|
||||
private HttpContext mockContext;
|
||||
private HttpCacheEntry mockCacheEntry;
|
||||
|
||||
|
||||
private ExecutorService mockExecutor;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mockClient = EasyMock.createMock(CachingHttpClient.class);
|
||||
|
@ -66,138 +66,138 @@ public class TestAsynchronousValidator {
|
|||
request = new HttpGet("/");
|
||||
mockContext = EasyMock.createMock(HttpContext.class);
|
||||
mockCacheEntry = EasyMock.createMock(HttpCacheEntry.class);
|
||||
|
||||
|
||||
mockExecutor = EasyMock.createMock(ExecutorService.class);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRevalidateCacheEntrySchedulesExecutionAndPopulatesIdentifier() {
|
||||
impl = new AsynchronousValidator(mockClient, mockExecutor);
|
||||
|
||||
|
||||
EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
|
||||
mockExecutor.execute(EasyMock.isA(AsynchronousValidationRequest.class));
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
Assert.assertEquals(1, impl.getScheduledIdentifiers().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMarkCompleteRemovesIdentifier() {
|
||||
impl = new AsynchronousValidator(mockClient, mockExecutor);
|
||||
|
||||
|
||||
EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
|
||||
Capture<AsynchronousValidationRequest> cap = new Capture<AsynchronousValidationRequest>();
|
||||
mockExecutor.execute(EasyMock.capture(cap));
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
Assert.assertEquals(1, impl.getScheduledIdentifiers().size());
|
||||
|
||||
|
||||
impl.markComplete(cap.getValue().getIdentifier());
|
||||
|
||||
|
||||
Assert.assertEquals(0, impl.getScheduledIdentifiers().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRevalidateCacheEntryDoesNotPopulateIdentifierOnRejectedExecutionException() {
|
||||
impl = new AsynchronousValidator(mockClient, mockExecutor);
|
||||
|
||||
|
||||
EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
|
||||
mockExecutor.execute(EasyMock.isA(AsynchronousValidationRequest.class));
|
||||
EasyMock.expectLastCall().andThrow(new RejectedExecutionException());
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
Assert.assertEquals(0, impl.getScheduledIdentifiers().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRevalidateCacheEntryProperlyCollapsesRequest() {
|
||||
impl = new AsynchronousValidator(mockClient, mockExecutor);
|
||||
|
||||
|
||||
EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
|
||||
mockExecutor.execute(EasyMock.isA(AsynchronousValidationRequest.class));
|
||||
|
||||
|
||||
EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry);
|
||||
impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
Assert.assertEquals(1, impl.getScheduledIdentifiers().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testVariantsBothRevalidated() {
|
||||
impl = new AsynchronousValidator(mockClient, mockExecutor);
|
||||
|
||||
|
||||
HttpRequest req1 = new HttpGet("/");
|
||||
req1.addHeader(new BasicHeader("Accept-Encoding", "identity"));
|
||||
|
||||
|
||||
HttpRequest req2 = new HttpGet("/");
|
||||
req2.addHeader(new BasicHeader("Accept-Encoding", "gzip"));
|
||||
|
||||
|
||||
Header[] variantHeaders = new Header[] {
|
||||
new BasicHeader(HeaderConstants.VARY, "Accept-Encoding")
|
||||
};
|
||||
|
||||
|
||||
EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(true).times(2);
|
||||
EasyMock.expect(mockCacheEntry.getHeaders(HeaderConstants.VARY)).andReturn(variantHeaders).times(2);
|
||||
mockExecutor.execute(EasyMock.isA(AsynchronousValidationRequest.class));
|
||||
EasyMock.expectLastCall().times(2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.revalidateCacheEntry(target, req1, mockContext, mockCacheEntry);
|
||||
impl.revalidateCacheEntry(target, req2, mockContext, mockCacheEntry);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
Assert.assertEquals(2, impl.getScheduledIdentifiers().size());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRevalidateCacheEntryEndToEnd() throws ProtocolException, IOException {
|
||||
CacheConfig config = new CacheConfig();
|
||||
config.setAsynchronousWorkersMax(1);
|
||||
config.setAsynchronousWorkersCore(1);
|
||||
impl = new AsynchronousValidator(mockClient, config);
|
||||
|
||||
|
||||
EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
|
||||
EasyMock.expect(mockClient.revalidateCacheEntry(target, request, mockContext, mockCacheEntry)).andReturn(null);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry);
|
||||
|
||||
|
||||
try {
|
||||
// shut down backend executor and make sure all finishes properly, 1 second should be sufficient
|
||||
ExecutorService implExecutor = impl.getExecutor();
|
||||
implExecutor.shutdown();
|
||||
implExecutor.awaitTermination(1, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException ie) {
|
||||
|
||||
|
||||
} finally {
|
||||
verifyMocks();
|
||||
|
||||
|
||||
Assert.assertEquals(0, impl.getScheduledIdentifiers().size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void replayMocks() {
|
||||
EasyMock.replay(mockExecutor);
|
||||
EasyMock.replay(mockClient);
|
||||
EasyMock.replay(mockContext);
|
||||
EasyMock.replay(mockCacheEntry);
|
||||
}
|
||||
|
||||
|
||||
public void verifyMocks() {
|
||||
EasyMock.verify(mockExecutor);
|
||||
EasyMock.verify(mockClient);
|
||||
|
|
|
@ -94,7 +94,7 @@ public class TestCacheEntryUpdater {
|
|||
HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, entry,
|
||||
new Date(), new Date(), response);
|
||||
|
||||
|
||||
|
||||
Header[] updatedHeaders = updatedEntry.getAllHeaders();
|
||||
assertEquals(2, updatedHeaders.length);
|
||||
headersContain(updatedHeaders, "Date", formatDate(responseDate));
|
||||
|
@ -159,7 +159,7 @@ public class TestCacheEntryUpdater {
|
|||
new BasicHeader("Date", formatDate(oneSecondAgo)),
|
||||
new BasicHeader("ETag", "\"new-etag\"")
|
||||
};
|
||||
entry = HttpTestUtils.makeCacheEntry(twoSecondsAgo, now, headers);
|
||||
entry = HttpTestUtils.makeCacheEntry(twoSecondsAgo, now, headers);
|
||||
response.setHeader("Date", formatDate(tenSecondsAgo));
|
||||
response.setHeader("ETag", "\"old-etag\"");
|
||||
HttpCacheEntry result = impl.updateCacheEntry("A", entry, new Date(),
|
||||
|
@ -179,7 +179,7 @@ public class TestCacheEntryUpdater {
|
|||
assertEquals(twoSecondsAgo, updated.getRequestDate());
|
||||
assertEquals(oneSecondAgo, updated.getResponseDate());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void entry1xxWarningsAreRemovedOnUpdate() throws Exception {
|
||||
Header[] headers = {
|
||||
|
@ -195,7 +195,7 @@ public class TestCacheEntryUpdater {
|
|||
|
||||
assertEquals(0, updated.getHeaders("Warning").length);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void entryWithMalformedDateIsStillUpdated() throws Exception {
|
||||
Header[] headers = {
|
||||
|
@ -225,7 +225,7 @@ public class TestCacheEntryUpdater {
|
|||
|
||||
assertEquals("\"new\"", updated.getFirstHeader("ETag").getValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cannotUpdateFromANon304OriginResponse() throws Exception {
|
||||
entry = HttpTestUtils.makeCacheEntry();
|
||||
|
|
|
@ -71,7 +71,7 @@ public class TestCacheInvalidator {
|
|||
public void setUp() {
|
||||
now = new Date();
|
||||
tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||
|
||||
|
||||
host = new HttpHost("foo.example.com");
|
||||
mockStorage = createMock(HttpCacheStorage.class);
|
||||
cacheKeyGenerator = new CacheKeyGenerator();
|
||||
|
@ -265,7 +265,7 @@ public class TestCacheInvalidator {
|
|||
impl.flushInvalidatedCacheEntries(host, request);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotFlushForResponsesWithoutContentLocation()
|
||||
throws Exception {
|
||||
|
@ -273,7 +273,7 @@ public class TestCacheInvalidator {
|
|||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void flushesEntryIfFresherAndSpecifiedByContentLocation()
|
||||
throws Exception {
|
||||
|
@ -281,20 +281,20 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
new BasicHeader("ETag", "\"old-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
mockStorage.removeEntry(theURI);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotFlushEntryForUnsuccessfulResponse()
|
||||
throws Exception {
|
||||
|
@ -303,14 +303,14 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
new BasicHeader("ETag", "\"old-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
|
@ -323,15 +323,15 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String cacheKey = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", "http://foo.example.com/bar");
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
new BasicHeader("ETag", "\"old-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(cacheKey)).andReturn(entry).anyTimes();
|
||||
mockStorage.removeEntry(cacheKey);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
|
@ -344,15 +344,15 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String cacheKey = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", "/bar");
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
new BasicHeader("ETag", "\"old-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(cacheKey)).andReturn(entry).anyTimes();
|
||||
mockStorage.removeEntry(cacheKey);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
|
@ -365,21 +365,21 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String cacheKey = "http://baz.example.com:80/bar";
|
||||
response.setHeader("Content-Location", cacheKey);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
new BasicHeader("ETag", "\"old-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(cacheKey)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotFlushEntrySpecifiedByContentLocationIfEtagsMatch()
|
||||
throws Exception {
|
||||
|
@ -387,14 +387,14 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
new BasicHeader("ETag", "\"same-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
|
@ -407,19 +407,19 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(now)),
|
||||
new BasicHeader("ETag", "\"old-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotFlushEntryIfNotInCache()
|
||||
throws Exception {
|
||||
|
@ -427,14 +427,14 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(null).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotFlushEntrySpecifiedByContentLocationIfResponseHasNoEtag()
|
||||
throws Exception {
|
||||
|
@ -442,19 +442,19 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
new BasicHeader("ETag", "\"old-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotFlushEntrySpecifiedByContentLocationIfEntryHasNoEtag()
|
||||
throws Exception {
|
||||
|
@ -462,13 +462,13 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
|
@ -481,19 +481,19 @@ public class TestCacheInvalidator {
|
|||
response.removeHeaders("Date");
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("ETag", "\"old-etag\""),
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo)),
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotFlushEntrySpecifiedByContentLocationIfEntryHasNoDate()
|
||||
throws Exception {
|
||||
|
@ -501,13 +501,13 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("ETag", "\"old-etag\"")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
|
@ -520,19 +520,19 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", "blarg");
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("ETag", "\"old-etag\""),
|
||||
new BasicHeader("Date", formatDate(tenSecondsAgo))
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotFlushEntrySpecifiedByContentLocationIfEntryHasMalformedDate()
|
||||
throws Exception {
|
||||
|
@ -540,20 +540,20 @@ public class TestCacheInvalidator {
|
|||
response.setHeader("Date", formatDate(now));
|
||||
String theURI = "http://foo.example.com:80/bar";
|
||||
response.setHeader("Content-Location", theURI);
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
|
||||
new BasicHeader("ETag", "\"old-etag\""),
|
||||
new BasicHeader("Date", "foo")
|
||||
});
|
||||
|
||||
|
||||
expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.flushInvalidatedCacheEntries(host, request, response);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Expectations
|
||||
private void cacheEntryHasVariantMap(Map<String,String> variantMap) {
|
||||
expect(mockEntry.getVariantMap()).andReturn(variantMap);
|
||||
|
@ -572,4 +572,4 @@ public class TestCacheInvalidator {
|
|||
mockStorage.removeEntry(theUri);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -331,7 +331,7 @@ public class TestCacheValidityPolicy {
|
|||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||
assertFalse(impl.isRevalidatable(entry));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMissingContentLengthDoesntInvalidateEntry() {
|
||||
final int contentLength = 128;
|
||||
|
@ -339,7 +339,7 @@ public class TestCacheValidityPolicy {
|
|||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers, HttpTestUtils.getRandomBytes(contentLength));
|
||||
assertTrue(impl.contentLengthHeaderMatchesActualLength(entry));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCorrectContentLengthDoesntInvalidateEntry() {
|
||||
final int contentLength = 128;
|
||||
|
@ -347,7 +347,7 @@ public class TestCacheValidityPolicy {
|
|||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers, HttpTestUtils.getRandomBytes(contentLength));
|
||||
assertTrue(impl.contentLengthHeaderMatchesActualLength(entry));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testWrongContentLengthInvalidatesEntry() {
|
||||
final int contentLength = 128;
|
||||
|
@ -436,7 +436,7 @@ public class TestCacheValidityPolicy {
|
|||
HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
|
||||
assertTrue(impl.mayReturnStaleIfError(req, entry, now));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMayReturnStaleIfErrorInRequestIsTrueWithinStaleness(){
|
||||
Header[] headers = new Header[] {
|
||||
|
@ -475,15 +475,15 @@ public class TestCacheValidityPolicy {
|
|||
@Test
|
||||
public void testMayReturnStaleWhileRevalidatingIsFalseWhenDirectiveIsAbsent() {
|
||||
Date now = new Date();
|
||||
|
||||
|
||||
Header[] headers = new Header[] { new BasicHeader("Cache-control", "public") };
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
|
||||
|
||||
|
||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
||||
|
||||
|
||||
assertFalse(impl.mayReturnStaleWhileRevalidating(entry, now));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMayReturnStaleWhileRevalidatingIsTrueWhenWithinStaleness() {
|
||||
Date now = new Date();
|
||||
|
@ -493,12 +493,12 @@ public class TestCacheValidityPolicy {
|
|||
new BasicHeader("Cache-Control", "max-age=5, stale-while-revalidate=15")
|
||||
};
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
|
||||
|
||||
|
||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
||||
|
||||
|
||||
assertTrue(impl.mayReturnStaleWhileRevalidating(entry, now));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMayReturnStaleWhileRevalidatingIsFalseWhenPastStaleness() {
|
||||
Date now = new Date();
|
||||
|
@ -508,12 +508,12 @@ public class TestCacheValidityPolicy {
|
|||
new BasicHeader("Cache-Control", "max-age=5, stale-while-revalidate=15")
|
||||
};
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
|
||||
|
||||
|
||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
||||
|
||||
|
||||
assertFalse(impl.mayReturnStaleWhileRevalidating(entry, now));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMayReturnStaleWhileRevalidatingIsFalseWhenDirectiveEmpty() {
|
||||
Date now = new Date();
|
||||
|
@ -523,9 +523,9 @@ public class TestCacheValidityPolicy {
|
|||
new BasicHeader("Cache-Control", "max-age=5, stale-while-revalidate=")
|
||||
};
|
||||
HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
|
||||
|
||||
|
||||
CacheValidityPolicy impl = new CacheValidityPolicy();
|
||||
|
||||
|
||||
assertFalse(impl.mayReturnStaleWhileRevalidating(entry, now));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,4 +260,4 @@ public class TestCachedResponseSuitabilityChecker {
|
|||
|
||||
Assert.assertTrue(impl.canCachedResponseBeUsed(host, request, entry, now));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -203,16 +203,16 @@ public class TestCachingHttpClient {
|
|||
@Test
|
||||
public void testCacheableResponsesGoIntoCache() throws Exception {
|
||||
impl = new CachingHttpClient(mockBackend);
|
||||
|
||||
|
||||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control","max-age=3600");
|
||||
|
||||
|
||||
expect(mockBackend.execute(isA(HttpHost.class), isA(HttpRequest.class),
|
||||
(HttpContext)isNull())).andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
|
@ -224,7 +224,7 @@ public class TestCachingHttpClient {
|
|||
impl = new CachingHttpClient(mockBackend);
|
||||
Date now = new Date();
|
||||
Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L);
|
||||
|
||||
|
||||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Date", DateUtils.formatDate(now));
|
||||
|
@ -233,7 +233,7 @@ public class TestCachingHttpClient {
|
|||
|
||||
expect(mockBackend.execute(isA(HttpHost.class), isA(HttpRequest.class),
|
||||
(HttpContext)isNull())).andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control","no-cache");
|
||||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
|
@ -260,7 +260,7 @@ public class TestCachingHttpClient {
|
|||
impl = new CachingHttpClient(mockBackend);
|
||||
Date now = new Date();
|
||||
Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L);
|
||||
|
||||
|
||||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Date", DateUtils.formatDate(fiveSecondsAgo));
|
||||
|
@ -269,7 +269,7 @@ public class TestCachingHttpClient {
|
|||
|
||||
expect(mockBackend.execute(isA(HttpHost.class), isA(HttpRequest.class),
|
||||
(HttpContext)isNull())).andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control","max-age=0");
|
||||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
|
@ -486,7 +486,7 @@ public class TestCachingHttpClient {
|
|||
impl = new CachingHttpClient(mockBackend,
|
||||
new BasicHttpCache(new HeapResourceFactory(), mockStorage, config),
|
||||
config);
|
||||
|
||||
|
||||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control","no-cache");
|
||||
|
@ -1012,8 +1012,8 @@ public class TestCachingHttpClient {
|
|||
resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo));
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1048,8 +1048,8 @@ public class TestCachingHttpClient {
|
|||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
|
@ -1088,8 +1088,8 @@ public class TestCachingHttpClient {
|
|||
.formatDate(tenSecondsAfter));
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1).times(2);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1116,8 +1116,8 @@ public class TestCachingHttpClient {
|
|||
resp1.setHeader("Cache-Control", "public, max-age=3600");
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1147,12 +1147,12 @@ public class TestCachingHttpClient {
|
|||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp2);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1185,8 +1185,8 @@ public class TestCachingHttpClient {
|
|||
req2.addHeader("If-Modified-Since", DateUtils.formatDate(now));
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1217,12 +1217,12 @@ public class TestCachingHttpClient {
|
|||
resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo));
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1432,13 +1432,13 @@ public class TestCachingHttpClient {
|
|||
resp2.setHeader("Date", DateUtils.formatDate(now));
|
||||
resp2.setHeader("Cache-Control", "public, max-age=5");
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp2);
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
|
@ -1476,13 +1476,13 @@ public class TestCachingHttpClient {
|
|||
resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo));
|
||||
resp2.setHeader("Cache-Control", "public, max-age=5");
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp2);
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
|
@ -1520,13 +1520,13 @@ public class TestCachingHttpClient {
|
|||
resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo));
|
||||
resp2.setHeader("Cache-Control", "public, max-age=5");
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp2);
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
|
@ -1565,13 +1565,13 @@ public class TestCachingHttpClient {
|
|||
resp1.setHeader("Last-Modified", DateUtils.formatDate(now));
|
||||
resp2.setHeader("Cache-Control", "public, max-age=5");
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp2);
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
|
@ -1628,18 +1628,18 @@ public class TestCachingHttpClient {
|
|||
resp3.setHeader("Cache-Control", "public, max-age=3600");
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp2);
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp3);
|
||||
|
||||
|
||||
|
@ -1702,18 +1702,18 @@ public class TestCachingHttpClient {
|
|||
resp4.setHeader("Cache-Control", "public, max-age=3600");
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp1);
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp2);
|
||||
|
||||
expect(
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
mockBackend.execute(isA(HttpHost.class),
|
||||
isA(HttpRequest.class), (HttpContext)
|
||||
isNull())).andReturn(resp4);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1744,7 +1744,7 @@ public class TestCachingHttpClient {
|
|||
mockCache.flushInvalidatedCacheEntriesFor(host, request);
|
||||
expectLastCall().andThrow(new IOException()).anyTimes();
|
||||
mockCache.flushInvalidatedCacheEntriesFor(isA(HttpHost.class), isA(HttpRequest.class), isA(HttpResponse.class));
|
||||
expectLastCall().anyTimes();
|
||||
expectLastCall().anyTimes();
|
||||
expect(mockCache.getCacheEntry(same(host),
|
||||
isA(HttpRequest.class)))
|
||||
.andThrow(new IOException()).anyTimes();
|
||||
|
@ -1853,7 +1853,7 @@ public class TestCachingHttpClient {
|
|||
expect(mockValidityPolicy.isRevalidatable(
|
||||
(HttpCacheEntry)anyObject())).andReturn(b);
|
||||
}
|
||||
|
||||
|
||||
private void cacheEntryMustRevalidate(boolean b) {
|
||||
expect(mockValidityPolicy.mustRevalidate(mockCacheEntry))
|
||||
.andReturn(b);
|
||||
|
@ -1863,7 +1863,7 @@ public class TestCachingHttpClient {
|
|||
expect(mockValidityPolicy.proxyRevalidate(mockCacheEntry))
|
||||
.andReturn(b);
|
||||
}
|
||||
|
||||
|
||||
private void mayReturnStaleWhileRevalidating(boolean b) {
|
||||
expect(mockValidityPolicy.mayReturnStaleWhileRevalidating(
|
||||
(HttpCacheEntry)anyObject(), (Date)anyObject())).andReturn(b);
|
||||
|
|
|
@ -54,12 +54,12 @@ public class TestHttpCacheEntrySerializers {
|
|||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
private HttpCacheEntrySerializer impl;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
impl = new DefaultHttpCacheEntrySerializer();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void canSerializeEntriesWithVariantMaps() throws Exception {
|
||||
readWriteVerify(makeCacheEntryWithVariantMap());
|
||||
|
@ -96,7 +96,7 @@ public class TestHttpCacheEntrySerializers {
|
|||
|
||||
return cacheEntry;
|
||||
}
|
||||
|
||||
|
||||
private boolean areEqual(HttpCacheEntry one, HttpCacheEntry two) throws IOException {
|
||||
// dates are only stored with second precision, so scrub milliseconds
|
||||
if (!((one.getRequestDate().getTime() / 1000) == (two.getRequestDate()
|
||||
|
|
|
@ -363,4 +363,4 @@ public class TestProtocolDeviations {
|
|||
Assert.assertSame(originResponse, result);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
private Date now;
|
||||
private Date tenSecondsAgo;
|
||||
private Date twoMinutesAgo;
|
||||
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
@ -76,7 +76,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
twoMinutesAgo = new Date(now.getTime() - 2 * 60 * 1000L);
|
||||
tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
|
||||
}
|
||||
|
||||
|
||||
/* "identity: The default (identity) encoding; the use of no
|
||||
* transformation whatsoever. This content-coding is used only in the
|
||||
* Accept-Encoding header, and SHOULD NOT be used in the
|
||||
|
@ -107,7 +107,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
* "304 Not Modified. ... If the conditional GET used a strong cache
|
||||
* validator (see section 13.3.3), the response SHOULD NOT include
|
||||
* other entity-headers."
|
||||
*
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
|
||||
*/
|
||||
private void cacheGenerated304ForValidatorShouldNotContainEntityHeader(
|
||||
|
@ -119,29 +119,29 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Cache-Control","max-age=3600");
|
||||
resp1.setHeader(validatorHeader, validator);
|
||||
resp1.setHeader(headerName, headerValue);
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader(conditionalHeader, validator);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
HttpResponse result = impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
if (HttpStatus.SC_NOT_MODIFIED == result.getStatusLine().getStatusCode()) {
|
||||
assertNull(result.getFirstHeader(headerName));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void cacheGenerated304ForStrongETagValidatorShouldNotContainEntityHeader(
|
||||
String headerName, String headerValue) throws Exception,
|
||||
IOException {
|
||||
cacheGenerated304ForValidatorShouldNotContainEntityHeader(headerName,
|
||||
headerValue, "ETag", "\"etag\"", "If-None-Match");
|
||||
}
|
||||
|
||||
|
||||
private void cacheGenerated304ForStrongDateValidatorShouldNotContainEntityHeader(
|
||||
String headerName, String headerValue) throws Exception,
|
||||
IOException {
|
||||
|
@ -149,28 +149,28 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
headerValue, "Last-Modified", formatDate(twoMinutesAgo),
|
||||
"If-Modified-Since");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongEtagValidatorShouldNotContainAllow()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongETagValidatorShouldNotContainEntityHeader(
|
||||
"Allow", "GET,HEAD");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongDateValidatorShouldNotContainAllow()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongDateValidatorShouldNotContainEntityHeader(
|
||||
"Allow", "GET,HEAD");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongEtagValidatorShouldNotContainContentEncoding()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongETagValidatorShouldNotContainEntityHeader(
|
||||
"Content-Encoding", "gzip");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongDateValidatorShouldNotContainContentEncoding()
|
||||
throws Exception {
|
||||
|
@ -184,7 +184,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
cacheGenerated304ForStrongETagValidatorShouldNotContainEntityHeader(
|
||||
"Content-Language", "en");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongDateValidatorShouldNotContainContentLanguage()
|
||||
throws Exception {
|
||||
|
@ -198,21 +198,21 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
cacheGenerated304ForStrongETagValidatorShouldNotContainEntityHeader(
|
||||
"Content-Length", "128");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongDateValidatorShouldNotContainContentLength()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongDateValidatorShouldNotContainEntityHeader(
|
||||
"Content-Length", "128");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongValidatorShouldNotContainContentMD5()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongETagValidatorShouldNotContainEntityHeader(
|
||||
"Content-MD5", "Q2hlY2sgSW50ZWdyaXR5IQ==");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongDateValidatorShouldNotContainContentMD5()
|
||||
throws Exception {
|
||||
|
@ -229,9 +229,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Cache-Control","max-age=3600");
|
||||
resp1.setHeader(validatorHeader, validator);
|
||||
resp1.setHeader("Content-Range", "bytes 0-127/256");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("If-Range", validator);
|
||||
req2.setHeader("Range","bytes=0-127");
|
||||
|
@ -240,67 +240,67 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified");
|
||||
resp2.setHeader("Date", formatDate(now));
|
||||
resp2.setHeader(validatorHeader, validator);
|
||||
|
||||
|
||||
// cache module does not currently deal with byte ranges, but we want
|
||||
// this test to work even if it does some day
|
||||
Capture<HttpRequest> cap = new Capture<HttpRequest>();
|
||||
expect(mockBackend.execute(same(host), capture(cap), (HttpContext)isNull()))
|
||||
.andReturn(resp2).times(0,1);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
HttpResponse result = impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
if (!cap.hasCaptured()
|
||||
&& HttpStatus.SC_NOT_MODIFIED == result.getStatusLine().getStatusCode()) {
|
||||
// cache generated a 304
|
||||
assertNull(result.getFirstHeader("Content-Range"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongEtagValidatorShouldNotContainContentRange()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongValidatorShouldNotContainContentRange(
|
||||
"ETag", "\"etag\"", "If-None-Match");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongDateValidatorShouldNotContainContentRange()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongValidatorShouldNotContainContentRange(
|
||||
"Last-Modified", formatDate(twoMinutesAgo), "If-Modified-Since");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongEtagValidatorShouldNotContainContentType()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongETagValidatorShouldNotContainEntityHeader(
|
||||
"Content-Type", "text/html");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongDateValidatorShouldNotContainContentType()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongDateValidatorShouldNotContainEntityHeader(
|
||||
"Content-Type", "text/html");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongEtagValidatorShouldNotContainLastModified()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongETagValidatorShouldNotContainEntityHeader(
|
||||
"Last-Modified", formatDate(tenSecondsAgo));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheGenerated304ForStrongDateValidatorShouldNotContainLastModified()
|
||||
throws Exception {
|
||||
cacheGenerated304ForStrongDateValidatorShouldNotContainEntityHeader(
|
||||
"Last-Modified", formatDate(twoMinutesAgo));
|
||||
}
|
||||
|
||||
|
||||
private void shouldStripEntityHeaderFromOrigin304ResponseToStrongValidation(
|
||||
String entityHeader, String entityHeaderValue) throws Exception,
|
||||
IOException {
|
||||
|
@ -311,23 +311,23 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp.setHeader("Date", formatDate(now));
|
||||
resp.setHeader("Etag", "\"etag\"");
|
||||
resp.setHeader(entityHeader, entityHeaderValue);
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp);
|
||||
|
||||
|
||||
replayMocks();
|
||||
HttpResponse result = impl.execute(host, req);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertNull(result.getFirstHeader(entityHeader));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldStripAllowFromOrigin304ResponseToStrongValidation()
|
||||
throws Exception {
|
||||
shouldStripEntityHeaderFromOrigin304ResponseToStrongValidation(
|
||||
"Allow", "GET,HEAD");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldStripContentEncodingFromOrigin304ResponseToStrongValidation()
|
||||
throws Exception {
|
||||
|
@ -341,14 +341,14 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
shouldStripEntityHeaderFromOrigin304ResponseToStrongValidation(
|
||||
"Content-Language", "en");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldStripContentLengthFromOrigin304ResponseToStrongValidation()
|
||||
throws Exception {
|
||||
shouldStripEntityHeaderFromOrigin304ResponseToStrongValidation(
|
||||
"Content-Length", "128");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldStripContentMD5FromOrigin304ResponseToStrongValidation()
|
||||
throws Exception {
|
||||
|
@ -362,35 +362,35 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
shouldStripEntityHeaderFromOrigin304ResponseToStrongValidation(
|
||||
"Content-Type", "text/html;charset=utf-8");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldStripContentRangeFromOrigin304ResponseToStringValidation()
|
||||
throws Exception {
|
||||
HttpRequest req = HttpTestUtils.makeDefaultRequest();
|
||||
req.setHeader("If-Range","\"etag\"");
|
||||
req.setHeader("Range","bytes=0-127");
|
||||
|
||||
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified");
|
||||
resp.setHeader("Date", formatDate(now));
|
||||
resp.setHeader("ETag", "\"etag\"");
|
||||
resp.setHeader("Content-Range", "bytes 0-127/256");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp);
|
||||
|
||||
|
||||
replayMocks();
|
||||
HttpResponse result = impl.execute(host, req);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertNull(result.getFirstHeader("Content-Range"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldStripLastModifiedFromOrigin304ResponseToStrongValidation()
|
||||
throws Exception {
|
||||
shouldStripEntityHeaderFromOrigin304ResponseToStrongValidation(
|
||||
"Last-Modified", formatDate(twoMinutesAgo));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "For this reason, a cache SHOULD NOT return a stale response if the
|
||||
* client explicitly requests a first-hand or fresh one, unless it is
|
||||
|
@ -616,7 +616,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
|
||||
assertEquals(warning, result.getFirstHeader("Warning").getValue());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "A transparent proxy SHOULD NOT modify an end-to-end header unless
|
||||
* the definition of that header requires or specifically allows that."
|
||||
|
@ -1175,7 +1175,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
}
|
||||
assertTrue(foundEtag1 && foundEtag2);
|
||||
}
|
||||
|
||||
|
||||
/* "If the entity-tag of the new response matches that of an existing
|
||||
* entry, the new response SHOULD be used to update the header fields
|
||||
* of the existing entry, and the result MUST be returned to the
|
||||
|
@ -1237,7 +1237,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
assertEquals(formatDate(now), result1.getFirstHeader("Date").getValue());
|
||||
assertEquals(formatDate(now), result2.getFirstHeader("Date").getValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testResponseToExistingVariantsIsCachedForFutureResponses()
|
||||
throws Exception {
|
||||
|
@ -1279,7 +1279,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
* for the associated entity, its entity-tag SHOULD NOT be included in
|
||||
* the If-None-Match header field unless the request is for a range
|
||||
* that would be fully satisfied by that entry."
|
||||
*
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
|
||||
*/
|
||||
@Test
|
||||
|
@ -1291,9 +1291,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Cache-Control", "max-age=3600");
|
||||
resp1.setHeader("Vary", "User-Agent");
|
||||
resp1.setHeader("ETag", "\"etag1\"");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("User-Agent", "agent2");
|
||||
req2.setHeader("Range", "bytes=0-49");
|
||||
|
@ -1306,27 +1306,27 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp2.setHeader("ETag", "\"etag2\"");
|
||||
resp2.setHeader("Cache-Control","max-age=3600");
|
||||
resp2.setHeader("Date", formatDate(new Date()));
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
HttpRequest req3 = HttpTestUtils.makeDefaultRequest();
|
||||
req3.setHeader("User-Agent", "agent3");
|
||||
|
||||
|
||||
HttpResponse resp3 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control", "max-age=3600");
|
||||
resp1.setHeader("Vary", "User-Agent");
|
||||
resp1.setHeader("ETag", "\"etag3\"");
|
||||
|
||||
|
||||
Capture<HttpRequest> cap = new Capture<HttpRequest>();
|
||||
expect(mockBackend.execute(isA(HttpHost.class), capture(cap),
|
||||
(HttpContext)isNull())).andReturn(resp3);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
impl.execute(host, req3);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
HttpRequest captured = cap.getValue();
|
||||
for(Header h : captured.getHeaders("If-None-Match")) {
|
||||
for(HeaderElement elt : h.getElements()) {
|
||||
|
@ -1334,15 +1334,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* "If a cache receives a successful response whose Content-Location
|
||||
* field matches that of an existing cache entry for the same Request-
|
||||
* URI, whose entity-tag differs from that of the existing entry, and
|
||||
* whose Date is more recent than that of the existing entry, the
|
||||
* existing entry SHOULD NOT be returned in response to future requests
|
||||
* and SHOULD be deleted from the cache.
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
|
||||
*/
|
||||
@Test
|
||||
public void cachedEntryShouldNotBeUsedIfMoreRecentMentionInContentLocation()
|
||||
|
@ -1352,34 +1352,34 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Cache-Control","max-age=3600");
|
||||
resp1.setHeader("ETag", "\"old-etag\"");
|
||||
resp1.setHeader("Date", formatDate(tenSecondsAgo));
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = new HttpGet("http://foo.example.com/bar");
|
||||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
resp2.setHeader("ETag", "\"new-etag\"");
|
||||
resp2.setHeader("Date", formatDate(now));
|
||||
resp2.setHeader("Content-Location", "http://foo.example.com/");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
HttpRequest req3 = new HttpGet("http://foo.example.com");
|
||||
HttpResponse resp3 = HttpTestUtils.make200Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp3);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
impl.execute(host, req3);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "This specifically means that responses from HTTP/1.0 servers for such
|
||||
* URIs [those containing a '?' in the rel_path part] SHOULD NOT be taken
|
||||
* from a cache."
|
||||
*
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.9
|
||||
*/
|
||||
@Test
|
||||
|
@ -1391,23 +1391,23 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Content-Length","200");
|
||||
resp1.setHeader("Date", formatDate(now));
|
||||
resp1.setHeader("Expires", formatDate(tenSecondsFromNow));
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = new HttpGet("http://foo.example.com/bar?baz=quux");
|
||||
HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
|
||||
resp2.setEntity(HttpTestUtils.makeBody(200));
|
||||
resp2.setHeader("Content-Length","200");
|
||||
resp2.setHeader("Date", formatDate(now));
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void responseToGetWithQueryFrom1_0OriginVia1_1ProxyIsNotCached()
|
||||
throws Exception {
|
||||
|
@ -1418,18 +1418,18 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Date", formatDate(now));
|
||||
resp1.setHeader("Expires", formatDate(tenSecondsFromNow));
|
||||
resp1.setHeader("Via","1.0 someproxy");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = new HttpGet("http://foo.example.com/bar?baz=quux");
|
||||
HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
|
||||
resp2.setEntity(HttpTestUtils.makeBody(200));
|
||||
resp2.setHeader("Content-Length","200");
|
||||
resp2.setHeader("Date", formatDate(now));
|
||||
resp2.setHeader("Via","1.0 someproxy");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
|
@ -1440,7 +1440,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
* "A cache that passes through requests for methods it does not
|
||||
* understand SHOULD invalidate any entities referred to by the
|
||||
* Request-URI."
|
||||
*
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.10
|
||||
*/
|
||||
@Test
|
||||
|
@ -1449,30 +1449,30 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control","max-age=3600");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = new BasicHttpRequest("FROB", "/", HttpVersion.HTTP_1_1);
|
||||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
resp2.setHeader("Cache-Control","max-age=3600");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
HttpResponse resp3 = HttpTestUtils.make200Response();
|
||||
resp3.setHeader("ETag", "\"etag\"");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp3);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
HttpResponse result = impl.execute(host, req3);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(resp3, result));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldInvalidateAllVariantsForUnknownMethod()
|
||||
throws Exception {
|
||||
|
@ -1481,7 +1481,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control","max-age=3600");
|
||||
resp1.setHeader("Vary", "User-Agent");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
|
@ -1489,30 +1489,30 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
resp2.setHeader("Cache-Control","max-age=3600");
|
||||
resp2.setHeader("Vary", "User-Agent");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
HttpRequest req3 = new BasicHttpRequest("FROB", "/", HttpVersion.HTTP_1_1);
|
||||
req3.setHeader("User-Agent", "agent3");
|
||||
HttpResponse resp3 = HttpTestUtils.make200Response();
|
||||
resp3.setHeader("Cache-Control","max-age=3600");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp3);
|
||||
|
||||
|
||||
HttpRequest req4 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
req4.setHeader("User-Agent", "agent1");
|
||||
HttpResponse resp4 = HttpTestUtils.make200Response();
|
||||
resp4.setHeader("ETag", "\"etag1\"");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp4);
|
||||
|
||||
HttpRequest req5 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
req5.setHeader("User-Agent", "agent2");
|
||||
HttpResponse resp5 = HttpTestUtils.make200Response();
|
||||
resp5.setHeader("ETag", "\"etag2\"");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp5);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
|
@ -1520,7 +1520,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
HttpResponse result4 = impl.execute(host, req4);
|
||||
HttpResponse result5 = impl.execute(host, req5);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(resp4, result4));
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(resp5, result5));
|
||||
}
|
||||
|
@ -1529,7 +1529,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
* "If a new cacheable response is received from a resource while any
|
||||
* existing responses for the same resource are cached, the cache
|
||||
* SHOULD use the new response to reply to the current request."
|
||||
*
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.12
|
||||
*/
|
||||
@Test
|
||||
|
@ -1540,29 +1540,29 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Date", formatDate(tenSecondsAgo));
|
||||
resp1.setHeader("Cache-Control", "max-age=3600");
|
||||
resp1.setHeader("ETag", "\"etag1\"");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control", "max-age=0");
|
||||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
resp2.setHeader("Date", formatDate(now));
|
||||
resp2.setHeader("Cache-Control", "max-age=3600");
|
||||
resp2.setHeader("ETag", "\"etag2\"");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
HttpRequest req3 = HttpTestUtils.makeDefaultRequest();
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
HttpResponse result = impl.execute(host, req3);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "Many HTTP/1.0 cache implementations will treat an Expires value
|
||||
* that is less than or equal to the response Date value as being
|
||||
|
@ -1571,7 +1571,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
* does not include a Cache-Control header field, it SHOULD consider
|
||||
* the response to be non-cacheable in order to retain compatibility
|
||||
* with HTTP/1.0 servers."
|
||||
*
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3
|
||||
*/
|
||||
@Test
|
||||
|
@ -1582,24 +1582,24 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Date", formatDate(now));
|
||||
resp1.setHeader("Expires", formatDate(now));
|
||||
resp1.removeHeaders("Cache-Control");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control", "max-stale=1000");
|
||||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
resp2.setHeader("ETag", "\"etag2\"");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
HttpResponse result = impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void expiresPriorToDateWithNoCacheControlIsNotCacheable()
|
||||
throws Exception {
|
||||
|
@ -1608,28 +1608,28 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
resp1.setHeader("Date", formatDate(now));
|
||||
resp1.setHeader("Expires", formatDate(tenSecondsAgo));
|
||||
resp1.removeHeaders("Cache-Control");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control", "max-stale=1000");
|
||||
HttpResponse resp2 = HttpTestUtils.make200Response();
|
||||
resp2.setHeader("ETag", "\"etag2\"");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
HttpResponse result = impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
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
|
||||
|
@ -1638,15 +1638,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
req1.setHeader("Cache-Control", "min-fresh=10, no-cache");
|
||||
req1.addHeader("Cache-Control", "max-stale=0, max-age=0");
|
||||
|
||||
|
||||
Capture<HttpRequest> cap = new Capture<HttpRequest>();
|
||||
expect(mockBackend.execute(same(host), capture(cap), (HttpContext)isNull()))
|
||||
.andReturn(HttpTestUtils.make200Response());
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
HttpRequest captured = cap.getValue();
|
||||
boolean foundNoCache = false;
|
||||
boolean foundDisallowedDirective = false;
|
||||
|
@ -1665,14 +1665,14 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
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
|
||||
* respond using a cached entry that is consistent with the other
|
||||
* constraints of the request, or respond with a 504 (Gateway Timeout)
|
||||
* status."
|
||||
*
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
|
||||
*/
|
||||
@Test
|
||||
|
@ -1680,35 +1680,35 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
throws Exception {
|
||||
HttpRequest req = HttpTestUtils.makeDefaultRequest();
|
||||
req.setHeader("Cache-Control", "only-if-cached");
|
||||
|
||||
|
||||
replayMocks();
|
||||
HttpResponse result = impl.execute(host, req);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT,
|
||||
result.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheHitOkWithOnlyIfCached()
|
||||
throws Exception {
|
||||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control","max-age=3600");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control", "only-if-cached");
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
HttpResponse result = impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returns504ForStaleEntryWithOnlyIfCached()
|
||||
throws Exception {
|
||||
|
@ -1716,21 +1716,21 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Date", formatDate(tenSecondsAgo));
|
||||
resp1.setHeader("Cache-Control","max-age=5");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control", "only-if-cached");
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
HttpResponse result = impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT,
|
||||
result.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsStaleCacheEntryWithOnlyIfCachedAndMaxStale()
|
||||
throws Exception {
|
||||
|
@ -1739,18 +1739,18 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Date", formatDate(tenSecondsAgo));
|
||||
resp1.setHeader("Cache-Control","max-age=5");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control", "max-stale=20, only-if-cached");
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
HttpResponse result = impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -5836,4 +5836,4 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
Assert.assertTrue(warningHeaders == null || warningHeaders.length == 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,26 +38,26 @@ import org.apache.http.impl.cookie.DateUtils;
|
|||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
/**
|
||||
* A suite of acceptance tests for compliance with RFC5861, which
|
||||
* describes the stale-if-error and stale-while-revalidate
|
||||
* Cache-Control extensions.
|
||||
*/
|
||||
public class TestRFC5861Compliance extends AbstractProtocolTest {
|
||||
|
||||
/*
|
||||
/*
|
||||
* "The stale-if-error Cache-Control extension indicates that when an
|
||||
* error is encountered, a cached stale response MAY be used to satisfy
|
||||
* the request, regardless of other freshness information.When used as a
|
||||
* the request, regardless of other freshness information.When used as a
|
||||
* request Cache-Control extension, its scope of application is the request
|
||||
* it appears in; when used as a response Cache-Control extension, its
|
||||
* scope is any request applicable to the cached response in which it
|
||||
* it appears in; when used as a response Cache-Control extension, its
|
||||
* scope is any request applicable to the cached response in which it
|
||||
* occurs.Its value indicates the upper limit to staleness; when the cached
|
||||
* response is more stale than the indicated amount, the cached response
|
||||
* SHOULD NOT be used to satisfy the request, absent other information.
|
||||
* In this context, an error is any situation that would result in a
|
||||
* 500, 502, 503, or 504 HTTP response status code being returned."
|
||||
*
|
||||
*
|
||||
* http://tools.ietf.org/html/rfc5861
|
||||
*/
|
||||
@Test
|
||||
|
@ -67,22 +67,22 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||
"public, max-age=5, stale-if-error=60");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host,req1);
|
||||
HttpResponse result = impl.execute(host,req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
HttpTestUtils.assert110WarningFound(result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testStaleIfErrorInResponseYieldsToMustRevalidate()
|
||||
throws Exception{
|
||||
|
@ -90,22 +90,22 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||
"public, max-age=5, stale-if-error=60, must-revalidate");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host,req1);
|
||||
HttpResponse result = impl.execute(host,req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testStaleIfErrorInResponseYieldsToProxyRevalidateForSharedCache()
|
||||
throws Exception{
|
||||
|
@ -114,46 +114,46 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||
"public, max-age=5, stale-if-error=60, proxy-revalidate");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host,req1);
|
||||
HttpResponse result = impl.execute(host,req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testStaleIfErrorInResponseNeedNotYieldToProxyRevalidateForPrivateCache()
|
||||
throws Exception{
|
||||
CacheConfig config = new CacheConfig();
|
||||
config.setSharedCache(false);
|
||||
impl = new CachingHttpClient(mockBackend, config);
|
||||
|
||||
|
||||
Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
|
||||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||
"public, max-age=5, stale-if-error=60, proxy-revalidate");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host,req1);
|
||||
HttpResponse result = impl.execute(host,req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
HttpTestUtils.assert110WarningFound(result);
|
||||
}
|
||||
|
||||
|
@ -164,23 +164,23 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||
"public, max-age=5, stale-if-error=60");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control","min-fresh=2");
|
||||
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host,req1);
|
||||
HttpResponse result = impl.execute(host,req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testStaleIfErrorInRequestIsTrueReturnsStaleEntryWithWarning()
|
||||
throws Exception{
|
||||
|
@ -188,23 +188,23 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||
"public, max-age=5");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control","public, stale-if-error=60");
|
||||
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host,req1);
|
||||
HttpResponse result = impl.execute(host,req2);
|
||||
verifyMocks();
|
||||
|
||||
|
||||
HttpTestUtils.assert110WarningFound(result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testStaleIfErrorInResponseIsFalseReturnsError()
|
||||
throws Exception{
|
||||
|
@ -213,14 +213,14 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||
"public, max-age=5, stale-if-error=2");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host,req1);
|
||||
HttpResponse result = impl.execute(host,req2);
|
||||
|
@ -229,7 +229,7 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR,
|
||||
result.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testStaleIfErrorInRequestIsFalseReturnsError()
|
||||
throws Exception{
|
||||
|
@ -238,15 +238,15 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
|
||||
"public, max-age=5");
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = HttpTestUtils.makeDefaultRequest();
|
||||
req2.setHeader("Cache-Control","stale-if-error=2");
|
||||
HttpResponse resp2 = HttpTestUtils.make500Response();
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host,req1);
|
||||
HttpResponse result = impl.execute(host,req2);
|
||||
|
@ -255,22 +255,22 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR,
|
||||
result.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When present in an HTTP response, the stale-while-revalidate Cache-
|
||||
* Control extension indicates that caches MAY serve the response in
|
||||
* which it appears after it becomes stale, up to the indicated number
|
||||
* of seconds.
|
||||
*
|
||||
*
|
||||
* http://tools.ietf.org/html/rfc5861
|
||||
*/
|
||||
@Test
|
||||
public void testStaleWhileRevalidateReturnsStaleEntryWithWarning()
|
||||
throws Exception {
|
||||
|
||||
|
||||
params.setAsynchronousWorkersMax(1);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
|
||||
|
||||
HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
Date now = new Date();
|
||||
|
@ -300,15 +300,15 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
}
|
||||
assertTrue(warning110Found);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCanAlsoServeStale304sWhileRevalidating()
|
||||
throws Exception {
|
||||
|
||||
|
||||
params.setAsynchronousWorkersMax(1);
|
||||
params.setSharedCache(false);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
|
||||
|
||||
HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
Date now = new Date();
|
||||
|
@ -340,17 +340,17 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
assertTrue(warning110Found);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testStaleWhileRevalidateYieldsToMustRevalidate()
|
||||
throws Exception {
|
||||
|
||||
|
||||
Date now = new Date();
|
||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||
|
||||
|
||||
params.setAsynchronousWorkersMax(1);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
|
||||
|
||||
HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, must-revalidate");
|
||||
|
@ -364,7 +364,7 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, must-revalidate");
|
||||
resp2.setHeader("ETag","\"etag\"");
|
||||
resp2.setHeader("Date", DateUtils.formatDate(now));
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
replayMocks();
|
||||
|
@ -388,14 +388,14 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
@Test
|
||||
public void testStaleWhileRevalidateYieldsToProxyRevalidateForSharedCache()
|
||||
throws Exception {
|
||||
|
||||
|
||||
Date now = new Date();
|
||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||
|
||||
|
||||
params.setAsynchronousWorkersMax(1);
|
||||
params.setSharedCache(true);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
|
||||
|
||||
HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, proxy-revalidate");
|
||||
|
@ -409,7 +409,7 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, proxy-revalidate");
|
||||
resp2.setHeader("ETag","\"etag\"");
|
||||
resp2.setHeader("Date", DateUtils.formatDate(now));
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
replayMocks();
|
||||
|
@ -433,14 +433,14 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
@Test
|
||||
public void testStaleWhileRevalidateYieldsToExplicitFreshnessRequest()
|
||||
throws Exception {
|
||||
|
||||
|
||||
Date now = new Date();
|
||||
Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||
|
||||
|
||||
params.setAsynchronousWorkersMax(1);
|
||||
params.setSharedCache(true);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
|
||||
|
||||
HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
|
||||
HttpResponse resp1 = HttpTestUtils.make200Response();
|
||||
resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15");
|
||||
|
@ -455,7 +455,7 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15");
|
||||
resp2.setHeader("ETag","\"etag\"");
|
||||
resp2.setHeader("Date", DateUtils.formatDate(now));
|
||||
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
replayMocks();
|
||||
|
@ -475,5 +475,5 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
|
|||
}
|
||||
assertFalse(warning110Found);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -42,22 +42,22 @@ public class TestRequestProtocolCompliance {
|
|||
private RequestProtocolCompliance impl;
|
||||
private HttpRequest req;
|
||||
private HttpRequest result;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
req = HttpTestUtils.makeDefaultRequest();
|
||||
impl = new RequestProtocolCompliance();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotModifyACompliantRequest() throws Exception {
|
||||
result = impl.makeRequestCompliant(req);
|
||||
result = impl.makeRequestCompliant(req);
|
||||
assertTrue(HttpTestUtils.equivalent(req, result));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void removesEntityFromTRACERequest() throws Exception {
|
||||
HttpEntityEnclosingRequest req =
|
||||
HttpEntityEnclosingRequest req =
|
||||
new BasicHttpEntityEnclosingRequest("TRACE", "/", HttpVersion.HTTP_1_1);
|
||||
req.setEntity(HttpTestUtils.makeBody(50));
|
||||
result = impl.makeRequestCompliant(req);
|
||||
|
@ -65,7 +65,7 @@ public class TestRequestProtocolCompliance {
|
|||
assertNull(((HttpEntityEnclosingRequest)result).getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void upgrades1_0RequestTo1_1() throws Exception {
|
||||
req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_0);
|
||||
|
@ -80,7 +80,7 @@ public class TestRequestProtocolCompliance {
|
|||
result = impl.makeRequestCompliant(req);
|
||||
assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void stripsMinFreshFromRequestIfNoCachePresent()
|
||||
throws Exception {
|
||||
|
@ -107,7 +107,7 @@ public class TestRequestProtocolCompliance {
|
|||
assertEquals("no-cache",
|
||||
result.getFirstHeader("Cache-Control").getValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotStripMinFreshFromRequestWithoutNoCache()
|
||||
throws Exception {
|
||||
|
@ -116,7 +116,7 @@ public class TestRequestProtocolCompliance {
|
|||
assertEquals("min-fresh=10",
|
||||
result.getFirstHeader("Cache-Control").getValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void correctlyStripsMinFreshFromMiddleIfNoCache()
|
||||
throws Exception {
|
||||
|
|
|
@ -60,7 +60,7 @@ public class TestResponseCachingPolicy {
|
|||
now = new Date();
|
||||
sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
||||
tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
|
||||
|
||||
|
||||
policy = new ResponseCachingPolicy(0, true);
|
||||
request = new BasicHttpRequest("GET","/",HTTP_1_1);
|
||||
response = new BasicHttpResponse(
|
||||
|
@ -397,7 +397,7 @@ public class TestResponseCachingPolicy {
|
|||
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
|
||||
Assert.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithExpires() {
|
||||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
|
@ -406,7 +406,7 @@ public class TestResponseCachingPolicy {
|
|||
response.setHeader("Expires", formatDate(tenSecondsFromNow));
|
||||
Assert.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheable() {
|
||||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
|
@ -424,7 +424,7 @@ public class TestResponseCachingPolicy {
|
|||
response.setHeader("Via", "1.0 someproxy");
|
||||
Assert.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesAreNotCacheableEvenWithExpires() {
|
||||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
|
@ -443,7 +443,7 @@ public class TestResponseCachingPolicy {
|
|||
response.setHeader("Via", "1.1 someproxy");
|
||||
Assert.assertTrue(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void notCacheableIfExpiresEqualsDateAndNoCacheControl() {
|
||||
response.setHeader("Date", formatDate(now));
|
||||
|
|
|
@ -60,12 +60,12 @@ public class TestResponseProtocolCompliance {
|
|||
private static class Flag {
|
||||
public boolean set;
|
||||
}
|
||||
|
||||
|
||||
private void setMinimalResponseHeaders(HttpResponse resp) {
|
||||
resp.setHeader("Date", DateUtils.formatDate(new Date()));
|
||||
resp.setHeader("Server", "MyServer/1.0");
|
||||
}
|
||||
|
||||
|
||||
private ByteArrayInputStream makeTrackableBody(int nbytes, final Flag closed) {
|
||||
byte[] buf = HttpTestUtils.getRandomBytes(nbytes);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(buf) {
|
||||
|
@ -76,7 +76,7 @@ public class TestResponseProtocolCompliance {
|
|||
};
|
||||
return bais;
|
||||
}
|
||||
|
||||
|
||||
private HttpResponse makePartialResponse(int nbytes) {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
|
||||
setMinimalResponseHeaders(resp);
|
||||
|
@ -84,7 +84,7 @@ public class TestResponseProtocolCompliance {
|
|||
resp.setHeader("Content-Range","0-127/256");
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void consumesBodyIfOriginSendsOneInResponseToHEAD() throws Exception {
|
||||
HttpRequest req = new HttpHead("http://foo.example.com/");
|
||||
|
@ -96,7 +96,7 @@ public class TestResponseProtocolCompliance {
|
|||
final Flag closed = new Flag();
|
||||
ByteArrayInputStream bais = makeTrackableBody(nbytes, closed);
|
||||
resp.setEntity(new InputStreamEntity(bais, -1));
|
||||
|
||||
|
||||
impl.ensureProtocolCompliance(req, resp);
|
||||
assertNull(resp.getEntity());
|
||||
assertTrue(closed.set || bais.read() == -1);
|
||||
|
@ -108,7 +108,7 @@ public class TestResponseProtocolCompliance {
|
|||
int nbytes = 128;
|
||||
HttpResponse resp = makePartialResponse(nbytes);
|
||||
resp.setEntity(HttpTestUtils.makeBody(nbytes));
|
||||
|
||||
|
||||
impl.ensureProtocolCompliance(req, resp);
|
||||
}
|
||||
|
||||
|
@ -117,18 +117,18 @@ public class TestResponseProtocolCompliance {
|
|||
HttpRequest req = new HttpGet("http://foo.example.com/");
|
||||
int nbytes = 128;
|
||||
HttpResponse resp = makePartialResponse(nbytes);
|
||||
|
||||
|
||||
final Flag closed = new Flag();
|
||||
ByteArrayInputStream bais = makeTrackableBody(nbytes, closed);
|
||||
resp.setEntity(new InputStreamEntity(bais, -1));
|
||||
|
||||
|
||||
try {
|
||||
impl.ensureProtocolCompliance(req, resp);
|
||||
} catch (ClientProtocolException expected) {
|
||||
}
|
||||
assertTrue(closed.set || bais.read() == -1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void consumesBodyOf100ContinueResponseIfItArrives() throws Exception {
|
||||
HttpEntityEnclosingRequest req = new BasicHttpEntityEnclosingRequest("POST", "/", HttpVersion.HTTP_1_1);
|
||||
|
@ -137,12 +137,12 @@ public class TestResponseProtocolCompliance {
|
|||
req.setHeader("Content-Type", "application/octet-stream");
|
||||
HttpEntity postBody = new ByteArrayEntity(HttpTestUtils.getRandomBytes(nbytes));
|
||||
req.setEntity(postBody);
|
||||
|
||||
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_CONTINUE, "Continue");
|
||||
final Flag closed = new Flag();
|
||||
ByteArrayInputStream bais = makeTrackableBody(nbytes, closed);
|
||||
resp.setEntity(new InputStreamEntity(bais, -1));
|
||||
|
||||
|
||||
try {
|
||||
impl.ensureProtocolCompliance(req, resp);
|
||||
} catch (ClientProtocolException expected) {
|
||||
|
|
|
@ -78,4 +78,4 @@ public interface RedirectStrategy {
|
|||
HttpResponse response,
|
||||
HttpContext context) throws ProtocolException;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,4 @@ public interface ServiceUnavailableRetryStrategy {
|
|||
*/
|
||||
long getRetryInterval();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,4 +43,4 @@ public interface Idn {
|
|||
* @return the Unicode domain name
|
||||
*/
|
||||
String toUnicode(String punycode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,4 +72,4 @@ public class JdkIdn implements Idn {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,4 +123,4 @@ public class Rfc3492Idn implements Idn {
|
|||
return output.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,4 +49,4 @@ public interface DnsResolver {
|
|||
*/
|
||||
InetAddress[] resolve(String host) throws UnknownHostException;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,4 +59,4 @@ public interface ClientCookie extends Cookie {
|
|||
|
||||
boolean containsAttribute(String name);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ import org.apache.http.protocol.HttpContext;
|
|||
import org.apache.http.client.*;
|
||||
|
||||
/**
|
||||
* {@link HttpClient} implementation that can automatically retry the request in case of
|
||||
* {@link HttpClient} implementation that can automatically retry the request in case of
|
||||
* a non-2xx response using the {@link ServiceUnavailableRetryStrategy} interface.
|
||||
*
|
||||
* @since 4.2
|
||||
|
@ -174,4 +174,4 @@ public class AutoRetryHttpClient implements HttpClient {
|
|||
return backend.getParams();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,11 +110,11 @@ public class DefaultHttpRequestRetryHandler implements HttpRequestRetryHandler {
|
|||
|
||||
HttpRequest request = (HttpRequest)
|
||||
context.getAttribute(ExecutionContext.HTTP_REQUEST);
|
||||
|
||||
|
||||
if(requestIsAborted(request)){
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (handleAsIdempotent(request)) {
|
||||
// Retry if the request is considered idempotent
|
||||
return true;
|
||||
|
@ -154,7 +154,7 @@ public class DefaultHttpRequestRetryHandler implements HttpRequestRetryHandler {
|
|||
protected boolean handleAsIdempotent(final HttpRequest request) {
|
||||
return !(request instanceof HttpEntityEnclosingRequest);
|
||||
}
|
||||
|
||||
|
||||
protected boolean requestIsAborted(final HttpRequest request) {
|
||||
return (request instanceof HttpUriRequest && ((HttpUriRequest)request).isAborted());
|
||||
}
|
||||
|
|
|
@ -211,4 +211,4 @@ public class DefaultRedirectStrategy implements RedirectStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.apache.http.protocol.HttpContext;
|
|||
* Default implementation of the {@link ServiceUnavailableRetryStrategy} interface.
|
||||
* that retries <code>503</code> (Service Unavailable) responses for a fixed number of times
|
||||
* at a fixed interval.
|
||||
*
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
@Immutable
|
||||
|
|
|
@ -92,4 +92,4 @@ public class InMemoryDnsResolver implements DnsResolver {
|
|||
return resolvedAddresses;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,4 +218,4 @@ public class BestMatchSpec implements CookieSpec {
|
|||
return "best-match";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,4 +64,4 @@ public class RFC2965CommentUrlAttributeHandler implements CookieAttributeHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,4 +64,4 @@ public class RFC2965DiscardAttributeHandler implements CookieAttributeHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,4 +191,4 @@ public class RFC2965DomainAttributeHandler implements CookieAttributeHandler {
|
|||
return effectiveHostWithoutDomain.indexOf('.') == -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,4 +95,4 @@ public class RFC2965VersionAttributeHandler implements CookieAttributeHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -512,9 +512,9 @@ public class TestRequestAddCookies {
|
|||
// Test for ordering adapted from test in Commons HC 3.1
|
||||
public void testCookieOrder() throws Exception {
|
||||
HttpRequest request = new BasicHttpRequest("GET", "/foobar/yada/yada");
|
||||
|
||||
|
||||
this.cookieStore.clear();
|
||||
|
||||
|
||||
cookieStore.addCookie(makeCookie("nomatch", "value", "localhost.local", "/noway"));
|
||||
cookieStore.addCookie(makeCookie("name2", "value", "localhost.local", "/foobar/yada"));
|
||||
cookieStore.addCookie(makeCookie("name3", "value", "localhost.local", "/foobar"));
|
||||
|
|
|
@ -327,10 +327,10 @@ public class TestURIUtils {
|
|||
public void testHTTPCLIENT_911() throws Exception{
|
||||
Assert.assertEquals(new HttpHost("localhost"),URIUtils.extractHost(new URI("http://localhost/abcd")));
|
||||
Assert.assertEquals(new HttpHost("localhost"),URIUtils.extractHost(new URI("http://localhost/abcd%3A")));
|
||||
|
||||
|
||||
Assert.assertEquals(new HttpHost("local_host"),URIUtils.extractHost(new URI("http://local_host/abcd")));
|
||||
Assert.assertEquals(new HttpHost("local_host"),URIUtils.extractHost(new URI("http://local_host/abcd%3A")));
|
||||
|
||||
|
||||
Assert.assertEquals(new HttpHost("localhost",8),URIUtils.extractHost(new URI("http://localhost:8/abcd")));
|
||||
Assert.assertEquals(new HttpHost("local_host",8),URIUtils.extractHost(new URI("http://local_host:8/abcd")));
|
||||
|
||||
|
@ -345,5 +345,5 @@ public class TestURIUtils {
|
|||
Assert.assertEquals(new HttpHost("local_host",8080),URIUtils.extractHost(new URI("http://@local_host:8080/abcd")));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -207,4 +207,4 @@ public class TestURLEncodedUtils {
|
|||
Assert.assertEquals(parameter.getValue(), expectedValue);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ public class TestHostnameVerifier {
|
|||
|
||||
checkMatching(bhv, "s.a.b.c", cns, alt, false); // OK
|
||||
checkMatching(shv, "s.a.b.c", cns, alt, true); // subdomain not OK
|
||||
|
||||
|
||||
cns = new String []{};
|
||||
alt = new String []{"dummy", "*.b.c"}; // check matches against all alts
|
||||
checkMatching(bhv, "a.b.c", cns, alt, false); // OK
|
||||
|
@ -275,28 +275,28 @@ public class TestHostnameVerifier {
|
|||
|
||||
checkMatching(bhv, "s.a.b.c", cns, alt, false); // OK
|
||||
checkMatching(shv, "s.a.b.c", cns, alt, true); // subdomain not OK
|
||||
|
||||
|
||||
alt = new String []{"*.gov.uk"};
|
||||
checkMatching(bhv, "a.gov.uk", cns, alt, true); // Bad 2TLD
|
||||
checkMatching(shv, "a.gov.uk", cns, alt, true); // Bad 2TLD
|
||||
|
||||
checkMatching(bhv, "s.a.gov.uk", cns, alt, true); // Bad 2TLD
|
||||
checkMatching(shv, "s.a.gov.uk", cns, alt, true); // Bad 2TLD/no subdomain allowed
|
||||
|
||||
|
||||
alt = new String []{"*.gov.com"};
|
||||
checkMatching(bhv, "a.gov.com", cns, alt, false); // OK, gov not 2TLD here
|
||||
checkMatching(shv, "a.gov.com", cns, alt, false); // OK, gov not 2TLD here
|
||||
|
||||
checkMatching(bhv, "s.a.gov.com", cns, alt, false); // OK, gov not 2TLD here
|
||||
checkMatching(shv, "s.a.gov.com", cns, alt, true); // no subdomain allowed
|
||||
|
||||
|
||||
cns = new String []{"a*.gov.uk"}; // 2TLD check applies to wildcards
|
||||
checkMatching(bhv, "a.gov.uk", cns, alt, true); // Bad 2TLD
|
||||
checkMatching(shv, "a.gov.uk", cns, alt, true); // Bad 2TLD
|
||||
|
||||
checkMatching(bhv, "s.a.gov.uk", cns, alt, true); // Bad 2TLD
|
||||
checkMatching(shv, "s.a.gov.uk", cns, alt, true); // Bad 2TLD/no subdomain allowed
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -305,7 +305,7 @@ public class TestHostnameVerifier {
|
|||
String alt[] = {};
|
||||
X509HostnameVerifier bhv = new BrowserCompatHostnameVerifier();
|
||||
X509HostnameVerifier shv = new StrictHostnameVerifier();
|
||||
|
||||
|
||||
cns = new String []{"a*.b.c"}; // component part
|
||||
checkMatching(bhv, "a.b.c", cns, alt, false); // OK
|
||||
checkMatching(shv, "a.b.c", cns, alt, false); // OK
|
||||
|
@ -317,10 +317,10 @@ public class TestHostnameVerifier {
|
|||
checkWildcard("s*.gov.uk", false); // 2 character TLD, invalid 2TLD
|
||||
checkWildcard("s*.gouv.uk", false); // 2 character TLD, invalid 2TLD
|
||||
}
|
||||
|
||||
|
||||
// Helper
|
||||
private void checkWildcard(String host, boolean isOK) {
|
||||
Assert.assertTrue(host+" should be "+isOK, isOK==AbstractVerifier.acceptableCountryWildcard(host));
|
||||
Assert.assertTrue(host+" should be "+isOK, isOK==AbstractVerifier.acceptableCountryWildcard(host));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -28,11 +28,11 @@ package org.apache.http.impl.client;
|
|||
public class MockClock implements Clock {
|
||||
|
||||
private long t = System.currentTimeMillis();
|
||||
|
||||
|
||||
public long getCurrentTime() {
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
public void setCurrentTime(long now) {
|
||||
t = now;
|
||||
}
|
||||
|
|
|
@ -52,33 +52,33 @@ public class TestAIMDBackoffManager {
|
|||
impl = new AIMDBackoffManager(connPerRoute, clock);
|
||||
impl.setPerHostConnectionCap(10);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isABackoffManager() {
|
||||
assertTrue(impl instanceof BackoffManager);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void halvesConnectionsOnBackoff() {
|
||||
connPerRoute.setMaxForRoute(route, 4);
|
||||
impl.backOff(route);
|
||||
assertEquals(2, connPerRoute.getMaxForRoute(route));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotBackoffBelowOneConnection() {
|
||||
connPerRoute.setMaxForRoute(route, 1);
|
||||
impl.backOff(route);
|
||||
assertEquals(1, connPerRoute.getMaxForRoute(route));
|
||||
assertEquals(1, connPerRoute.getMaxForRoute(route));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void increasesByOneOnProbe() {
|
||||
connPerRoute.setMaxForRoute(route, 2);
|
||||
impl.probe(route);
|
||||
assertEquals(3, connPerRoute.getMaxForRoute(route));
|
||||
assertEquals(3, connPerRoute.getMaxForRoute(route));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotIncreaseBeyondPerHostMaxOnProbe() {
|
||||
connPerRoute.setDefaultMaxPerRoute(5);
|
||||
|
@ -87,7 +87,7 @@ public class TestAIMDBackoffManager {
|
|||
impl.probe(route);
|
||||
assertEquals(5, connPerRoute.getMaxForRoute(route));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void backoffDoesNotAdjustDuringCoolDownPeriod() {
|
||||
connPerRoute.setMaxForRoute(route, 4);
|
||||
|
@ -99,7 +99,7 @@ public class TestAIMDBackoffManager {
|
|||
impl.backOff(route);
|
||||
assertEquals(max, connPerRoute.getMaxForRoute(route));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void backoffStillAdjustsAfterCoolDownPeriod() {
|
||||
connPerRoute.setMaxForRoute(route, 8);
|
||||
|
@ -111,9 +111,9 @@ public class TestAIMDBackoffManager {
|
|||
impl.backOff(route);
|
||||
assertTrue(max == 1 || max > connPerRoute.getMaxForRoute(route));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void probeDoesNotAdjustDuringCooldownPeriod() {
|
||||
public void probeDoesNotAdjustDuringCooldownPeriod() {
|
||||
connPerRoute.setMaxForRoute(route, 4);
|
||||
long now = System.currentTimeMillis();
|
||||
clock.setCurrentTime(now);
|
||||
|
@ -135,7 +135,7 @@ public class TestAIMDBackoffManager {
|
|||
impl.probe(route);
|
||||
assertTrue(max < connPerRoute.getMaxForRoute(route));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void willBackoffImmediatelyEvenAfterAProbe() {
|
||||
connPerRoute.setMaxForRoute(route, 8);
|
||||
|
@ -147,7 +147,7 @@ public class TestAIMDBackoffManager {
|
|||
impl.backOff(route);
|
||||
assertTrue(connPerRoute.getMaxForRoute(route) < max);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void backOffFactorIsConfigurable() {
|
||||
connPerRoute.setMaxForRoute(route, 10);
|
||||
|
@ -155,7 +155,7 @@ public class TestAIMDBackoffManager {
|
|||
impl.backOff(route);
|
||||
assertEquals(9, connPerRoute.getMaxForRoute(route));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void coolDownPeriodIsConfigurable() {
|
||||
long cd = new Random().nextLong() / 2;
|
||||
|
|
|
@ -48,34 +48,34 @@ public class TestDefaultBackoffStrategy {
|
|||
public void setUp() {
|
||||
impl = new DefaultBackoffStrategy();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isABackoffStrategy() {
|
||||
assertTrue(impl instanceof ConnectionBackoffStrategy);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void backsOffForSocketTimeouts() {
|
||||
assertTrue(impl.shouldBackoff(new SocketTimeoutException()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void backsOffForConnectionTimeouts() {
|
||||
assertTrue(impl.shouldBackoff(new ConnectException()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotBackOffForConnectionManagerTimeout() {
|
||||
assertFalse(impl.shouldBackoff(new ConnectionPoolTimeoutException()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void backsOffForServiceUnavailable() {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1,
|
||||
HttpStatus.SC_SERVICE_UNAVAILABLE, "Service Unavailable");
|
||||
assertTrue(impl.shouldBackoff(resp));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotBackOffForNon503StatusCodes() {
|
||||
for(int i = 100; i <= 599; i++) {
|
||||
|
|
|
@ -40,73 +40,73 @@ import org.junit.Test;
|
|||
|
||||
|
||||
public class TestDefaultHttpRequestRetryHandler {
|
||||
|
||||
|
||||
@Test
|
||||
public void noRetryOnConnectTimeout() throws Exception {
|
||||
HttpContext context = mock(HttpContext.class);
|
||||
HttpUriRequest request = mock(HttpUriRequest.class);
|
||||
|
||||
|
||||
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
|
||||
Assert.assertEquals(3, retryHandler.getRetryCount());
|
||||
|
||||
|
||||
when(request.isAborted()).thenReturn(Boolean.FALSE);
|
||||
when(context.getAttribute(ExecutionContext.HTTP_REQUEST)).thenReturn(request);
|
||||
|
||||
|
||||
Assert.assertFalse(retryHandler.retryRequest(new ConnectTimeoutException(), 1, context));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void noRetryOnUnknownHost() throws Exception {
|
||||
HttpContext context = mock(HttpContext.class);
|
||||
HttpUriRequest request = mock(HttpUriRequest.class);
|
||||
|
||||
|
||||
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
|
||||
|
||||
|
||||
when(request.isAborted()).thenReturn(Boolean.FALSE);
|
||||
when(context.getAttribute(ExecutionContext.HTTP_REQUEST)).thenReturn(request);
|
||||
|
||||
|
||||
Assert.assertFalse(retryHandler.retryRequest(new UnknownHostException(), 1, context));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void noRetryOnAbortedRequests() throws Exception{
|
||||
HttpContext context = mock(HttpContext.class);
|
||||
HttpUriRequest request = mock(HttpUriRequest.class);
|
||||
|
||||
|
||||
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
|
||||
|
||||
|
||||
when(request.isAborted()).thenReturn(Boolean.TRUE);
|
||||
when(context.getAttribute(ExecutionContext.HTTP_REQUEST)).thenReturn(request);
|
||||
|
||||
|
||||
Assert.assertFalse(retryHandler.retryRequest(new IOException(),3,context));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void retryOnNonAbortedRequests() throws Exception{
|
||||
|
||||
|
||||
HttpContext context = mock(HttpContext.class);
|
||||
HttpUriRequest request = mock(HttpUriRequest.class);
|
||||
|
||||
|
||||
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
|
||||
|
||||
|
||||
when(request.isAborted()).thenReturn(Boolean.FALSE);
|
||||
when(context.getAttribute(ExecutionContext.HTTP_REQUEST)).thenReturn(request);
|
||||
|
||||
|
||||
Assert.assertTrue(retryHandler.retryRequest(new IOException(),3,context));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void noRetryOnConnectionTimeout() throws Exception{
|
||||
|
||||
|
||||
HttpContext context = mock(HttpContext.class);
|
||||
HttpUriRequest request = mock(HttpUriRequest.class);
|
||||
|
||||
|
||||
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
|
||||
|
||||
|
||||
when(request.isAborted()).thenReturn(false);
|
||||
when(context.getAttribute(ExecutionContext.HTTP_REQUEST)).thenReturn(request);
|
||||
|
||||
|
||||
Assert.assertFalse(retryHandler.retryRequest(new ConnectTimeoutException(),3,context));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,12 +43,12 @@ public class TestNullBackoffStrategy {
|
|||
public void setUp() {
|
||||
impl = new NullBackoffStrategy();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotBackoffForThrowables() {
|
||||
assertFalse(impl.shouldBackoff(new Exception()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotBackoffForResponses() {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1,
|
||||
|
|
|
@ -54,7 +54,7 @@ public class ConnPoolBench {
|
|||
oldPool(c, reps);
|
||||
newPool(c, reps);
|
||||
}
|
||||
|
||||
|
||||
public static void newPool(int c, long reps) throws Exception {
|
||||
Log log = LogFactory.getLog(ConnPoolBench.class);
|
||||
|
||||
|
|
|
@ -82,4 +82,4 @@ public class TestDefaultClientConnectOperator {
|
|||
return new InetAddress[] { InetAddress.getByAddress(byteIpAddress) };
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>${httpcore.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Not currently used
|
||||
|
|
|
@ -103,7 +103,7 @@ public class HttpMultipart {
|
|||
|
||||
/**
|
||||
* Creates an instance with the specified settings.
|
||||
*
|
||||
*
|
||||
* @param subType mime subtype - must not be {@code null}
|
||||
* @param charset the character set to use. May be {@code null}, in which case {@link MIME#DEFAULT_CHARSET} - i.e. US-ASCII - is used.
|
||||
* @param boundary to use - must not be {@code null}
|
||||
|
@ -128,7 +128,7 @@ public class HttpMultipart {
|
|||
/**
|
||||
* Creates an instance with the specified settings.
|
||||
* Mode is set to {@link HttpMultipartMode#STRICT}
|
||||
*
|
||||
*
|
||||
* @param subType mime subtype - must not be {@code null}
|
||||
* @param charset the character set to use. May be {@code null}, in which case {@link MIME#DEFAULT_CHARSET} - i.e. US-ASCII - is used.
|
||||
* @param boundary to use - must not be {@code null}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class StringBody extends AbstractContentBody {
|
|||
|
||||
/**
|
||||
* Create a StringBody from the specified text, mime type and character set.
|
||||
*
|
||||
*
|
||||
* @param text to be used for the body, not {@code null}
|
||||
* @param mimeType the mime type, not {@code null}
|
||||
* @param charset the character set, may be {@code null}, in which case the US-ASCII charset is used
|
||||
|
@ -103,7 +103,7 @@ public class StringBody extends AbstractContentBody {
|
|||
/**
|
||||
* Create a StringBody from the specified text and character set.
|
||||
* The mime type is set to "text/plain".
|
||||
*
|
||||
*
|
||||
* @param text to be used for the body, not {@code null}
|
||||
* @param charset the character set, may be {@code null}, in which case the US-ASCII charset is used
|
||||
* @throws UnsupportedEncodingException
|
||||
|
@ -117,7 +117,7 @@ public class StringBody extends AbstractContentBody {
|
|||
* Create a StringBody from the specified text.
|
||||
* The mime type is set to "text/plain".
|
||||
* The hosts default charset is used.
|
||||
*
|
||||
*
|
||||
* @param text to be used for the body, not {@code null}
|
||||
* @throws UnsupportedEncodingException
|
||||
* @throws IllegalArgumentException if the {@code text} parameter is null
|
||||
|
|
Loading…
Reference in New Issue