From fcd02a0a18c3404e338c0749d2f29dec21fe7df7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 8 Dec 2012 19:59:24 +0000 Subject: [PATCH] Ported CachingHttpClient to ClientExecChain API git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1418743 13f79535-47bb-0310-9956-ffa450edef68 --- .../cache/AsynchronousValidationRequest.java | 41 +- .../client/cache/AsynchronousValidator.java | 39 +- .../http/impl/client/cache/CachingExec.java | 830 +++++++ .../impl/client/cache/CachingHttpClient.java | 158 ++ .../http/impl/client/cache/Proxies.java | 30 + .../client/cache/ResponseProxyHandler.java | 89 + .../memcached/MemcachedHttpCacheStorage.java | 13 +- .../client/cache/AbstractProtocolTest.java | 51 +- .../cache/DoNotTestProtocolRequirements.java | 186 -- .../http/impl/client/cache/DummyBackend.java | 70 + .../impl/client/cache/DummyHttpClient.java | 142 -- .../TestAsynchronousValidationRequest.java | 76 +- .../cache/TestAsynchronousValidator.java | 46 +- ...ngHttpClient.java => TestCachingExec.java} | 1345 ++++------- .../cache/TestHttpCacheJiraNumber1147.java | 55 +- .../cache/TestProtocolAllowedBehavior.java | 22 +- .../client/cache/TestProtocolDeviations.java | 116 +- .../cache/TestProtocolRecommendations.java | 565 +++-- .../cache/TestProtocolRequirements.java | 2067 ++++++++++------- .../client/cache/TestRFC5861Compliance.java | 190 +- .../TestEhcacheProtocolRequirements.java | 8 +- .../TestMemcachedHttpCacheStorage.java | 64 +- .../impl/client/execchain/MainClientExec.java | 8 +- .../{ExecProxies.java => Proxies.java} | 2 +- .../impl/client/execchain/RedirectExec.java | 2 +- .../http/impl/client/execchain/RetryExec.java | 2 +- 26 files changed, 3622 insertions(+), 2595 deletions(-) create mode 100644 httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java create mode 100644 httpclient-cache/src/main/java/org/apache/http/impl/client/cache/Proxies.java create mode 100644 httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProxyHandler.java delete mode 100644 httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DoNotTestProtocolRequirements.java create mode 100644 httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DummyBackend.java delete mode 100644 httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DummyHttpClient.java rename httpclient-cache/src/test/java/org/apache/http/impl/client/cache/{TestCachingHttpClient.java => TestCachingExec.java} (53%) rename httpclient/src/main/java/org/apache/http/impl/client/execchain/{ExecProxies.java => Proxies.java} (99%) diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidationRequest.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidationRequest.java index 4b498867c..0d1b8d8eb 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidationRequest.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidationRequest.java @@ -29,11 +29,12 @@ package org.apache.http.impl.client.cache; import java.io.IOException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.HttpHost; -import org.apache.http.ProtocolException; +import org.apache.http.HttpException; import org.apache.http.client.cache.HttpCacheEntry; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpRequestWrapper; -import org.apache.http.protocol.HttpContext; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; /** * Class used to represent an asynchronous revalidation event, such as with @@ -41,10 +42,11 @@ import org.apache.http.protocol.HttpContext; */ class AsynchronousValidationRequest implements Runnable { private final AsynchronousValidator parent; - private final CachingHttpClient cachingClient; - private final HttpHost target; + private final CachingExec cachingExec; + private final HttpRoute route; private final HttpRequestWrapper request; - private final HttpContext context; + private final HttpClientContext context; + private final HttpExecutionAware execAware; private final HttpCacheEntry cacheEntry; private final String identifier; @@ -61,27 +63,32 @@ class AsynchronousValidationRequest implements Runnable { * @param bookKeeping * @param identifier */ - AsynchronousValidationRequest(AsynchronousValidator parent, - CachingHttpClient cachingClient, HttpHost target, - HttpRequestWrapper request, HttpContext context, - HttpCacheEntry cacheEntry, - String identifier) { + AsynchronousValidationRequest( + final AsynchronousValidator parent, + final CachingExec cachingExec, + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware, + final HttpCacheEntry cacheEntry, + final String identifier) { this.parent = parent; - this.cachingClient = cachingClient; - this.target = target; + this.cachingExec = cachingExec; + this.route = route; this.request = request; this.context = context; + this.execAware = execAware; this.cacheEntry = cacheEntry; this.identifier = identifier; } public void run() { try { - cachingClient.revalidateCacheEntry(target, request, context, cacheEntry); + cachingExec.revalidateCacheEntry(route, request, context, execAware, cacheEntry); } catch (IOException ioe) { - log.debug("Asynchronous revalidation failed due to exception: " + ioe); - } catch (ProtocolException pe) { - log.error("ProtocolException thrown during asynchronous revalidation: " + pe); + log.debug("Asynchronous revalidation failed due to I/O error", ioe); + } catch (HttpException pe) { + log.error("HTTP protocol exception during asynchronous revalidation", pe); } finally { parent.markComplete(identifier); } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java index a4217670c..2335d327d 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java @@ -37,17 +37,18 @@ import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.HttpHost; import org.apache.http.client.cache.HttpCacheEntry; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpRequestWrapper; -import org.apache.http.protocol.HttpContext; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; /** * Class used for asynchronous revalidations to be used when the "stale- * while-revalidate" directive is present */ class AsynchronousValidator { - private final CachingHttpClient cachingClient; + private final CachingExec cachingExec; private final ExecutorService executor; private final Set queued; private final CacheKeyGenerator cacheKeyGenerator; @@ -59,16 +60,16 @@ class AsynchronousValidator { * using the supplied {@link CachingHttpClient}, and * a {@link ThreadPoolExecutor} generated according to the thread * pool settings provided in the given {@link CacheConfig}. - * @param cachingClient used to execute asynchronous requests + * @param cachingExect 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()}. */ - public AsynchronousValidator(CachingHttpClient cachingClient, + public AsynchronousValidator(CachingExec cachingExect, CacheConfig config) { - this(cachingClient, + this(cachingExect, new ThreadPoolExecutor(config.getAsynchronousWorkersCore(), config.getAsynchronousWorkersMax(), config.getAsynchronousWorkerIdleLifetimeSecs(), @@ -81,12 +82,11 @@ class AsynchronousValidator { * Create AsynchronousValidator which will make revalidation requests * using the supplied {@link CachingHttpClient} and * {@link ExecutorService}. - * @param cachingClient used to execute asynchronous requests + * @param cachingExect used to execute asynchronous requests * @param executor used to manage a thread pool of revalidation workers */ - AsynchronousValidator(CachingHttpClient cachingClient, - ExecutorService executor) { - this.cachingClient = cachingClient; + AsynchronousValidator(CachingExec cachingExec, ExecutorService executor) { + this.cachingExec = cachingExec; this.executor = executor; this.queued = new HashSet(); this.cacheKeyGenerator = new CacheKeyGenerator(); @@ -94,21 +94,20 @@ class AsynchronousValidator { /** * Schedules an asynchronous revalidation - * - * @param target - * @param request - * @param context - * @param entry */ - public synchronized void revalidateCacheEntry(HttpHost target, - HttpRequestWrapper request, HttpContext context, HttpCacheEntry entry) { + public synchronized void revalidateCacheEntry( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware, + final HttpCacheEntry entry) { // getVariantURI will fall back on getURI if no variants exist - String uri = cacheKeyGenerator.getVariantURI(target, request, entry); + String uri = cacheKeyGenerator.getVariantURI(route.getTargetHost(), request, entry); if (!queued.contains(uri)) { AsynchronousValidationRequest revalidationRequest = - new AsynchronousValidationRequest(this, cachingClient, target, - request, context, entry, uri); + new AsynchronousValidationRequest( + this, cachingExec, route, request, context, execAware, entry, uri); try { executor.execute(revalidationRequest); diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java new file mode 100644 index 000000000..12b7838cd --- /dev/null +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java @@ -0,0 +1,830 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.client.cache; + +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.Header; +import org.apache.http.HeaderElement; +import org.apache.http.HttpException; +import org.apache.http.HttpHost; +import org.apache.http.HttpMessage; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; +import org.apache.http.ProtocolVersion; +import org.apache.http.RequestLine; +import org.apache.http.annotation.ThreadSafe; +import org.apache.http.client.cache.CacheResponseStatus; +import org.apache.http.client.cache.HeaderConstants; +import org.apache.http.client.cache.HttpCacheEntry; +import org.apache.http.client.cache.HttpCacheStorage; +import org.apache.http.client.cache.ResourceFactory; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpExecutionAware; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.ClientContext; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.impl.client.execchain.ClientExecChain; +import org.apache.http.impl.cookie.DateParseException; +import org.apache.http.impl.cookie.DateUtils; +import org.apache.http.message.BasicHttpResponse; +import org.apache.http.protocol.ExecutionContext; +import org.apache.http.protocol.HTTP; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; +import org.apache.http.util.VersionInfo; + +/** + *

CachingExec is intended to transparently add client-side caching + * to the HttpClient {@link ClientExecChain execution chain}. + * The current implementation is conditionally compliant with HTTP/1.1 + * (meaning all the MUST and MUST NOTs are obeyed), although quite a lot, + * though not all, of the SHOULDs and SHOULD NOTs are obeyed too.

+ * + *

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 + * {@link org.apache.http.impl.client.cache.ehcache.EhcacheHttpCacheStorage + * EhCache} and {@link + * org.apache.http.impl.client.cache.memcached.MemcachedHttpCacheStorage + * memcached} storage backends.

+ *

+ * + * @since 4.3 + */ +@ThreadSafe // So long as the responseCache implementation is threadsafe +public class CachingExec implements ClientExecChain { + + /** + * This is the name under which the {@link + * org.apache.http.client.cache.CacheResponseStatus} of a request + * (for example, whether it resulted in a cache hit) will be recorded if an + * {@link HttpContext} is provided during execution. + */ + public static final String CACHE_RESPONSE_STATUS = "http.cache.response.status"; + + private final static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false; + + private final AtomicLong cacheHits = new AtomicLong(); + private final AtomicLong cacheMisses = new AtomicLong(); + private final AtomicLong cacheUpdates = new AtomicLong(); + + private final Map viaHeaders = new HashMap(4); + + private final CacheConfig cacheConfig; + private final ClientExecChain backend; + private final HttpCache responseCache; + private final CacheValidityPolicy validityPolicy; + private final CachedHttpResponseGenerator responseGenerator; + private final CacheableRequestPolicy cacheableRequestPolicy; + private final CachedResponseSuitabilityChecker suitabilityChecker; + private final ConditionalRequestBuilder conditionalRequestBuilder; + private final ResponseProtocolCompliance responseCompliance; + private final RequestProtocolCompliance requestCompliance; + private final ResponseCachingPolicy responseCachingPolicy; + + private final AsynchronousValidator asynchRevalidator; + + private final Log log = LogFactory.getLog(getClass()); + + public CachingExec( + ClientExecChain backend, + HttpCache cache, + CacheConfig config) { + super(); + if (backend == null) { + throw new IllegalArgumentException("HTTP backend may not be null"); + } + if (cache == null) { + throw new IllegalArgumentException("HttpCache may not be null"); + } + this.cacheConfig = config != null ? config : CacheConfig.DEFAULT; + this.backend = backend; + this.responseCache = cache; + this.validityPolicy = new CacheValidityPolicy(); + this.responseGenerator = new CachedHttpResponseGenerator(this.validityPolicy); + this.cacheableRequestPolicy = new CacheableRequestPolicy(); + this.suitabilityChecker = new CachedResponseSuitabilityChecker(this.validityPolicy, config); + this.conditionalRequestBuilder = new ConditionalRequestBuilder(); + this.responseCompliance = new ResponseProtocolCompliance(); + this.requestCompliance = new RequestProtocolCompliance(); + this.responseCachingPolicy = new ResponseCachingPolicy( + this.cacheConfig.getMaxObjectSize(), this.cacheConfig.isSharedCache()); + this.asynchRevalidator = makeAsynchronousValidator(config); + } + + public CachingExec( + ClientExecChain backend, + ResourceFactory resourceFactory, + HttpCacheStorage storage, + CacheConfig config) { + this(backend, new BasicHttpCache(resourceFactory, storage, config), config); + } + + public CachingExec(ClientExecChain backend) { + this(backend, new BasicHttpCache(), CacheConfig.DEFAULT); + } + + CachingExec( + ClientExecChain backend, + HttpCache responseCache, + CacheValidityPolicy validityPolicy, + ResponseCachingPolicy responseCachingPolicy, + CachedHttpResponseGenerator responseGenerator, + CacheableRequestPolicy cacheableRequestPolicy, + CachedResponseSuitabilityChecker suitabilityChecker, + ConditionalRequestBuilder conditionalRequestBuilder, + ResponseProtocolCompliance responseCompliance, + RequestProtocolCompliance requestCompliance, + CacheConfig config) { + this.cacheConfig = config != null ? config : CacheConfig.DEFAULT; + this.backend = backend; + this.responseCache = responseCache; + this.validityPolicy = validityPolicy; + this.responseCachingPolicy = responseCachingPolicy; + this.responseGenerator = responseGenerator; + this.cacheableRequestPolicy = cacheableRequestPolicy; + this.suitabilityChecker = suitabilityChecker; + this.conditionalRequestBuilder = conditionalRequestBuilder; + this.responseCompliance = responseCompliance; + this.requestCompliance = requestCompliance; + this.asynchRevalidator = makeAsynchronousValidator(config); + } + + private AsynchronousValidator makeAsynchronousValidator( + CacheConfig config) { + if (config.getAsynchronousWorkersMax() > 0) { + return new AsynchronousValidator(this, config); + } + return null; + } + + /** + * 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 + */ + public long getCacheHits() { + return cacheHits.get(); + } + + /** + * Reports the number of times that the cache contacted the origin + * server because it had no appropriate response cached. + * @return the number of cache misses + */ + public long getCacheMisses() { + return cacheMisses.get(); + } + + /** + * Reports the number of times that the cache was able to satisfy + * a response by revalidating an existing but stale cache entry. + * @return the number of cache revalidations + */ + public long getCacheUpdates() { + return cacheUpdates.get(); + } + + public CloseableHttpResponse execute( + final HttpRoute route, + final HttpRequestWrapper request) throws IOException, HttpException { + return execute(route, request, HttpClientContext.create(), null); + } + + public CloseableHttpResponse execute( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context) throws IOException, HttpException { + return execute(route, request, context, null); + } + + public CloseableHttpResponse execute( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware) throws IOException, HttpException { + + HttpHost target = route.getTargetHost(); + String via = generateViaHeader(request.getOriginal()); + + // default response context + setResponseStatus(context, CacheResponseStatus.CACHE_MISS); + + if (clientRequestsOurOptions(request)) { + setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE); + return Proxies.enhanceResponse(new OptionsHttp11Response()); + } + + HttpResponse fatalErrorResponse = getFatallyNoncompliantResponse(request, context); + if (fatalErrorResponse != null) { + return Proxies.enhanceResponse(fatalErrorResponse); + } + + requestCompliance.makeRequestCompliant(request); + request.addHeader("Via",via); + + flushEntriesInvalidatedByRequest(route.getTargetHost(), request); + + if (!cacheableRequestPolicy.isServableFromCache(request)) { + log.debug("Request is not servable from cache"); + return callBackend(route, request, context, execAware); + } + + HttpCacheEntry entry = satisfyFromCache(target, request); + if (entry == null) { + log.debug("Cache miss"); + return handleCacheMiss(route, request, context, execAware); + } + + return handleCacheHit(route, request, context, execAware, entry); + } + + private CloseableHttpResponse handleCacheHit( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware, + final HttpCacheEntry entry) throws IOException, HttpException { + HttpHost target = route.getTargetHost(); + recordCacheHit(target, request); + CloseableHttpResponse out = null; + Date now = getCurrentDate(); + if (suitabilityChecker.canCachedResponseBeUsed(target, request, entry, now)) { + log.debug("Cache hit"); + out = Proxies.enhanceResponse(generateCachedResponse(request, context, entry, now)); + } else if (!mayCallBackend(request)) { + log.debug("Cache entry not suitable but only-if-cached requested"); + out = Proxies.enhanceResponse(generateGatewayTimeout(context)); + } else if (validityPolicy.isRevalidatable(entry)) { + log.debug("Revalidating cache entry"); + return revalidateCacheEntry(route, request, context, execAware, entry, now); + } else { + log.debug("Cache entry not usable; calling backend"); + return callBackend(route, request, context, execAware); + } + if (context != null) { + context.setAttribute(ClientContext.ROUTE, route); + context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, target); + context.setAttribute(ExecutionContext.HTTP_REQUEST, request); + context.setAttribute(ExecutionContext.HTTP_RESPONSE, out); + context.setAttribute(ExecutionContext.HTTP_REQ_SENT, Boolean.TRUE); + } + return out; + } + + private CloseableHttpResponse revalidateCacheEntry( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware, + final HttpCacheEntry entry, + final Date now) throws IOException, HttpException { + + try { + if (asynchRevalidator != null + && !staleResponseNotAllowed(request, entry, now) + && validityPolicy.mayReturnStaleWhileRevalidating(entry, now)) { + log.trace("Serving stale with asynchronous revalidation"); + HttpResponse resp = generateCachedResponse(request, context, entry, now); + asynchRevalidator.revalidateCacheEntry(route, request, context, execAware, entry); + return Proxies.enhanceResponse(resp); + } + return revalidateCacheEntry(route, request, context, execAware, entry); + } catch (IOException ioex) { + return Proxies.enhanceResponse( + handleRevalidationFailure(request, context, entry, now)); + } + } + + private CloseableHttpResponse handleCacheMiss( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware) throws IOException, HttpException { + HttpHost target = route.getTargetHost(); + recordCacheMiss(target, request); + + if (!mayCallBackend(request)) { + return Proxies.enhanceResponse( + new BasicHttpResponse( + HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout")); + } + + Map variants = getExistingCacheVariants(target, request); + if (variants != null && variants.size() > 0) { + return Proxies.enhanceResponse( + negotiateResponseFromVariants(route, request, context, execAware, variants)); + } + + return callBackend(route, request, context, execAware); + } + + private HttpCacheEntry satisfyFromCache( + final HttpHost target, final HttpRequestWrapper request) { + HttpCacheEntry entry = null; + try { + entry = responseCache.getCacheEntry(target, request); + } catch (IOException ioe) { + log.warn("Unable to retrieve entries from cache", ioe); + } + return entry; + } + + private HttpResponse getFatallyNoncompliantResponse( + final HttpRequestWrapper request, + final HttpContext context) { + HttpResponse fatalErrorResponse = null; + List fatalError = requestCompliance.requestIsFatallyNonCompliant(request); + + for (RequestProtocolError error : fatalError) { + setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE); + fatalErrorResponse = requestCompliance.getErrorForRequest(error); + } + return fatalErrorResponse; + } + + private Map getExistingCacheVariants( + final HttpHost target, + final HttpRequestWrapper request) { + Map variants = null; + try { + variants = responseCache.getVariantCacheEntriesWithEtags(target, request); + } catch (IOException ioe) { + log.warn("Unable to retrieve variant entries from cache", ioe); + } + return variants; + } + + private void recordCacheMiss(final HttpHost target, final HttpRequestWrapper request) { + cacheMisses.getAndIncrement(); + if (log.isTraceEnabled()) { + RequestLine rl = request.getRequestLine(); + log.trace("Cache miss [host: " + target + "; uri: " + rl.getUri() + "]"); + } + } + + private void recordCacheHit(final HttpHost target, final HttpRequestWrapper request) { + cacheHits.getAndIncrement(); + if (log.isTraceEnabled()) { + RequestLine rl = request.getRequestLine(); + log.trace("Cache hit [host: " + target + "; uri: " + rl.getUri() + "]"); + } + } + + private void recordCacheUpdate(HttpContext context) { + cacheUpdates.getAndIncrement(); + setResponseStatus(context, CacheResponseStatus.VALIDATED); + } + + private void flushEntriesInvalidatedByRequest( + final HttpHost target, + final HttpRequestWrapper request) { + try { + responseCache.flushInvalidatedCacheEntriesFor(target, request); + } catch (IOException ioe) { + log.warn("Unable to flush invalidated entries from cache", ioe); + } + } + + private HttpResponse generateCachedResponse(HttpRequestWrapper request, + HttpContext context, HttpCacheEntry entry, Date now) { + final HttpResponse cachedResponse; + if (request.containsHeader(HeaderConstants.IF_NONE_MATCH) + || request.containsHeader(HeaderConstants.IF_MODIFIED_SINCE)) { + cachedResponse = responseGenerator.generateNotModifiedResponse(entry); + } else { + cachedResponse = responseGenerator.generateResponse(entry); + } + setResponseStatus(context, CacheResponseStatus.CACHE_HIT); + if (validityPolicy.getStalenessSecs(entry, now) > 0L) { + cachedResponse.addHeader(HeaderConstants.WARNING,"110 localhost \"Response is stale\""); + } + return cachedResponse; + } + + private HttpResponse handleRevalidationFailure( + final HttpRequestWrapper request, + final HttpContext context, + final HttpCacheEntry entry, + final Date now) { + if (staleResponseNotAllowed(request, entry, now)) { + return generateGatewayTimeout(context); + } else { + return unvalidatedCacheHit(context, entry); + } + } + + private HttpResponse generateGatewayTimeout(final HttpContext context) { + setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE); + return new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + } + + private HttpResponse unvalidatedCacheHit( + final HttpContext context, final HttpCacheEntry entry) { + final HttpResponse cachedResponse = responseGenerator.generateResponse(entry); + setResponseStatus(context, CacheResponseStatus.CACHE_HIT); + cachedResponse.addHeader(HeaderConstants.WARNING, "111 localhost \"Revalidation failed\""); + return cachedResponse; + } + + private boolean staleResponseNotAllowed( + final HttpRequestWrapper request, + final HttpCacheEntry entry, + final Date now) { + return validityPolicy.mustRevalidate(entry) + || (cacheConfig.isSharedCache() && validityPolicy.proxyRevalidate(entry)) + || explicitFreshnessRequest(request, entry, now); + } + + private boolean mayCallBackend(final HttpRequestWrapper request) { + for (Header h: request.getHeaders(HeaderConstants.CACHE_CONTROL)) { + for (HeaderElement elt : h.getElements()) { + if ("only-if-cached".equals(elt.getName())) { + log.trace("Request marked only-if-cached"); + return false; + } + } + } + return true; + } + + private boolean explicitFreshnessRequest( + final HttpRequestWrapper request, + final HttpCacheEntry entry, + final Date now) { + for(Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) { + for(HeaderElement elt : h.getElements()) { + if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) { + try { + int maxstale = Integer.parseInt(elt.getValue()); + long age = validityPolicy.getCurrentAgeSecs(entry, now); + long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry); + if (age - lifetime > maxstale) return true; + } catch (NumberFormatException nfe) { + return true; + } + } else if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName()) + || HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) { + return true; + } + } + } + return false; + } + + private String generateViaHeader(final HttpMessage msg) { + + final ProtocolVersion pv = msg.getProtocolVersion(); + String existingEntry = viaHeaders.get(pv); + if (existingEntry != null) return existingEntry; + + final VersionInfo vi = VersionInfo.loadVersionInfo("org.apache.http.client", getClass().getClassLoader()); + final String release = (vi != null) ? vi.getRelease() : VersionInfo.UNAVAILABLE; + + String value; + if ("http".equalsIgnoreCase(pv.getProtocol())) { + value = String.format("%d.%d localhost (Apache-HttpClient/%s (cache))", pv.getMajor(), pv.getMinor(), + release); + } else { + value = String.format("%s/%d.%d localhost (Apache-HttpClient/%s (cache))", pv.getProtocol(), pv.getMajor(), + pv.getMinor(), release); + } + viaHeaders.put(pv, value); + + return value; + } + + private void setResponseStatus(final HttpContext context, final CacheResponseStatus value) { + if (context != null) { + context.setAttribute(CACHE_RESPONSE_STATUS, value); + } + } + + /** + * Reports whether this {@code CachingHttpClient} implementation + * supports byte-range requests as specified by the {@code Range} + * and {@code Content-Range} headers. + * @return {@code true} if byte-range requests are supported + */ + public boolean supportsRangeAndContentRangeHeaders() { + return SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS; + } + + Date getCurrentDate() { + return new Date(); + } + + boolean clientRequestsOurOptions(final HttpRequest request) { + RequestLine line = request.getRequestLine(); + + if (!HeaderConstants.OPTIONS_METHOD.equals(line.getMethod())) + return false; + + if (!"*".equals(line.getUri())) + return false; + + if (!"0".equals(request.getFirstHeader(HeaderConstants.MAX_FORWARDS).getValue())) + return false; + + return true; + } + + CloseableHttpResponse callBackend( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware) throws IOException, HttpException { + + Date requestDate = getCurrentDate(); + + log.trace("Calling the backend"); + CloseableHttpResponse backendResponse = backend.execute(route, request, context, execAware); + backendResponse.addHeader("Via", generateViaHeader(backendResponse)); + return handleBackendResponse(route, request, context, execAware, + requestDate, getCurrentDate(), backendResponse); + } + + private boolean revalidationResponseIsTooOld(HttpResponse backendResponse, + HttpCacheEntry cacheEntry) { + final Header entryDateHeader = cacheEntry.getFirstHeader(HTTP.DATE_HEADER); + final Header responseDateHeader = backendResponse.getFirstHeader(HTTP.DATE_HEADER); + if (entryDateHeader != null && responseDateHeader != null) { + try { + Date entryDate = DateUtils.parseDate(entryDateHeader.getValue()); + Date respDate = DateUtils.parseDate(responseDateHeader.getValue()); + if (respDate.before(entryDate)) return true; + } catch (DateParseException e) { + // either backend response or cached entry did not have a valid + // Date header, so we can't tell if they are out of order + // according to the origin clock; thus we can skip the + // unconditional retry recommended in 13.2.6 of RFC 2616. + } + } + return false; + } + + HttpResponse negotiateResponseFromVariants( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware, + final Map variants) throws IOException, HttpException { + HttpRequestWrapper conditionalRequest = conditionalRequestBuilder + .buildConditionalRequestFromVariants(request, variants); + + Date requestDate = getCurrentDate(); + CloseableHttpResponse backendResponse = backend.execute( + route, conditionalRequest, context, execAware); + Date responseDate = getCurrentDate(); + + backendResponse.addHeader("Via", generateViaHeader(backendResponse)); + + if (backendResponse.getStatusLine().getStatusCode() != HttpStatus.SC_NOT_MODIFIED) { + return handleBackendResponse( + route, request, context, execAware, + requestDate, responseDate, backendResponse); + } + + Header resultEtagHeader = backendResponse.getFirstHeader(HeaderConstants.ETAG); + if (resultEtagHeader == null) { + log.warn("304 response did not contain ETag"); + return callBackend(route, request, context, execAware); + } + + String resultEtag = resultEtagHeader.getValue(); + Variant matchingVariant = variants.get(resultEtag); + if (matchingVariant == null) { + log.debug("304 response did not contain ETag matching one sent in If-None-Match"); + return callBackend(route, request, context, execAware); + } + + HttpCacheEntry matchedEntry = matchingVariant.getEntry(); + + if (revalidationResponseIsTooOld(backendResponse, matchedEntry)) { + EntityUtils.consume(backendResponse.getEntity()); + return retryRequestUnconditionally(route, request, context, execAware, matchedEntry); + } + + recordCacheUpdate(context); + + HttpCacheEntry responseEntry = getUpdatedVariantEntry( + route.getTargetHost(), conditionalRequest, requestDate, responseDate, + backendResponse, matchingVariant, matchedEntry); + + HttpResponse resp = responseGenerator.generateResponse(responseEntry); + tryToUpdateVariantMap(route.getTargetHost(), request, matchingVariant); + + if (shouldSendNotModifiedResponse(request, responseEntry)) { + return responseGenerator.generateNotModifiedResponse(responseEntry); + } + + return resp; + } + + private HttpResponse retryRequestUnconditionally( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware, + final HttpCacheEntry matchedEntry) throws IOException, HttpException { + HttpRequestWrapper unconditional = conditionalRequestBuilder + .buildUnconditionalRequest(request, matchedEntry); + return callBackend(route, unconditional, context, execAware); + } + + private HttpCacheEntry getUpdatedVariantEntry( + final HttpHost target, + final HttpRequestWrapper conditionalRequest, + final Date requestDate, + final Date responseDate, + final HttpResponse backendResponse, + final Variant matchingVariant, + final HttpCacheEntry matchedEntry) { + HttpCacheEntry responseEntry = matchedEntry; + try { + responseEntry = responseCache.updateVariantCacheEntry(target, conditionalRequest, + matchedEntry, backendResponse, requestDate, responseDate, matchingVariant.getCacheKey()); + } catch (IOException ioe) { + log.warn("Could not update cache entry", ioe); + } + return responseEntry; + } + + private void tryToUpdateVariantMap( + final HttpHost target, + final HttpRequestWrapper request, + final Variant matchingVariant) { + try { + responseCache.reuseVariantEntryFor(target, request, matchingVariant); + } catch (IOException ioe) { + log.warn("Could not update cache entry to reuse variant", ioe); + } + } + + private boolean shouldSendNotModifiedResponse( + final HttpRequestWrapper request, + final HttpCacheEntry responseEntry) { + return (suitabilityChecker.isConditional(request) + && suitabilityChecker.allConditionalsMatch(request, responseEntry, new Date())); + } + + CloseableHttpResponse revalidateCacheEntry( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware, + final HttpCacheEntry cacheEntry) throws IOException, HttpException { + + HttpRequestWrapper conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry); + + Date requestDate = getCurrentDate(); + CloseableHttpResponse backendResponse = backend.execute( + route, conditionalRequest, context, execAware); + Date responseDate = getCurrentDate(); + + if (revalidationResponseIsTooOld(backendResponse, cacheEntry)) { + backendResponse.close(); + HttpRequestWrapper unconditional = conditionalRequestBuilder + .buildUnconditionalRequest(request, cacheEntry); + requestDate = getCurrentDate(); + backendResponse = backend.execute(route, unconditional, context, execAware); + responseDate = getCurrentDate(); + } + + backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse)); + + int statusCode = backendResponse.getStatusLine().getStatusCode(); + if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) { + recordCacheUpdate(context); + } + + if (statusCode == HttpStatus.SC_NOT_MODIFIED) { + HttpCacheEntry updatedEntry = responseCache.updateCacheEntry( + route.getTargetHost(), request, cacheEntry, + backendResponse, requestDate, responseDate); + if (suitabilityChecker.isConditional(request) + && suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) { + return Proxies.enhanceResponse( + responseGenerator.generateNotModifiedResponse(updatedEntry)); + } + return Proxies.enhanceResponse(responseGenerator.generateResponse(updatedEntry)); + } + + if (staleIfErrorAppliesTo(statusCode) + && !staleResponseNotAllowed(request, cacheEntry, getCurrentDate()) + && validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) { + try { + HttpResponse cachedResponse = responseGenerator.generateResponse(cacheEntry); + cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\""); + return Proxies.enhanceResponse(cachedResponse); + } finally { + backendResponse.close(); + } + } + return handleBackendResponse( + route, conditionalRequest, context, execAware, + requestDate, responseDate, backendResponse); + } + + private boolean staleIfErrorAppliesTo(int statusCode) { + return statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR + || statusCode == HttpStatus.SC_BAD_GATEWAY + || statusCode == HttpStatus.SC_SERVICE_UNAVAILABLE + || statusCode == HttpStatus.SC_GATEWAY_TIMEOUT; + } + + CloseableHttpResponse handleBackendResponse( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext context, + final HttpExecutionAware execAware, + final Date requestDate, + final Date responseDate, + final CloseableHttpResponse backendResponse) throws IOException { + + log.trace("Handling Backend response"); + responseCompliance.ensureProtocolCompliance(request, backendResponse); + + HttpHost target = route.getTargetHost(); + boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse); + responseCache.flushInvalidatedCacheEntriesFor(target, request, backendResponse); + if (cacheable && !alreadyHaveNewerCacheEntry(target, request, backendResponse)) { + try { + return Proxies.enhanceResponse(responseCache.cacheAndReturnResponse( + target, request, backendResponse, requestDate, responseDate)); + } catch (IOException ioe) { + log.warn("Unable to store entries in cache", ioe); + } finally { + backendResponse.close(); + } + } + if (!cacheable) { + try { + responseCache.flushCacheEntriesFor(target, request); + } catch (IOException ioe) { + log.warn("Unable to flush invalid cache entries", ioe); + } + } + return backendResponse; + } + + private boolean alreadyHaveNewerCacheEntry(HttpHost target, HttpRequestWrapper request, + HttpResponse backendResponse) { + HttpCacheEntry existing = null; + try { + existing = responseCache.getCacheEntry(target, request); + } catch (IOException ioe) { + // nop + } + if (existing == null) return false; + Header entryDateHeader = existing.getFirstHeader(HTTP.DATE_HEADER); + if (entryDateHeader == null) return false; + Header responseDateHeader = backendResponse.getFirstHeader(HTTP.DATE_HEADER); + if (responseDateHeader == null) return false; + try { + Date entryDate = DateUtils.parseDate(entryDateHeader.getValue()); + Date responseDate = DateUtils.parseDate(responseDateHeader.getValue()); + return responseDate.before(entryDate); + } catch (DateParseException e) { + // Empty on Purpose + } + return false; + } + +} diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java index d722a0f37..f2bdc05aa 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java @@ -29,10 +29,18 @@ package org.apache.http.impl.client.cache; import java.io.IOException; import java.lang.reflect.UndeclaredThrowableException; import java.net.URI; +import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.logging.Log; @@ -109,7 +117,10 @@ import org.apache.http.util.VersionInfo; * memcached} storage backends.

*

* @since 4.1 + * + * @deprecated (4.3) */ +@Deprecated @ThreadSafe // So long as the responseCache implementation is threadsafe public class CachingHttpClient implements HttpClient { @@ -960,4 +971,151 @@ public class CachingHttpClient implements HttpClient { return false; } + static class AsynchronousValidator { + private final CachingHttpClient cachingClient; + private final ExecutorService executor; + private final Set 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 + * a {@link ThreadPoolExecutor} generated according to the thread + * 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()}. + */ + public AsynchronousValidator(CachingHttpClient cachingClient, + CacheConfig config) { + this(cachingClient, + new ThreadPoolExecutor(config.getAsynchronousWorkersCore(), + config.getAsynchronousWorkersMax(), + config.getAsynchronousWorkerIdleLifetimeSecs(), + TimeUnit.SECONDS, + new ArrayBlockingQueue(config.getRevalidationQueueSize())) + ); + } + + /** + * Create AsynchronousValidator which will make revalidation requests + * using the supplied {@link CachingHttpClient} and + * {@link ExecutorService}. + * @param cachingClient used to execute asynchronous requests + * @param executor used to manage a thread pool of revalidation workers + */ + AsynchronousValidator(CachingHttpClient cachingClient, + ExecutorService executor) { + this.cachingClient = cachingClient; + this.executor = executor; + this.queued = new HashSet(); + this.cacheKeyGenerator = new CacheKeyGenerator(); + } + + /** + * Schedules an asynchronous revalidation + * + * @param target + * @param request + * @param context + * @param entry + */ + public synchronized void revalidateCacheEntry(HttpHost target, + HttpRequestWrapper 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, + request, context, entry, uri); + + try { + executor.execute(revalidationRequest); + queued.add(uri); + } catch (RejectedExecutionException ree) { + log.debug("Revalidation for [" + uri + "] not scheduled: " + ree); + } + } + } + + /** + * Removes an identifier from the internal list of revalidation jobs in + * 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 + */ + synchronized void markComplete(String identifier) { + queued.remove(identifier); + } + + Set getScheduledIdentifiers() { + return Collections.unmodifiableSet(queued); + } + + ExecutorService getExecutor() { + return executor; + } + } + + static class AsynchronousValidationRequest implements Runnable { + private final AsynchronousValidator parent; + private final CachingHttpClient cachingClient; + private final HttpHost target; + private final HttpRequestWrapper request; + 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. + * @param cachingClient + * @param target + * @param request + * @param context + * @param cacheEntry + * @param bookKeeping + * @param identifier + */ + AsynchronousValidationRequest(AsynchronousValidator parent, + CachingHttpClient cachingClient, HttpHost target, + HttpRequestWrapper request, HttpContext context, + HttpCacheEntry cacheEntry, + String identifier) { + this.parent = parent; + this.cachingClient = cachingClient; + this.target = target; + this.request = request; + this.context = context; + this.cacheEntry = cacheEntry; + this.identifier = identifier; + } + + public void run() { + try { + cachingClient.revalidateCacheEntry(target, request, context, cacheEntry); + } catch (IOException ioe) { + log.debug("Asynchronous revalidation failed due to exception: " + ioe); + } catch (ProtocolException pe) { + log.error("ProtocolException thrown during asynchronous revalidation: " + pe); + } finally { + parent.markComplete(identifier); + } + } + + String getIdentifier() { + return identifier; + } + + } + } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/Proxies.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/Proxies.java new file mode 100644 index 000000000..7ce19e006 --- /dev/null +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/Proxies.java @@ -0,0 +1,30 @@ +package org.apache.http.impl.client.cache; + +import java.lang.reflect.Proxy; + +import org.apache.http.HttpResponse; +import org.apache.http.annotation.NotThreadSafe; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.util.Args; + +/** + * Proxies for HTTP message objects. + * + * @since 4.3 + */ +@NotThreadSafe +class Proxies { + + public static CloseableHttpResponse enhanceResponse(final HttpResponse original) { + Args.notNull(original, "HTTP response"); + if (original instanceof CloseableHttpResponse) { + return (CloseableHttpResponse) original; + } else { + return (CloseableHttpResponse) Proxy.newProxyInstance( + ResponseProxyHandler.class.getClassLoader(), + new Class[] { CloseableHttpResponse.class }, + new ResponseProxyHandler(original)); + } + } + +} \ No newline at end of file diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProxyHandler.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProxyHandler.java new file mode 100644 index 000000000..3767c6821 --- /dev/null +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProxyHandler.java @@ -0,0 +1,89 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.client.cache; + +import java.io.Closeable; +import java.io.IOException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.http.HttpResponse; +import org.apache.http.annotation.NotThreadSafe; +import org.apache.http.util.EntityUtils; + +/** + * A proxy class that can enhance an arbitrary {@link HttpResponse} with + * {@link Closeable#close()} method. + * + * @since 4.3 + */ +@NotThreadSafe +class ResponseProxyHandler implements InvocationHandler { + + private static final Method CLOSE_METHOD; + + static { + try { + CLOSE_METHOD = Closeable.class.getMethod("close"); + } catch (NoSuchMethodException ex) { + throw new Error(ex); + } + } + + private final HttpResponse original; + + ResponseProxyHandler(final HttpResponse original) { + super(); + this.original = original; + } + + public void close() throws IOException { + EntityUtils.consume(original.getEntity()); + } + + public Object invoke( + final Object proxy, final Method method, final Object[] args) throws Throwable { + if (method.equals(CLOSE_METHOD)) { + close(); + return null; + } else { + try { + return method.invoke(this.original, args); + } catch (InvocationTargetException ex) { + Throwable cause = ex.getCause(); + if (cause != null) { + throw cause; + } else { + throw ex; + } + } + } + } + +} diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/memcached/MemcachedHttpCacheStorage.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/memcached/MemcachedHttpCacheStorage.java index 6fb0d2c14..be664f9af 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/memcached/MemcachedHttpCacheStorage.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/memcached/MemcachedHttpCacheStorage.java @@ -43,7 +43,6 @@ import org.apache.http.client.cache.HttpCacheUpdateException; import org.apache.http.client.cache.HttpCacheStorage; import org.apache.http.client.cache.HttpCacheUpdateCallback; import org.apache.http.impl.client.cache.CacheConfig; -import org.apache.http.impl.client.cache.CachingHttpClient; /** *

This class is a storage backend that uses an external memcached @@ -62,13 +61,13 @@ import org.apache.http.impl.client.cache.CachingHttpClient; * fails (see the * KetamaConnectionFactory). *

- * + * *

Because memcached places limits on the size of its keys, we need to * introduce a key hashing scheme to map the annotated URLs the higher-level - * {@link CachingHttpClient} wants to use as keys onto ones that are suitable + * caching HTTP client wants to use as keys onto ones that are suitable * for use with memcached. Please see {@link KeyHashingScheme} if you would * like to use something other than the provided {@link SHA256KeyHashingScheme}.

- * + * *

Because this hashing scheme can potentially result in key collisions (though * highly unlikely), we need to store the higher-level logical storage key along * with the {@link HttpCacheEntry} so that we can re-check it on retrieval. There @@ -87,7 +86,7 @@ import org.apache.http.impl.client.cache.CachingHttpClient; public class MemcachedHttpCacheStorage implements HttpCacheStorage { private static final Log log = LogFactory.getLog(MemcachedHttpCacheStorage.class); - + private final MemcachedClientIF client; private final KeyHashingScheme keyHashingScheme; private final MemcachedCacheEntryFactory memcachedCacheEntryFactory; @@ -158,7 +157,7 @@ public class MemcachedHttpCacheStorage implements HttpCacheStorage { this.memcachedCacheEntryFactory = memcachedCacheEntryFactory; this.keyHashingScheme = keyHashingScheme; } - + public void putEntry(String url, HttpCacheEntry entry) throws IOException { byte[] bytes = serializeEntry(url, entry); String key = getCacheKey(url); @@ -209,7 +208,7 @@ public class MemcachedHttpCacheStorage implements HttpCacheStorage { } return mce; } - + public HttpCacheEntry getEntry(String url) throws IOException { String key = getCacheKey(url); if (key == null) return null; diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java index 20b611f58..e353f764a 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java @@ -27,15 +27,19 @@ package org.apache.http.impl.client.cache; import java.util.HashMap; + import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; -import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.impl.client.execchain.ClientExecChain; import org.apache.http.message.BasicHttpRequest; -import org.apache.http.protocol.HttpContext; import org.easymock.IExpectationSetters; import org.easymock.classextension.EasyMock; import org.junit.Before; @@ -46,16 +50,17 @@ public abstract class AbstractProtocolTest { protected static final int MAX_ENTRIES = 100; protected int entityLength = 128; protected HttpHost host; + protected HttpRoute route; protected HttpEntity body; - protected HttpClient mockBackend; + protected ClientExecChain mockBackend; protected HttpCache mockCache; protected HttpRequestWrapper request; - protected HttpResponse originResponse; + protected CloseableHttpResponse originResponse; protected CacheConfig config; - protected CachingHttpClient impl; + protected CachingExec impl; protected HttpCache cache; - public static HttpRequest eqRequest(HttpRequest in) { + public static HttpRequestWrapper eqRequest(HttpRequestWrapper in) { EasyMock.reportMatcher(new RequestEquivalent(in)); return null; } @@ -64,20 +69,23 @@ public abstract class AbstractProtocolTest { public void setUp() { host = new HttpHost("foo.example.com"); + route = new HttpRoute(host); + body = HttpTestUtils.makeBody(entityLength); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); - originResponse = HttpTestUtils.make200Response(); + originResponse = Proxies.enhanceResponse(HttpTestUtils.make200Response()); config = CacheConfig.custom() .setMaxCacheEntries(MAX_ENTRIES) .setMaxObjectSize(MAX_BYTES) .build(); + cache = new BasicHttpCache(config); - mockBackend = EasyMock.createNiceMock(HttpClient.class); + mockBackend = EasyMock.createNiceMock(ClientExecChain.class); mockCache = EasyMock.createNiceMock(HttpCache.class); - impl = new CachingHttpClient(mockBackend, cache, config); + impl = new CachingExec(mockBackend, cache, config); } protected void replayMocks() { @@ -90,17 +98,30 @@ public abstract class AbstractProtocolTest { EasyMock.verify(mockCache); } - protected IExpectationSetters backendExpectsAnyRequest() throws Exception { - HttpResponse resp = mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock - .isA(HttpRequest.class), (HttpContext) EasyMock.isNull()); + protected IExpectationSetters backendExpectsAnyRequest() throws Exception { + CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); return EasyMock.expect(resp); } + protected IExpectationSetters backendExpectsAnyRequestAndReturn( + HttpResponse reponse) throws Exception { + CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(reponse)); + } + protected void emptyMockCacheExpectsNoPuts() throws Exception { - mockBackend = EasyMock.createNiceMock(HttpClient.class); + mockBackend = EasyMock.createNiceMock(ClientExecChain.class); mockCache = EasyMock.createNiceMock(HttpCache.class); - impl = new CachingHttpClient(mockBackend, mockCache, config); + impl = new CachingExec(mockBackend, mockCache, config); EasyMock.expect(mockCache.getCacheEntry(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class))) .andReturn(null).anyTimes(); @@ -126,7 +147,7 @@ public abstract class AbstractProtocolTest { .setMaxObjectSize(MAX_BYTES) .setSharedCache(false) .build(); - impl = new CachingHttpClient(mockBackend, cache, config); + impl = new CachingExec(mockBackend, cache, config); } public AbstractProtocolTest() { diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DoNotTestProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DoNotTestProtocolRequirements.java deleted file mode 100644 index 263be6644..000000000 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DoNotTestProtocolRequirements.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.http.impl.client.cache; - -import java.util.Date; -import java.util.Random; - -import org.apache.http.Header; -import org.apache.http.HeaderElement; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.NameValuePair; -import org.apache.http.ProtocolVersion; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.impl.cookie.DateUtils; -import org.apache.http.message.BasicHttpRequest; -import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.HttpContext; -import org.easymock.classextension.EasyMock; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -public class DoNotTestProtocolRequirements { - - private static final ProtocolVersion HTTP_1_1 = new ProtocolVersion("HTTP", 1, 1); - - private static final int MAX_BYTES = 1024; - private static final int MAX_ENTRIES = 100; - - private HttpHost host; - private HttpEntity mockEntity; - private HttpClient mockBackend; - private HttpCache mockCache; - private HttpRequest request; - private HttpResponse originResponse; - - private CachingHttpClient impl; - - @Before - public void setUp() { - host = new HttpHost("foo.example.com"); - - request = new BasicHttpRequest("GET", "/foo", HTTP_1_1); - - originResponse = make200Response(); - CacheConfig params = CacheConfig.custom() - .setMaxObjectSize(MAX_BYTES) - .setMaxCacheEntries(MAX_ENTRIES).build(); - - HttpCache cache = new BasicHttpCache(params); - mockBackend = EasyMock.createNiceMock(HttpClient.class); - mockEntity = EasyMock.createNiceMock(HttpEntity.class); - mockCache = EasyMock.createNiceMock(HttpCache.class); - impl = new CachingHttpClient(mockBackend, cache, params); - } - - private HttpResponse make200Response() { - HttpResponse out = new BasicHttpResponse(HTTP_1_1, HttpStatus.SC_OK, "OK"); - out.setHeader("Date", DateUtils.formatDate(new Date())); - out.setHeader("Server", "MockOrigin/1.0"); - out.setEntity(makeBody(128)); - return out; - } - - private void replayMocks() { - EasyMock.replay(mockBackend); - EasyMock.replay(mockCache); - EasyMock.replay(mockEntity); - } - - private HttpEntity makeBody(int nbytes) { - byte[] bytes = new byte[nbytes]; - (new Random()).nextBytes(bytes); - return new ByteArrayEntity(bytes); - } - - /* - * "10.2.7 206 Partial Content ... The response MUST include the following - * header fields: - * - * - Either a Content-Range header field (section 14.16) indicating the - * range included with this response, or a multipart/byteranges Content-Type - * including Content-Range fields for each part. If a Content-Length header - * field is present in the response, its value MUST match the actual number - * of OCTETs transmitted in the message-body. - * - * - Date - * - * - ETag and/or Content-Location, if the header would have been sent in a - * 200 response to the same request - * - * - Expires, Cache-Control, and/or Vary, if the field-value might differ - * from that sent in any previous response for the same variant - * - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.7 - */ - @Test - @Ignore - public void test206ResponseReturnedToClientMustHaveContentRangeOrByteRangesContentType() - throws Exception { - request.addHeader("Range", "bytes 0-499/1234"); - originResponse = new BasicHttpResponse(HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, - "Partial Content"); - originResponse.setHeader("Date", DateUtils.formatDate(new Date())); - originResponse.setHeader("Server", "MockOrigin/1.0"); - originResponse.setEntity(makeBody(500)); - - org.easymock.EasyMock.expect( - mockBackend.execute(org.easymock.EasyMock.isA(HttpHost.class), - org.easymock.EasyMock.isA(HttpRequest.class), - (HttpContext) org.easymock.EasyMock.isNull())).andReturn(originResponse); - - replayMocks(); - - try { - HttpResponse result = impl.execute(host, request); - Header crHdr = result.getFirstHeader("Content-Range"); - Header ctHdr = result.getFirstHeader("Content-Type"); - if (result.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT) { - if (crHdr == null) { - Assert.assertNotNull(ctHdr); - boolean foundMultipartByteRanges = false; - for (HeaderElement elt : ctHdr.getElements()) { - if ("multipart/byteranges".equalsIgnoreCase(elt.getName())) { - NameValuePair param = elt.getParameterByName("boundary"); - Assert.assertNotNull(param); - String boundary = param.getValue(); - Assert.assertNotNull(boundary); - // perhaps eventually should parse out the - // request body to check proper formatting - // but that might be excessive; HttpClient - // developers have indicated that - // HttpClient's job does not involve - // parsing a response body - } - } - Assert.assertTrue(foundMultipartByteRanges); - } - } - } catch (ClientProtocolException acceptableBehavior) { - } - } - - @Test - @Ignore - public void test206ResponseReturnedToClientWithAContentLengthMustMatchActualOctetsTransmitted() { - // We are explicitly saying that CachingHttpClient does not care about - // this: - // We do not attempt to cache 206, nor do we ever construct a 206. We - // simply pass along a 206, - // which could be malformed. But protocol compliance of a downstream - // server is not our responsibility - } - -} diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DummyBackend.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DummyBackend.java new file mode 100644 index 000000000..ef3562c10 --- /dev/null +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DummyBackend.java @@ -0,0 +1,70 @@ +/* + * ==================================================================== + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.client.cache; + +import java.io.IOException; + +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.ProtocolVersion; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpExecutionAware; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.impl.client.execchain.ClientExecChain; +import org.apache.http.message.BasicHttpResponse; + +public class DummyBackend implements ClientExecChain { + + private HttpRequest request; + private HttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP",1,1), HttpStatus.SC_OK, "OK"); + private int executions = 0; + + public void setResponse(HttpResponse resp) { + response = resp; + } + + public HttpRequest getCapturedRequest() { + return request; + } + + public CloseableHttpResponse execute( + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext clientContext, + final HttpExecutionAware execAware) throws IOException, HttpException { + this.request = request; + executions++; + return Proxies.enhanceResponse(response); + } + + public int getExecutions() { + return executions; + } +} diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DummyHttpClient.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DummyHttpClient.java deleted file mode 100644 index b829c6bcc..000000000 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DummyHttpClient.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * ==================================================================== - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.http.impl.client.cache; - -import java.io.IOException; - -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.ProtocolVersion; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.impl.conn.SingleClientConnManager; -import org.apache.http.message.BasicHttpResponse; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpParams; -import org.apache.http.protocol.HttpContext; - -@SuppressWarnings("deprecation") -public class DummyHttpClient implements HttpClient { - - private HttpParams params = new BasicHttpParams(); - private ClientConnectionManager connManager = new SingleClientConnManager(); - private HttpRequest request; - private HttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP",1,1), HttpStatus.SC_OK, "OK"); - private int executions = 0; - - public void setParams(HttpParams params) { - this.params = params; - } - - public HttpParams getParams() { - return params; - } - - public ClientConnectionManager getConnectionManager() { - return connManager; - } - - public void setConnectionManager(ClientConnectionManager ccm) { - connManager = ccm; - } - - public void setResponse(HttpResponse resp) { - response = resp; - } - - public HttpRequest getCapturedRequest() { - return request; - } - - public HttpResponse execute(HttpUriRequest request) throws IOException, - ClientProtocolException { - this.request = request; - executions++; - return response; - } - - public HttpResponse execute(HttpUriRequest request, HttpContext context) - throws IOException, ClientProtocolException { - this.request = request; - executions++; - return response; - } - - public HttpResponse execute(HttpHost target, HttpRequest request) - throws IOException, ClientProtocolException { - this.request = request; - executions++; - return response; - } - - public HttpResponse execute(HttpHost target, HttpRequest request, - HttpContext context) throws IOException, ClientProtocolException { - this.request = request; - executions++; - return response; - } - - public T execute(HttpUriRequest request, - ResponseHandler responseHandler) throws IOException, - ClientProtocolException { - this.request = request; - executions++; - return responseHandler.handleResponse(response); - } - - public T execute(HttpUriRequest request, - ResponseHandler responseHandler, HttpContext context) - throws IOException, ClientProtocolException { - this.request = request; - executions++; - return responseHandler.handleResponse(response); - } - - public T execute(HttpHost target, HttpRequest request, - ResponseHandler responseHandler) throws IOException, - ClientProtocolException { - this.request = request; - executions++; - return responseHandler.handleResponse(response); - } - - public T execute(HttpHost target, HttpRequest request, - ResponseHandler responseHandler, HttpContext context) - throws IOException, ClientProtocolException { - this.request = request; - executions++; - return responseHandler.handleResponse(response); - } - - public int getExecutions() { - return executions; - } -} diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidationRequest.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidationRequest.java index 41e5c6fa8..fe186092e 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidationRequest.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidationRequest.java @@ -31,9 +31,11 @@ import java.io.IOException; import org.apache.http.HttpHost; import org.apache.http.ProtocolException; import org.apache.http.client.cache.HttpCacheEntry; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestWrapper; -import org.apache.http.protocol.HttpContext; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; import org.easymock.classextension.EasyMock; import org.junit.Before; import org.junit.Test; @@ -41,51 +43,36 @@ import org.junit.Test; public class TestAsynchronousValidationRequest { private AsynchronousValidator mockParent; - private CachingHttpClient mockClient; - private HttpHost target; + private CachingExec mockClient; + private HttpRoute route; private HttpRequestWrapper request; - private HttpContext mockContext; + private HttpClientContext context; + private HttpExecutionAware mockExecAware; private HttpCacheEntry mockCacheEntry; @Before public void setUp() { mockParent = EasyMock.createNiceMock(AsynchronousValidator.class); - mockClient = EasyMock.createNiceMock(CachingHttpClient.class); - target = new HttpHost("foo.example.com"); + mockClient = EasyMock.createNiceMock(CachingExec.class); + route = new HttpRoute(new HttpHost("foo.example.com")); request = HttpRequestWrapper.wrap(new HttpGet("/")); - mockContext = EasyMock.createNiceMock(HttpContext.class); + context = HttpClientContext.create(); + mockExecAware = EasyMock.createNiceMock(HttpExecutionAware.class); mockCacheEntry = EasyMock.createNiceMock(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 { + public void testRunCallsCachingClientAndRemovesIdentifier() throws Exception { String identifier = "foo"; AsynchronousValidationRequest impl = new AsynchronousValidationRequest( - mockParent, mockClient, target, request, mockContext, mockCacheEntry, + mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, identifier); // response not used EasyMock.expect( - mockClient.revalidateCacheEntry(target, request, mockContext, - mockCacheEntry)).andThrow(new ProtocolException()); + mockClient.revalidateCacheEntry( + route, request, context, mockExecAware, mockCacheEntry)).andReturn(null); mockParent.markComplete(identifier); replayMocks(); @@ -94,17 +81,38 @@ public class TestAsynchronousValidationRequest { } @Test - public void testRunGracefullyHandlesIOException() throws IOException, ProtocolException { + public void testRunGracefullyHandlesProtocolException() throws Exception { String identifier = "foo"; AsynchronousValidationRequest impl = new AsynchronousValidationRequest( - mockParent, mockClient, target, request, mockContext, mockCacheEntry, + mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, identifier); // response not used EasyMock.expect( - mockClient.revalidateCacheEntry(target, request, mockContext, - mockCacheEntry)).andThrow(new IOException()); + mockClient.revalidateCacheEntry( + route, request, context, mockExecAware, mockCacheEntry)).andThrow( + new ProtocolException()); + mockParent.markComplete(identifier); + + replayMocks(); + impl.run(); + verifyMocks(); + } + + @Test + public void testRunGracefullyHandlesIOException() throws Exception { + String identifier = "foo"; + + AsynchronousValidationRequest impl = new AsynchronousValidationRequest( + mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, + identifier); + + // response not used + EasyMock.expect( + mockClient.revalidateCacheEntry( + route, request, context, mockExecAware, mockCacheEntry)).andThrow( + new IOException()); mockParent.markComplete(identifier); replayMocks(); @@ -114,13 +122,13 @@ public class TestAsynchronousValidationRequest { public void replayMocks() { EasyMock.replay(mockClient); - EasyMock.replay(mockContext); + EasyMock.replay(mockExecAware); EasyMock.replay(mockCacheEntry); } public void verifyMocks() { EasyMock.verify(mockClient); - EasyMock.verify(mockContext); + EasyMock.verify(mockExecAware); EasyMock.verify(mockCacheEntry); } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java index 67e280425..b860ab7a4 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java @@ -26,7 +26,6 @@ */ package org.apache.http.impl.client.cache; -import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; @@ -36,13 +35,14 @@ import junit.framework.Assert; import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.ProtocolException; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheEntry; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; import org.apache.http.message.BasicHeader; -import org.apache.http.protocol.HttpContext; import org.easymock.Capture; import org.easymock.classextension.EasyMock; import org.junit.Before; @@ -52,22 +52,23 @@ public class TestAsynchronousValidator { private AsynchronousValidator impl; - private CachingHttpClient mockClient; - private HttpHost target; + private CachingExec mockClient; + private HttpRoute route; private HttpRequestWrapper request; - private HttpContext mockContext; + private HttpClientContext context; + private HttpExecutionAware mockExecAware; private HttpCacheEntry mockCacheEntry; private ExecutorService mockExecutor; @Before public void setUp() { - mockClient = EasyMock.createNiceMock(CachingHttpClient.class); - target = new HttpHost("foo.example.com"); + mockClient = EasyMock.createNiceMock(CachingExec.class); + route = new HttpRoute(new HttpHost("foo.example.com")); request = HttpRequestWrapper.wrap(new HttpGet("/")); - mockContext = EasyMock.createNiceMock(HttpContext.class); + context = HttpClientContext.create(); + mockExecAware = EasyMock.createNiceMock(HttpExecutionAware.class); mockCacheEntry = EasyMock.createNiceMock(HttpCacheEntry.class); - mockExecutor = EasyMock.createNiceMock(ExecutorService.class); } @@ -80,7 +81,7 @@ public class TestAsynchronousValidator { mockExecutor.execute(EasyMock.isA(AsynchronousValidationRequest.class)); replayMocks(); - impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry); + impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry); verifyMocks(); Assert.assertEquals(1, impl.getScheduledIdentifiers().size()); @@ -95,7 +96,7 @@ public class TestAsynchronousValidator { mockExecutor.execute(EasyMock.capture(cap)); replayMocks(); - impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry); + impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry); verifyMocks(); Assert.assertEquals(1, impl.getScheduledIdentifiers().size()); @@ -114,7 +115,7 @@ public class TestAsynchronousValidator { EasyMock.expectLastCall().andThrow(new RejectedExecutionException()); replayMocks(); - impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry); + impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry); verifyMocks(); Assert.assertEquals(0, impl.getScheduledIdentifiers().size()); @@ -130,8 +131,8 @@ public class TestAsynchronousValidator { EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false); replayMocks(); - impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry); - impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry); + impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry); + impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry); verifyMocks(); Assert.assertEquals(1, impl.getScheduledIdentifiers().size()); @@ -157,8 +158,8 @@ public class TestAsynchronousValidator { EasyMock.expectLastCall().times(2); replayMocks(); - impl.revalidateCacheEntry(target, HttpRequestWrapper.wrap(req1), mockContext, mockCacheEntry); - impl.revalidateCacheEntry(target, HttpRequestWrapper.wrap(req2), mockContext, mockCacheEntry); + impl.revalidateCacheEntry(route, HttpRequestWrapper.wrap(req1), context, mockExecAware, mockCacheEntry); + impl.revalidateCacheEntry(route, HttpRequestWrapper.wrap(req2), context, mockExecAware, mockCacheEntry); verifyMocks(); Assert.assertEquals(2, impl.getScheduledIdentifiers().size()); @@ -166,7 +167,7 @@ public class TestAsynchronousValidator { } @Test - public void testRevalidateCacheEntryEndToEnd() throws ProtocolException, IOException { + public void testRevalidateCacheEntryEndToEnd() throws Exception { CacheConfig config = CacheConfig.custom() .setAsynchronousWorkersMax(1) .setAsynchronousWorkersCore(1) @@ -174,10 +175,11 @@ public class TestAsynchronousValidator { impl = new AsynchronousValidator(mockClient, config); EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false); - EasyMock.expect(mockClient.revalidateCacheEntry(target, request, mockContext, mockCacheEntry)).andReturn(null); + EasyMock.expect(mockClient.revalidateCacheEntry( + route, request, context, mockExecAware, mockCacheEntry)).andReturn(null); replayMocks(); - impl.revalidateCacheEntry(target, request, mockContext, mockCacheEntry); + impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry); try { // shut down backend executor and make sure all finishes properly, 1 second should be sufficient @@ -196,14 +198,14 @@ public class TestAsynchronousValidator { public void replayMocks() { EasyMock.replay(mockExecutor); EasyMock.replay(mockClient); - EasyMock.replay(mockContext); + EasyMock.replay(mockExecAware); EasyMock.replay(mockCacheEntry); } public void verifyMocks() { EasyMock.verify(mockExecutor); EasyMock.verify(mockClient); - EasyMock.verify(mockContext); + EasyMock.verify(mockExecAware); EasyMock.verify(mockCacheEntry); } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java similarity index 53% rename from httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java rename to httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java index 391866d98..518153eaf 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java @@ -27,12 +27,12 @@ package org.apache.http.impl.client.cache; import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.isA; import static org.easymock.EasyMock.isNull; import static org.easymock.EasyMock.same; +import static org.easymock.EasyMock.eq; import static org.easymock.classextension.EasyMock.createMockBuilder; import static org.easymock.classextension.EasyMock.createNiceMock; import static org.easymock.classextension.EasyMock.replay; @@ -42,9 +42,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.net.URI; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -52,38 +50,38 @@ import java.util.List; import java.util.Map; import org.apache.http.Header; -import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; -import org.apache.http.ProtocolException; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.cache.CacheResponseStatus; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.cache.HttpCacheStorage; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.entity.InputStreamEntity; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.impl.client.execchain.ClientExecChain; import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHttpRequest; import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.ExecutionContext; -import org.apache.http.protocol.HttpContext; import org.easymock.Capture; +import org.easymock.IExpectationSetters; +import org.easymock.classextension.EasyMock; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -public class TestCachingHttpClient { +public class TestCachingExec { private static final String GET_CURRENT_DATE = "getCurrentDate"; @@ -93,78 +91,80 @@ public class TestCachingHttpClient { private static final String REVALIDATE_CACHE_ENTRY = "revalidateCacheEntry"; - private CachingHttpClient impl; + private CachingExec impl; private boolean mockedImpl; private CacheValidityPolicy mockValidityPolicy; private CacheableRequestPolicy mockRequestPolicy; - private HttpClient mockBackend; + private ClientExecChain mockBackend; private HttpCache mockCache; private HttpCacheStorage mockStorage; private CachedResponseSuitabilityChecker mockSuitabilityChecker; private ResponseCachingPolicy mockResponsePolicy; - private HttpResponse mockBackendResponse; + private CloseableHttpResponse mockBackendResponse; private HttpCacheEntry mockCacheEntry; private CachedHttpResponseGenerator mockResponseGenerator; - private ClientConnectionManager mockConnectionManager; private ResponseHandler mockHandler; private HttpUriRequest mockUriRequest; - private HttpResponse mockCachedResponse; + private CloseableHttpResponse mockCachedResponse; private ConditionalRequestBuilder mockConditionalRequestBuilder; private HttpRequest mockConditionalRequest; private StatusLine mockStatusLine; private ResponseProtocolCompliance mockResponseProtocolCompliance; private RequestProtocolCompliance mockRequestProtocolCompliance; + private CacheConfig config; private Date requestDate; private Date responseDate; + private HttpRoute route; private HttpHost host; private HttpRequestWrapper request; - private HttpContext context; + private HttpClientContext context; private HttpCacheEntry entry; - private ConsumableInputStream cis; @SuppressWarnings("unchecked") @Before public void setUp() { mockRequestPolicy = createNiceMock(CacheableRequestPolicy.class); mockValidityPolicy = createNiceMock(CacheValidityPolicy.class); - mockBackend = createNiceMock(HttpClient.class); + mockBackend = createNiceMock(ClientExecChain.class); mockCache = createNiceMock(HttpCache.class); mockSuitabilityChecker = createNiceMock(CachedResponseSuitabilityChecker.class); mockResponsePolicy = createNiceMock(ResponseCachingPolicy.class); - mockConnectionManager = createNiceMock(ClientConnectionManager.class); mockHandler = createNiceMock(ResponseHandler.class); - mockBackendResponse = createNiceMock(HttpResponse.class); + mockBackendResponse = createNiceMock(CloseableHttpResponse.class); mockUriRequest = createNiceMock(HttpUriRequest.class); mockCacheEntry = createNiceMock(HttpCacheEntry.class); mockResponseGenerator = createNiceMock(CachedHttpResponseGenerator.class); - mockCachedResponse = createNiceMock(HttpResponse.class); + mockCachedResponse = createNiceMock(CloseableHttpResponse.class); mockConditionalRequestBuilder = createNiceMock(ConditionalRequestBuilder.class); mockConditionalRequest = createNiceMock(HttpRequest.class); mockStatusLine = createNiceMock(StatusLine.class); mockResponseProtocolCompliance = createNiceMock(ResponseProtocolCompliance.class); mockRequestProtocolCompliance = createNiceMock(RequestProtocolCompliance.class); mockStorage = createNiceMock(HttpCacheStorage.class); + config = CacheConfig.DEFAULT; requestDate = new Date(System.currentTimeMillis() - 1000); responseDate = new Date(); host = new HttpHost("foo.example.com"); + route = new HttpRoute(host); request = HttpRequestWrapper.wrap( new BasicHttpRequest("GET", "/stuff", HttpVersion.HTTP_1_1)); - context = new BasicHttpContext(); + context = HttpClientContext.create(); entry = HttpTestUtils.makeCacheEntry(); - impl = new CachingHttpClient( + impl = new CachingExec( mockBackend, + mockCache, mockValidityPolicy, mockResponsePolicy, - mockCache, mockResponseGenerator, mockRequestPolicy, mockSuitabilityChecker, mockConditionalRequestBuilder, mockResponseProtocolCompliance, - mockRequestProtocolCompliance); + mockRequestProtocolCompliance, + config); } private void replayMocks() { @@ -176,7 +176,6 @@ public class TestCachingHttpClient { replay(mockResponseGenerator); replay(mockBackend); replay(mockCache); - replay(mockConnectionManager); replay(mockHandler); replay(mockBackendResponse); replay(mockUriRequest); @@ -201,7 +200,6 @@ public class TestCachingHttpClient { verify(mockResponseGenerator); verify(mockBackend); verify(mockCache); - verify(mockConnectionManager); verify(mockHandler); verify(mockBackendResponse); verify(mockUriRequest); @@ -219,54 +217,51 @@ public class TestCachingHttpClient { @Test public void testCacheableResponsesGoIntoCache() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(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); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @Test public void testOlderCacheableResponsesDoNotGoIntoCache() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); Date now = new Date(); Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Etag", "\"new-etag\""); - expect(mockBackend.execute(isA(HttpHost.class), isA(HttpRequest.class), - (HttpContext)isNull())).andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control","no-cache"); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag", "\"old-etag\""); resp2.setHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); resp2.setHeader("Cache-Control","max-age=3600"); - expect(mockBackend.execute(isA(HttpHost.class), isA(HttpRequest.class), - (HttpContext)isNull())).andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); @@ -274,35 +269,33 @@ public class TestCachingHttpClient { @Test public void testNewerCacheableResponsesReplaceExistingCacheEntry() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); Date now = new Date(); Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Etag", "\"old-etag\""); - expect(mockBackend.execute(isA(HttpHost.class), isA(HttpRequest.class), - (HttpContext)isNull())).andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control","max-age=0"); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag", "\"new-etag\""); resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Cache-Control","max-age=3600"); - expect(mockBackend.execute(isA(HttpHost.class), isA(HttpRequest.class), - (HttpContext)isNull())).andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); @@ -315,11 +308,11 @@ public class TestCachingHttpClient { requestPolicyAllowsCaching(false); mockImplMethods(CALL_BACKEND); - callBackendReturnsResponse(mockBackendResponse); + implExpectsAnyRequestAndReturn(mockBackendResponse); requestIsFatallyNonCompliant(null); replayMocks(); - HttpResponse result = impl.execute(host, request, context); + HttpResponse result = impl.execute(route, request, context); verifyMocks(); Assert.assertSame(mockBackendResponse, result); @@ -345,10 +338,10 @@ public class TestCachingHttpClient { requestIsFatallyNonCompliant(null); - callBackendReturnsResponse(mockBackendResponse); + implExpectsAnyRequestAndReturn(mockBackendResponse); replayMocks(); - HttpResponse result = impl.execute(host, request, context); + HttpResponse result = impl.execute(route, request, context); verifyMocks(); Assert.assertSame(mockBackendResponse, result); @@ -367,10 +360,10 @@ public class TestCachingHttpClient { getCacheEntryReturns(mockCacheEntry); cacheEntrySuitable(false); cacheEntryValidatable(false); - callBackendReturnsResponse(mockBackendResponse); + implExpectsAnyRequestAndReturn(mockBackendResponse); replayMocks(); - HttpResponse result = impl.execute(host, request, context); + HttpResponse result = impl.execute(route, request, context); verifyMocks(); Assert.assertSame(mockBackendResponse, result); @@ -392,10 +385,16 @@ public class TestCachingHttpClient { cacheEntryMustRevalidate(false); cacheEntryProxyRevalidate(false); mayReturnStaleWhileRevalidating(false); - revalidateCacheEntryReturns(mockBackendResponse); + + expect(impl.revalidateCacheEntry( + isA(HttpRoute.class), + isA(HttpRequestWrapper.class), + isA(HttpClientContext.class), + (HttpExecutionAware) isNull(), + isA(HttpCacheEntry.class))).andReturn(mockBackendResponse); replayMocks(); - HttpResponse result = impl.execute(host, request, context); + HttpResponse result = impl.execute(route, request, context); verifyMocks(); Assert.assertSame(mockBackendResponse, result); @@ -408,24 +407,29 @@ public class TestCachingHttpClient { public void testRevalidationCallsHandleBackEndResponseWhenNot200Or304() throws Exception { mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE); - HttpRequestWrapper validate = - HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpResponse originResponse = - new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_NOT_FOUND, "Not Found"); - HttpResponse finalResponse = HttpTestUtils.make200Response(); + HttpRequestWrapper validate = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + CloseableHttpResponse originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_FOUND, "Not Found")); + CloseableHttpResponse finalResponse = Proxies.enhanceResponse( + HttpTestUtils.make200Response()); conditionalRequestBuilderReturns(validate); getCurrentDateReturns(requestDate); - backendCall(validate, originResponse); + backendExpectsRequestAndReturn(validate, originResponse); getCurrentDateReturns(responseDate); - expect(impl.handleBackendResponse(host, validate, - requestDate, responseDate, originResponse)) - .andReturn(finalResponse); + expect(impl.handleBackendResponse( + eq(route), + same(validate), + same(context), + (HttpExecutionAware) isNull(), + eq(requestDate), + eq(responseDate), + same(originResponse))).andReturn(finalResponse); replayMocks(); HttpResponse result = - impl.revalidateCacheEntry(host, request, context, entry); + impl.revalidateCacheEntry(route, request, context, null, entry); verifyMocks(); Assert.assertSame(finalResponse, result); @@ -437,25 +441,29 @@ public class TestCachingHttpClient { mockImplMethods(GET_CURRENT_DATE); - HttpRequestWrapper validate = - HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpResponse originResponse = - new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + HttpRequestWrapper validate = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpResponse originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified")); HttpCacheEntry updatedEntry = HttpTestUtils.makeCacheEntry(); conditionalRequestBuilderReturns(validate); getCurrentDateReturns(requestDate); - backendCall(validate, originResponse); + backendExpectsRequestAndReturn(validate, originResponse); getCurrentDateReturns(responseDate); - expect(mockCache.updateCacheEntry(host, request, - entry, originResponse, requestDate, responseDate)) + expect(mockCache.updateCacheEntry( + eq(host), + same(request), + same(entry), + same(originResponse), + eq(requestDate), + eq(responseDate))) .andReturn(updatedEntry); expect(mockSuitabilityChecker.isConditional(request)).andReturn(false); responseIsGeneratedFromCache(); replayMocks(); - impl.revalidateCacheEntry(host, request, context, entry); + impl.revalidateCacheEntry(route, request, context, null, entry); verifyMocks(); } @@ -470,7 +478,7 @@ public class TestCachingHttpClient { entryHasStaleness(0L); replayMocks(); - HttpResponse result = impl.execute(host, request, context); + HttpResponse result = impl.execute(route, request, context); verifyMocks(); Assert.assertSame(mockCachedResponse, result); @@ -481,13 +489,13 @@ public class TestCachingHttpClient { mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE); HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); getCurrentDateReturns(requestDate); - backendCallWasMade(request, resp); + backendExpectsRequestAndReturn(request, resp); getCurrentDateReturns(responseDate); handleBackendResponseReturnsResponse(request, resp); replayMocks(); - impl.callBackend(host, request, context); + impl.callBackend(route, request, context, null); verifyMocks(); } @@ -495,353 +503,26 @@ public class TestCachingHttpClient { @Test public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Exception { CacheConfig config = CacheConfig.DEFAULT; - impl = new CachingHttpClient(mockBackend, + impl = new CachingExec(mockBackend, new BasicHttpCache(new HeapResourceFactory(), mockStorage, config), config); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","no-cache"); expect(mockStorage.getEntry(isA(String.class))).andReturn(null).anyTimes(); mockStorage.removeEntry(isA(String.class)); expectLastCall().anyTimes(); - expect(mockBackend.execute(isA(HttpHost.class), isA(HttpRequest.class), - (HttpContext)isNull())).andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); replayMocks(); - HttpResponse result = impl.execute(host, req1); + HttpResponse result = impl.execute(route, req1); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); } - - @Test - public void testCallsSelfForExecuteOnHostRequestWithNullContext() throws Exception { - final Counter c = new Counter(); - final HttpHost theHost = host; - final HttpRequest theRequest = request; - final HttpResponse theResponse = mockBackendResponse; - impl = new CachingHttpClient( - mockBackend, - mockValidityPolicy, - mockResponsePolicy, - mockCache, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockConditionalRequestBuilder, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance) { - @Override - public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) { - Assert.assertSame(theHost, target); - Assert.assertSame(theRequest, request); - Assert.assertNull(context); - c.incr(); - return theResponse; - } - }; - - replayMocks(); - HttpResponse result = impl.execute(host, request); - verifyMocks(); - Assert.assertSame(mockBackendResponse, result); - Assert.assertEquals(1, c.getCount()); - } - - @Test - public void testCallsSelfWithDefaultContextForExecuteOnHostRequestWithHandler() - throws Exception { - - final Counter c = new Counter(); - final HttpHost theHost = host; - final HttpRequest theRequest = request; - final HttpResponse theResponse = mockBackendResponse; - final ResponseHandler theHandler = mockHandler; - final Object value = new Object(); - impl = new CachingHttpClient( - mockBackend, - mockValidityPolicy, - mockResponsePolicy, - mockCache, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockConditionalRequestBuilder, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance) { - @Override - public T execute(HttpHost target, HttpRequest request, - ResponseHandler rh, HttpContext context) { - Assert.assertSame(theHost, target); - Assert.assertSame(theRequest, request); - Assert.assertSame(theHandler, rh); - Assert.assertNull(context); - c.incr(); - try { - return rh.handleResponse(theResponse); - } catch (Exception wrong) { - throw new RuntimeException("unexpected exn", wrong); - } - } - }; - - expect(mockHandler.handleResponse(mockBackendResponse)).andReturn( - value); - - replayMocks(); - Object result = impl.execute(host, request, mockHandler); - verifyMocks(); - - Assert.assertSame(value, result); - Assert.assertEquals(1, c.getCount()); - } - - @Test - public void testCallsSelfOnExecuteHostRequestWithHandlerAndContext() throws Exception { - - final Counter c = new Counter(); - final HttpHost theHost = host; - final HttpRequest theRequest = request; - final HttpResponse theResponse = mockBackendResponse; - final HttpContext theContext = context; - impl = new CachingHttpClient( - mockBackend, - mockValidityPolicy, - mockResponsePolicy, - mockCache, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockConditionalRequestBuilder, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance) { - @Override - public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) { - Assert.assertSame(theHost, target); - Assert.assertSame(theRequest, request); - Assert.assertSame(theContext, context); - c.incr(); - return theResponse; - } - }; - - final Object theObject = new Object(); - - expect(mockHandler.handleResponse(mockBackendResponse)).andReturn( - theObject); - HttpEntity streamingEntity = makeStreamingEntity(); - expect(theResponse.getEntity()).andReturn(streamingEntity); - replayMocks(); - Object result = impl.execute(host, request, mockHandler, context); - verifyMocks(); - Assert.assertEquals(1, c.getCount()); - Assert.assertSame(theObject, result); - Assert.assertTrue(cis.wasClosed()); - } - - @Test - public void testConsumesEntityOnExecuteWithException() throws Exception { - - final Counter c = new Counter(); - final HttpHost theHost = host; - final HttpRequest theRequest = request; - final HttpResponse theResponse = mockBackendResponse; - final HttpContext theContext = context; - impl = new CachingHttpClient( - mockBackend, - mockValidityPolicy, - mockResponsePolicy, - mockCache, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockConditionalRequestBuilder, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance) { - @Override - public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) { - Assert.assertSame(theHost, target); - Assert.assertSame(theRequest, request); - Assert.assertSame(theContext, context); - c.incr(); - return theResponse; - } - }; - IOException ioException = new IOException("test exception"); - - expect(mockHandler.handleResponse(mockBackendResponse)).andThrow(ioException); - HttpEntity streamingEntity = makeStreamingEntity(); - expect(theResponse.getEntity()).andReturn(streamingEntity).anyTimes(); - - replayMocks(); - Object result = null; - try { - result = impl.execute(host, request, mockHandler, context); - } catch (Exception e) { - assertEquals(ioException, e); - } - verifyMocks(); - Assert.assertEquals(1, c.getCount()); - Assert.assertNull(result); - assertTrue(cis.wasClosed()); - } - - @Test - public void testCallsSelfWithNullContextOnExecuteUriRequest() throws Exception { - final Counter c = new Counter(); - final HttpUriRequest theRequest = mockUriRequest; - final HttpResponse theResponse = mockBackendResponse; - impl = new CachingHttpClient( - mockBackend, - mockValidityPolicy, - mockResponsePolicy, - mockCache, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockConditionalRequestBuilder, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance) { - @Override - public HttpResponse execute(HttpUriRequest request, HttpContext context) { - Assert.assertSame(theRequest, request); - Assert.assertNull(context); - c.incr(); - return theResponse; - } - }; - - replayMocks(); - HttpResponse result = impl.execute(mockUriRequest); - verifyMocks(); - - Assert.assertEquals(1, c.getCount()); - Assert.assertSame(theResponse, result); - } - - @Test - public void testCallsSelfWithExtractedHostOnExecuteUriRequestWithContext() throws Exception { - - final URI uri = new URI("sch://host:8888"); - final Counter c = new Counter(); - final HttpRequest theRequest = mockUriRequest; - final HttpContext theContext = context; - final HttpResponse theResponse = mockBackendResponse; - impl = new CachingHttpClient( - mockBackend, - mockValidityPolicy, - mockResponsePolicy, - mockCache, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockConditionalRequestBuilder, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance) { - @Override - public HttpResponse execute(HttpHost hh, HttpRequest req, HttpContext ctx) { - Assert.assertEquals("sch", hh.getSchemeName()); - Assert.assertEquals("host", hh.getHostName()); - Assert.assertEquals(8888, hh.getPort()); - Assert.assertSame(theRequest, req); - Assert.assertSame(theContext, ctx); - c.incr(); - return theResponse; - } - }; - - expect(mockUriRequest.getURI()).andReturn(uri); - - replayMocks(); - HttpResponse result = impl.execute(mockUriRequest, context); - verifyMocks(); - - Assert.assertEquals(1, c.getCount()); - Assert.assertSame(mockBackendResponse, result); - } - - @Test - public void testCallsSelfWithNullContextOnExecuteUriRequestWithHandler() throws Exception { - final Counter c = new Counter(); - final HttpUriRequest theRequest = mockUriRequest; - final HttpResponse theResponse = mockBackendResponse; - final Object theValue = new Object(); - impl = new CachingHttpClient( - mockBackend, - mockValidityPolicy, - mockResponsePolicy, - mockCache, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockConditionalRequestBuilder, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance) { - @Override - public T execute(HttpUriRequest request, ResponseHandler handler, - HttpContext context) throws IOException { - Assert.assertSame(theRequest, request); - Assert.assertNull(context); - c.incr(); - return handler.handleResponse(theResponse); - } - }; - - expect(mockHandler.handleResponse(mockBackendResponse)).andReturn( - theValue); - - replayMocks(); - Object result = impl.execute(mockUriRequest, mockHandler); - verifyMocks(); - - Assert.assertEquals(1, c.getCount()); - Assert.assertSame(theValue, result); - } - - @Test - public void testCallsSelfAndRunsHandlerOnExecuteUriRequestWithHandlerAndContext() - throws Exception { - - final Counter c = new Counter(); - final HttpUriRequest theRequest = mockUriRequest; - final HttpContext theContext = context; - final HttpResponse theResponse = mockBackendResponse; - final Object theValue = new Object(); - impl = new CachingHttpClient( - mockBackend, - mockValidityPolicy, - mockResponsePolicy, - mockCache, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockConditionalRequestBuilder, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance) { - @Override - public HttpResponse execute(HttpUriRequest request, HttpContext context) - throws IOException { - Assert.assertSame(theRequest, request); - Assert.assertSame(theContext, context); - c.incr(); - return theResponse; - } - }; - expect(mockHandler.handleResponse(mockBackendResponse)).andReturn( - theValue); - HttpEntity streamingEntity = makeStreamingEntity(); - expect(theResponse.getEntity()).andReturn(streamingEntity); - replayMocks(); - Object result = impl.execute(mockUriRequest, mockHandler, context); - verifyMocks(); - Assert.assertEquals(1, c.getCount()); - Assert.assertSame(theValue, result); - Assert.assertTrue(cis.wasClosed()); - } - @Test public void testResponseIsGeneratedWhenCacheEntryIsUsable() throws Exception { @@ -854,7 +535,7 @@ public class TestCachingHttpClient { entryHasStaleness(0L); replayMocks(); - impl.execute(host, request, context); + impl.execute(route, request, context); verifyMocks(); } @@ -870,7 +551,7 @@ public class TestCachingHttpClient { boolean gotException = false; replayMocks(); try { - impl.execute(host, request, context); + impl.execute(route, request, context); } catch (ClientProtocolException ex) { Assert.assertSame(expected, ex); gotException = true; @@ -882,11 +563,11 @@ public class TestCachingHttpClient { @Test public void testSetsModuleGeneratedResponseContextForCacheOptionsResponse() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req = new BasicHttpRequest("OPTIONS","*",HttpVersion.HTTP_1_1); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS","*",HttpVersion.HTTP_1_1)); req.setHeader("Max-Forwards","0"); - impl.execute(host, req, context); + impl.execute(route, req, context); Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, context.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS)); } @@ -894,12 +575,12 @@ public class TestCachingHttpClient { @Test public void testSetsModuleGeneratedResponseContextForFatallyNoncompliantRequest() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); req.setHeader("Range","bytes=0-50"); req.setHeader("If-Range","W/\"weak-etag\""); - impl.execute(host, req, context); + impl.execute(route, req, context); Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, context.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS)); } @@ -907,18 +588,17 @@ public class TestCachingHttpClient { @Test public void testRecordsClientProtocolInViaHeaderIfRequestNotServableFromCache() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_0); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_0)); req.setHeader("Cache-Control","no-cache"); HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - Capture cap = new Capture(); + Capture cap = new Capture(); - expect(mockBackend.execute(isA(HttpHost.class), - capture(cap), isA(HttpContext.class))) - .andReturn(resp); + backendCaptureRequestAndReturn(cap, resp); replayMocks(); - impl.execute(host, req, context); + impl.execute(route, req, context); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -931,17 +611,15 @@ public class TestCachingHttpClient { @Test public void testSetsCacheMissContextIfRequestNotServableFromCache() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); req.setHeader("Cache-Control","no-cache"); HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andReturn(resp); + backendExpectsAnyRequestAndReturn(resp); replayMocks(); - impl.execute(host, req, context); + impl.execute(route, req, context); verifyMocks(); Assert.assertEquals(CacheResponseStatus.CACHE_MISS, context.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS)); @@ -950,17 +628,15 @@ public class TestCachingHttpClient { @Test public void testSetsViaHeaderOnResponseIfRequestNotServableFromCache() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); req.setHeader("Cache-Control","no-cache"); HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext)isNull())) - .andReturn(resp); + backendExpectsAnyRequestAndReturn(resp); replayMocks(); - HttpResponse result = impl.execute(host, req); + HttpResponse result = impl.execute(route, req); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @@ -968,8 +644,8 @@ public class TestCachingHttpClient { @Test public void testSetsViaHeaderOnResponseForCacheMiss() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length","128"); @@ -977,12 +653,10 @@ public class TestCachingHttpClient { resp1.setHeader("Date", DateUtils.formatDate(new Date())); resp1.setHeader("Cache-Control","public, max-age=3600"); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); replayMocks(); - HttpResponse result = impl.execute(host, req1, new BasicHttpContext()); + HttpResponse result = impl.execute(route, req1); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @@ -990,9 +664,9 @@ public class TestCachingHttpClient { @Test public void testSetsCacheHitContextIfRequestServedFromCache() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length","128"); @@ -1000,13 +674,11 @@ public class TestCachingHttpClient { resp1.setHeader("Date", DateUtils.formatDate(new Date())); resp1.setHeader("Cache-Control","public, max-age=3600"); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); replayMocks(); - impl.execute(host, req1, new BasicHttpContext()); - impl.execute(host, req2, context); + impl.execute(route, req1); + impl.execute(route, req2, context); verifyMocks(); Assert.assertEquals(CacheResponseStatus.CACHE_HIT, context.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS)); @@ -1015,9 +687,9 @@ public class TestCachingHttpClient { @Test public void testSetsViaHeaderOnResponseIfRequestServedFromCache() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length","128"); @@ -1025,13 +697,11 @@ public class TestCachingHttpClient { resp1.setHeader("Date", DateUtils.formatDate(new Date())); resp1.setHeader("Cache-Control","public, max-age=3600"); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext)isNull())) - .andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @@ -1041,9 +711,9 @@ public class TestCachingHttpClient { throws Exception { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1054,14 +724,11 @@ public class TestCachingHttpClient { resp1.setHeader("Cache-Control", "public, max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); @@ -1071,9 +738,9 @@ public class TestCachingHttpClient { public void testReturns200ForIfModifiedSinceDateIsLess() throws Exception { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1090,19 +757,12 @@ public class TestCachingHttpClient { HttpResponse resp2 = HttpTestUtils.make200Response(); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), - (HttpContext) isNull())) - .andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -1113,9 +773,9 @@ public class TestCachingHttpClient { throws Exception { Date now = new Date(); Date tenSecondsAfter = new Date(now.getTime() + 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1130,14 +790,11 @@ public class TestCachingHttpClient { req2.addHeader("If-Modified-Since", DateUtils .formatDate(tenSecondsAfter)); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1).times(2); + backendExpectsAnyRequestAndReturn(resp1).times(2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -1146,9 +803,9 @@ public class TestCachingHttpClient { @Test public void testReturns304ForIfNoneMatchHeaderIfRequestServedFromCache() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); req2.addHeader("If-None-Match", "*"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1158,14 +815,11 @@ public class TestCachingHttpClient { resp1.setHeader("Date", DateUtils.formatDate(new Date())); resp1.setHeader("Cache-Control", "public, max-age=3600"); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); @@ -1173,9 +827,9 @@ public class TestCachingHttpClient { @Test public void testReturns200ForIfNoneMatchHeaderFails() throws Exception { - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1189,18 +843,12 @@ public class TestCachingHttpClient { HttpResponse resp2 = HttpTestUtils.make200Response(); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(200, result.getStatusLine().getStatusCode()); @@ -1209,11 +857,11 @@ public class TestCachingHttpClient { @Test public void testReturns304ForIfNoneMatchHeaderAndIfModifiedSinceIfRequestServedFromCache() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1227,14 +875,11 @@ public class TestCachingHttpClient { req2.addHeader("If-None-Match", "*"); req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); @@ -1243,11 +888,11 @@ public class TestCachingHttpClient { @Test public void testReturns200ForIfNoneMatchHeaderFailsIfModifiedSinceIgnored() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); req2.addHeader("If-None-Match", "\"abc\""); req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, @@ -1259,18 +904,12 @@ public class TestCachingHttpClient { resp1.setHeader("Cache-Control", "public, max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(200, result.getStatusLine().getStatusCode()); @@ -1282,9 +921,9 @@ public class TestCachingHttpClient { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); @@ -1300,16 +939,12 @@ 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), isA(HttpContext.class))) - .andReturn(resp1); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1, new BasicHttpContext()); - impl.execute(host, req2, context); + impl.execute(route, req1); + impl.execute(route, req2, context); verifyMocks(); Assert.assertEquals(CacheResponseStatus.VALIDATED, context.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS)); @@ -1321,9 +956,9 @@ public class TestCachingHttpClient { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); @@ -1339,16 +974,12 @@ 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), isA(HttpContext.class))) - .andReturn(resp1); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1, new BasicHttpContext()); - HttpResponse result = impl.execute(host, req2, context); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2, context); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @@ -1360,9 +991,9 @@ public class TestCachingHttpClient { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); @@ -1371,16 +1002,12 @@ public class TestCachingHttpClient { resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","public, max-age=5, must-revalidate"); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andReturn(resp1); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andThrow(new IOException()); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndThrows(new IOException()); replayMocks(); - impl.execute(host, req1, new BasicHttpContext()); - impl.execute(host, req2, context); + impl.execute(route, req1); + impl.execute(route, req2, context); verifyMocks(); Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, context.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS)); @@ -1392,9 +1019,9 @@ public class TestCachingHttpClient { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); @@ -1403,16 +1030,12 @@ public class TestCachingHttpClient { resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","public, max-age=5"); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andReturn(resp1); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andThrow(new IOException()); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndThrows(new IOException()); replayMocks(); - impl.execute(host, req1, new BasicHttpContext()); - impl.execute(host, req2, context); + impl.execute(route, req1); + impl.execute(route, req2, context); verifyMocks(); Assert.assertEquals(CacheResponseStatus.CACHE_HIT, context.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS)); @@ -1424,9 +1047,9 @@ public class TestCachingHttpClient { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); @@ -1435,16 +1058,12 @@ public class TestCachingHttpClient { resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","public, max-age=5"); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andReturn(resp1); - expect(mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), isA(HttpContext.class))) - .andThrow(new IOException()); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndThrows(new IOException()); replayMocks(); - impl.execute(host, req1, new BasicHttpContext()); - HttpResponse result = impl.execute(host, req2, context); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2, context); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @@ -1456,9 +1075,9 @@ public class TestCachingHttpClient { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1474,18 +1093,12 @@ public class TestCachingHttpClient { resp2.setHeader("ETag", "\"etag\""); resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Cache-Control", "public, max-age=5"); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); @@ -1498,9 +1111,9 @@ public class TestCachingHttpClient { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingHttpClient(mockBackend); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1518,18 +1131,13 @@ public class TestCachingHttpClient { resp2.setHeader("ETag", "\"newetag\""); resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp2.setHeader("Cache-Control", "public, max-age=5"); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -1538,13 +1146,13 @@ public class TestCachingHttpClient { @Test public void testReturns304ForIfModifiedSincePassesIfRequestServedFromOrigin() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1562,18 +1170,13 @@ public class TestCachingHttpClient { resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); 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) - isNull())).andReturn(resp1); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); @@ -1582,12 +1185,12 @@ public class TestCachingHttpClient { @Test public void testReturns200ForIfModifiedSinceFailsIfRequestServedFromOrigin() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = new HttpGet("http://foo.example.com/"); - HttpRequest req2 = new HttpGet("http://foo.example.com/"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1607,18 +1210,13 @@ public class TestCachingHttpClient { resp2.setHeader("Date", DateUtils.formatDate(now)); 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) - isNull())).andReturn(resp1); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -1626,10 +1224,10 @@ public class TestCachingHttpClient { @Test public void testVariantMissServerIfReturns304CacheReturns200() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); Date now = new Date(); - HttpRequest req1 = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req1.addHeader("Accept-Encoding", "gzip"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1640,10 +1238,10 @@ public class TestCachingHttpClient { resp1.setHeader("Vary", "Accept-Encoding"); resp1.setHeader("Cache-Control", "public, max-age=3600"); - HttpRequest req2 = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req2.addHeader("Accept-Encoding", "deflate"); - HttpRequest req2Server = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req2Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req2Server.addHeader("Accept-Encoding", "deflate"); req2Server.addHeader("If-None-Match", "\"gzip_etag\""); @@ -1655,10 +1253,10 @@ public class TestCachingHttpClient { resp2.setHeader("Vary", "Accept-Encoding"); resp2.setHeader("Cache-Control", "public, max-age=3600"); - HttpRequest req3 = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req3.addHeader("Accept-Encoding", "gzip,deflate"); - HttpRequest req3Server = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req3Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req3Server.addHeader("Accept-Encoding", "gzip,deflate"); req3Server.addHeader("If-None-Match", "\"gzip_etag\",\"deflate_etag\""); @@ -1670,28 +1268,16 @@ public class TestCachingHttpClient { resp3.setHeader("Vary", "Accept-Encoding"); resp3.setHeader("Cache-Control", "public, max-age=3600"); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); - - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp2); - - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp3); - + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - HttpResponse result1 = impl.execute(host, req1); + HttpResponse result1 = impl.execute(route, req1); - HttpResponse result2 = impl.execute(host, req2); + HttpResponse result2 = impl.execute(route, req2); - HttpResponse result3 = impl.execute(host, req3); + HttpResponse result3 = impl.execute(route, req3); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result1.getStatusLine().getStatusCode()); @@ -1701,10 +1287,10 @@ public class TestCachingHttpClient { @Test public void testVariantsMissServerReturns304CacheReturns304() throws Exception { - impl = new CachingHttpClient(mockBackend); + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); Date now = new Date(); - HttpRequest req1 = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req1.addHeader("Accept-Encoding", "gzip"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -1715,10 +1301,10 @@ public class TestCachingHttpClient { resp1.setHeader("Vary", "Accept-Encoding"); resp1.setHeader("Cache-Control", "public, max-age=3600"); - HttpRequest req2 = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req2.addHeader("Accept-Encoding", "deflate"); - HttpRequest req2Server = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req2Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req2Server.addHeader("Accept-Encoding", "deflate"); req2Server.addHeader("If-None-Match", "\"gzip_etag\""); @@ -1730,11 +1316,11 @@ public class TestCachingHttpClient { resp2.setHeader("Vary", "Accept-Encoding"); resp2.setHeader("Cache-Control", "public, max-age=3600"); - HttpRequest req4 = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req4 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req4.addHeader("Accept-Encoding", "gzip,identity"); req4.addHeader("If-None-Match", "\"gzip_etag\""); - HttpRequest req4Server = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req4Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); req4Server.addHeader("Accept-Encoding", "gzip,identity"); req4Server.addHeader("If-None-Match", "\"gzip_etag\""); @@ -1744,27 +1330,16 @@ public class TestCachingHttpClient { resp4.setHeader("Vary", "Accept-Encoding"); resp4.setHeader("Cache-Control", "public, max-age=3600"); - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp1); - - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp2); - - expect( - mockBackend.execute(isA(HttpHost.class), - isA(HttpRequest.class), (HttpContext) - isNull())).andReturn(resp4); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + backendExpectsAnyRequestAndReturn(resp4); replayMocks(); - HttpResponse result1 = impl.execute(host, req1); + HttpResponse result1 = impl.execute(route, req1); - HttpResponse result2 = impl.execute(host, req2); + HttpResponse result2 = impl.execute(route, req2); - HttpResponse result4 = impl.execute(host, req4); + HttpResponse result4 = impl.execute(route, req4); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result1.getStatusLine().getStatusCode()); Assert.assertEquals(HttpStatus.SC_OK, result2.getStatusLine().getStatusCode()); @@ -1774,15 +1349,15 @@ public class TestCachingHttpClient { @Test public void testIsSharedCache() { - Assert.assertTrue(impl.isSharedCache()); + Assert.assertTrue(config.isSharedCache()); } @Test public void testTreatsCacheIOExceptionsAsCacheMiss() throws Exception { - impl = new CachingHttpClient(mockBackend, mockCache, CacheConfig.DEFAULT); - HttpResponse resp = HttpTestUtils.make200Response(); + impl = new CachingExec(mockBackend, mockCache, CacheConfig.DEFAULT); + CloseableHttpResponse resp = Proxies.enhanceResponse(HttpTestUtils.make200Response()); mockCache.flushInvalidatedCacheEntriesFor(host, request); expectLastCall().andThrow(new IOException()).anyTimes(); @@ -1798,23 +1373,25 @@ public class TestCachingHttpClient { isA(HttpRequest.class), isA(HttpResponse.class), isA(Date.class), isA(Date.class))) .andThrow(new IOException()).anyTimes(); - expect(mockBackend.execute(same(host), - isA(HttpRequest.class), (HttpContext)isNull())) - .andReturn(resp); + expect(mockBackend.execute( + same(route), + isA(HttpRequestWrapper.class), + isA(HttpClientContext.class), + (HttpExecutionAware) isNull())).andReturn(resp); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertSame(resp, result); } @Test - public void testIfOnlyIfCachedAndNoCacheEntryBackendNotCalled() throws IOException { - impl = new CachingHttpClient(mockBackend); + public void testIfOnlyIfCachedAndNoCacheEntryBackendNotCalled() throws Exception { + impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); request.addHeader("Cache-Control", "only-if-cached"); - HttpResponse resp = impl.execute(host, request); + HttpResponse resp = impl.execute(route, request); Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getStatusLine().getStatusCode()); } @@ -1833,7 +1410,7 @@ public class TestCachingHttpClient { cacheEntrySuitable(false); replayMocks(); - HttpResponse resp = impl.execute(host, request); + HttpResponse resp = impl.execute(route, request); verifyMocks(); Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getStatusLine().getStatusCode()); @@ -1853,155 +1430,163 @@ public class TestCachingHttpClient { entryHasStaleness(0); replayMocks(); - HttpResponse resp = impl.execute(host, request); + HttpResponse resp = impl.execute(route, request); verifyMocks(); Assert.assertSame(mockCachedResponse, resp); } - - private DummyHttpClient getContextSettingBackend(final Object value, final HttpResponse response) { - return new DummyHttpClient() { - @Override - public HttpResponse execute(HttpHost target, HttpRequest request, - HttpContext context) throws IOException, ClientProtocolException { - if (context != null) { - context.setAttribute(ExecutionContext.HTTP_CONNECTION, value); - context.setAttribute(ExecutionContext.HTTP_PROXY_HOST, value); - context.setAttribute(ExecutionContext.HTTP_REQ_SENT, value); - context.setAttribute(ExecutionContext.HTTP_REQUEST, value); - context.setAttribute(ExecutionContext.HTTP_RESPONSE, value); - context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, value); - } - return response; - } - }; + + @Test + public void testDoesNotSetConnectionInContextOnCacheHit() throws Exception { + DummyBackend backend = new DummyBackend(); + HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = new CachingExec(backend); + HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request); + impl.execute(route, request, ctx); + assertNull(ctx.getAttribute(ExecutionContext.HTTP_CONNECTION)); } - - private void assertAllContextVariablesAreEqualTo(HttpContext ctx, - final Object value) { - assertSame(value, ctx.getAttribute(ExecutionContext.HTTP_CONNECTION)); - assertSame(value, ctx.getAttribute(ExecutionContext.HTTP_PROXY_HOST)); - assertSame(value, ctx.getAttribute(ExecutionContext.HTTP_REQ_SENT)); - assertSame(value, ctx.getAttribute(ExecutionContext.HTTP_REQUEST)); - assertSame(value, ctx.getAttribute(ExecutionContext.HTTP_RESPONSE)); - assertSame(value, ctx.getAttribute(ExecutionContext.HTTP_TARGET_HOST)); - } - @Test - public void testAllowsBackendToSetHttpContextVariablesOnCacheMiss() throws Exception { - final Object value = new Object(); - impl = new CachingHttpClient(getContextSettingBackend(value, HttpTestUtils.make200Response())); - HttpContext ctx = new BasicHttpContext(); - impl.execute(host, request, ctx); - assertAllContextVariablesAreEqualTo(ctx, value); - } - - @Test - public void testDoesNotSetConnectionInContextOnCacheHit() throws Exception { - DummyHttpClient backend = new DummyHttpClient(); - HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingHttpClient(backend); - HttpContext ctx = new BasicHttpContext(); - impl.execute(host, request); - impl.execute(host, request, ctx); - assertNull(ctx.getAttribute(ExecutionContext.HTTP_CONNECTION)); - } - - @Test - public void testDoesNotSetProxyHostInContextOnCacheHit() throws Exception { - DummyHttpClient backend = new DummyHttpClient(); - HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingHttpClient(backend); - HttpContext ctx = new BasicHttpContext(); - impl.execute(host, request); - impl.execute(host, request, ctx); - assertNull(ctx.getAttribute(ExecutionContext.HTTP_PROXY_HOST)); - } - - @Test - public void testSetsTargetHostInContextOnCacheHit() throws Exception { - DummyHttpClient backend = new DummyHttpClient(); - HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingHttpClient(backend); - HttpContext ctx = new BasicHttpContext(); - impl.execute(host, request); - impl.execute(host, request, ctx); - assertSame(host, ctx.getAttribute(ExecutionContext.HTTP_TARGET_HOST)); - } + @Test + public void testDoesNotSetProxyHostInContextOnCacheHit() throws Exception { + DummyBackend backend = new DummyBackend(); + HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = new CachingExec(backend); + HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request); + impl.execute(route, request, ctx); + assertNull(ctx.getAttribute(ExecutionContext.HTTP_PROXY_HOST)); + } - @Test - public void testSetsRequestInContextOnCacheHit() throws Exception { - DummyHttpClient backend = new DummyHttpClient(); - HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingHttpClient(backend); - HttpContext ctx = new BasicHttpContext(); - impl.execute(host, request); - impl.execute(host, request, ctx); - assertSame(request, ctx.getAttribute(ExecutionContext.HTTP_REQUEST)); - } + @Test + public void testSetsTargetHostInContextOnCacheHit() throws Exception { + DummyBackend backend = new DummyBackend(); + HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = new CachingExec(backend); + HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request); + impl.execute(route, request, ctx); + assertSame(host, ctx.getAttribute(ExecutionContext.HTTP_TARGET_HOST)); + } + + @Test + public void testSetsRequestInContextOnCacheHit() throws Exception { + DummyBackend backend = new DummyBackend(); + HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = new CachingExec(backend); + HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request); + impl.execute(route, request, ctx); + assertSame(request, ctx.getAttribute(ExecutionContext.HTTP_REQUEST)); + } + + @Test + public void testSetsResponseInContextOnCacheHit() throws Exception { + DummyBackend backend = new DummyBackend(); + HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = new CachingExec(backend); + HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request); + HttpResponse result = impl.execute(route, request, ctx); + assertSame(result, ctx.getAttribute(ExecutionContext.HTTP_RESPONSE)); + } + + @Test + public void testSetsRequestSentInContextOnCacheHit() throws Exception { + DummyBackend backend = new DummyBackend(); + HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = new CachingExec(backend); + HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request); + impl.execute(route, request, ctx); + assertEquals(Boolean.TRUE, ctx.getAttribute(ExecutionContext.HTTP_REQ_SENT)); + } + + @Test + public void testCanCacheAResponseWithoutABody() throws Exception { + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); + response.setHeader("Date", DateUtils.formatDate(new Date())); + response.setHeader("Cache-Control","max-age=300"); + DummyBackend backend = new DummyBackend(); + backend.setResponse(response); + impl = new CachingExec(backend); + impl.execute(route, request); + impl.execute(route, request); + assertEquals(1, backend.getExecutions()); + } + + private IExpectationSetters backendExpectsAnyRequestAndReturn( + HttpResponse response) throws Exception { + CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); + } + + private IExpectationSetters implExpectsAnyRequestAndReturn( + CloseableHttpResponse response) throws Exception { + CloseableHttpResponse resp = impl.callBackend( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(response); + } + + private IExpectationSetters backendExpectsRequestAndReturn( + HttpRequestWrapper request, HttpResponse response) throws Exception { + CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.eq(request), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); + } + + private IExpectationSetters backendExpectsRequestAndReturn( + HttpRequestWrapper request, CloseableHttpResponse response) throws Exception { + CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.eq(request), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(response); + } + + private IExpectationSetters backendExpectsAnyRequestAndThrows( + Throwable throwable) throws Exception { + CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andThrow(throwable); + } + + private IExpectationSetters backendCaptureRequestAndReturn( + Capture cap, HttpResponse response) throws Exception { + CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); + } - @Test - public void testSetsResponseInContextOnCacheHit() throws Exception { - DummyHttpClient backend = new DummyHttpClient(); - HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingHttpClient(backend); - HttpContext ctx = new BasicHttpContext(); - impl.execute(host, request); - HttpResponse result = impl.execute(host, request, ctx); - assertSame(result, ctx.getAttribute(ExecutionContext.HTTP_RESPONSE)); - } - - @Test - public void testSetsRequestSentInContextOnCacheHit() throws Exception { - DummyHttpClient backend = new DummyHttpClient(); - HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingHttpClient(backend); - HttpContext ctx = new BasicHttpContext(); - impl.execute(host, request); - impl.execute(host, request, ctx); - assertEquals(Boolean.TRUE, ctx.getAttribute(ExecutionContext.HTTP_REQ_SENT)); - } - - @Test - public void testAllowsBackendToSetContextVariablesOnRevalidation() throws Exception { - final Object value = new Object(); - HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control","public"); - response.setHeader("Etag", "\"v1\""); - DummyHttpClient backend = getContextSettingBackend(value, response); - backend.setResponse(response); - impl = new CachingHttpClient(backend); - HttpContext ctx = new BasicHttpContext(); - impl.execute(host, request); - impl.execute(host, request, ctx); - assertAllContextVariablesAreEqualTo(ctx, value); - } - - @Test - public void testCanCacheAResponseWithoutABody() throws Exception { - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - response.setHeader("Date", DateUtils.formatDate(new Date())); - response.setHeader("Cache-Control","max-age=300"); - DummyHttpClient backend = new DummyHttpClient(); - backend.setResponse(response); - impl = new CachingHttpClient(backend); - impl.execute(host, request); - impl.execute(host, request); - assertEquals(1, backend.getExecutions()); - } - private void getCacheEntryReturns(HttpCacheEntry result) throws IOException { expect(mockCache.getCacheEntry(host, request)).andReturn(result); } @@ -2016,23 +1601,6 @@ public class TestCachingHttpClient { (HttpRequest)anyObject()); } - private void callBackendReturnsResponse(HttpResponse response) throws IOException { - expect(impl.callBackend( - (HttpHost)anyObject(), - (HttpRequestWrapper)anyObject(), - (HttpContext)anyObject())).andReturn(response); - } - - private void revalidateCacheEntryReturns(HttpResponse response) throws IOException, - ProtocolException { - expect( - impl.revalidateCacheEntry( - (HttpHost)anyObject(), - (HttpRequestWrapper)anyObject(), - (HttpContext)anyObject(), - (HttpCacheEntry)anyObject())).andReturn(response); - } - private void cacheEntryValidatable(boolean b) { expect(mockValidityPolicy.isRevalidatable( (HttpCacheEntry)anyObject())).andReturn(b); @@ -2055,9 +1623,8 @@ public class TestCachingHttpClient { private void conditionalRequestBuilderReturns(HttpRequestWrapper validate) throws Exception { - expect(mockConditionalRequestBuilder - .buildConditionalRequest(request, entry)) - .andReturn(validate); + expect(mockConditionalRequestBuilder.buildConditionalRequest( + request, entry)).andReturn(validate); } private void getCurrentDateReturns(Date date) { @@ -2069,19 +1636,6 @@ public class TestCachingHttpClient { (HttpRequest)anyObject())).andReturn(allow); } - private void backendCall(HttpRequest req, HttpResponse resp) - throws Exception { - expect(mockBackend.execute(host, req, context)) - .andReturn(resp); - } - - private void backendCallWasMade(HttpRequest request, HttpResponse response) throws IOException { - expect(mockBackend.execute( - (HttpHost)anyObject(), - same(request), - (HttpContext)anyObject())).andReturn(response); - } - private void cacheEntrySuitable(boolean suitable) { expect( mockSuitabilityChecker.canCachedResponseBeUsed( @@ -2107,33 +1661,30 @@ public class TestCachingHttpClient { throws IOException { expect( impl.handleBackendResponse( - (HttpHost)anyObject(), + isA(HttpRoute.class), same(request), - (Date)anyObject(), - (Date)anyObject(), - (HttpResponse)anyObject())).andReturn(response); - } - - private HttpEntity makeStreamingEntity() { - byte[] body = HttpTestUtils.getRandomBytes(101); - ByteArrayInputStream buf = new ByteArrayInputStream(body); - cis = new ConsumableInputStream(buf); - return new InputStreamEntity(cis, 101); + isA(HttpClientContext.class), + (HttpExecutionAware) isNull(), + isA(Date.class), + isA(Date.class), + isA(CloseableHttpResponse.class))).andReturn( + Proxies.enhanceResponse(response)); } private void mockImplMethods(String... methods) { mockedImpl = true; - impl = createMockBuilder(CachingHttpClient.class).withConstructor( + impl = createMockBuilder(CachingExec.class).withConstructor( mockBackend, + mockCache, mockValidityPolicy, mockResponsePolicy, - mockCache, mockResponseGenerator, mockRequestPolicy, mockSuitabilityChecker, mockConditionalRequestBuilder, mockResponseProtocolCompliance, - mockRequestProtocolCompliance).addMockedMethods(methods).createNiceMock(); + mockRequestProtocolCompliance, + config).addMockedMethods(methods).createNiceMock(); } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestHttpCacheJiraNumber1147.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestHttpCacheJiraNumber1147.java index 5355b8723..1a03e83bf 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestHttpCacheJiraNumber1147.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestHttpCacheJiraNumber1147.java @@ -32,21 +32,18 @@ import java.util.Date; import junit.framework.Assert; import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; -import org.apache.http.client.HttpClient; import org.apache.http.client.cache.HttpCacheStorage; import org.apache.http.client.cache.ResourceFactory; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.cache.CacheConfig; -import org.apache.http.impl.client.cache.CachingHttpClient; -import org.apache.http.impl.client.cache.FileResourceFactory; -import org.apache.http.impl.client.cache.ManagedHttpCacheStorage; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.impl.client.execchain.ClientExecChain; import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import org.easymock.EasyMock; import org.junit.After; @@ -92,10 +89,11 @@ public class TestHttpCacheJiraNumber1147 { ResourceFactory resourceFactory = new FileResourceFactory(cacheDir); HttpCacheStorage httpCacheStorage = new ManagedHttpCacheStorage(cacheConfig); - HttpClient client = EasyMock.createNiceMock(HttpClient.class); - HttpGet get = new HttpGet("http://somehost/"); - HttpContext context = new BasicHttpContext(); + ClientExecChain backend = EasyMock.createNiceMock(ClientExecChain.class); + HttpRequestWrapper get = HttpRequestWrapper.wrap(new HttpGet("http://somehost/")); + HttpClientContext context = HttpClientContext.create(); HttpHost target = new HttpHost("somehost"); + HttpRoute route = new HttpRoute(target); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); @@ -107,34 +105,37 @@ public class TestHttpCacheJiraNumber1147 { response.setHeader("Cache-Control", "public, max-age=3600"); response.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - EasyMock.expect(client.execute( - EasyMock.eq(target), - EasyMock.isA(HttpRequest.class), - EasyMock.same(context))).andReturn(response); - EasyMock.replay(client); + EasyMock.expect(backend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.same(context), + EasyMock.isNull())).andReturn(Proxies.enhanceResponse(response)); + EasyMock.replay(backend); - CachingHttpClient t = new CachingHttpClient(client, resourceFactory, httpCacheStorage, cacheConfig); + BasicHttpCache cache = new BasicHttpCache(resourceFactory, httpCacheStorage, cacheConfig); + CachingExec t = new CachingExec(backend, cache, cacheConfig); - HttpResponse response1 = t.execute(get, context); + HttpResponse response1 = t.execute(route, get, context, null); Assert.assertEquals(200, response1.getStatusLine().getStatusCode()); EntityUtils.consume(response1.getEntity()); - EasyMock.verify(client); + EasyMock.verify(backend); removeCache(); - EasyMock.reset(client); - EasyMock.expect(client.execute( - EasyMock.eq(target), - EasyMock.isA(HttpRequest.class), - EasyMock.same(context))).andReturn(response); - EasyMock.replay(client); + EasyMock.reset(backend); + EasyMock.expect(backend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.same(context), + EasyMock.isNull())).andReturn(Proxies.enhanceResponse(response)); + EasyMock.replay(backend); - HttpResponse response2 = t.execute(get, context); + HttpResponse response2 = t.execute(route, get, context, null); Assert.assertEquals(200, response2.getStatusLine().getStatusCode()); EntityUtils.consume(response2.getEntity()); - EasyMock.verify(client); + EasyMock.verify(backend); } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolAllowedBehavior.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolAllowedBehavior.java index f247f90df..a366c7ea2 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolAllowedBehavior.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolAllowedBehavior.java @@ -31,10 +31,10 @@ import java.util.Date; import junit.framework.Assert; -import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; +import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHttpRequest; import org.junit.Test; @@ -49,7 +49,8 @@ public class TestProtocolAllowedBehavior extends AbstractProtocolTest { @Test public void testNonSharedCacheReturnsStaleResponseWhenRevalidationFailsForProxyRevalidate() throws Exception { - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1)); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); originResponse.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); @@ -58,14 +59,15 @@ public class TestProtocolAllowedBehavior extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1)); backendExpectsAnyRequest().andThrow(new SocketTimeoutException()); replayMocks(); behaveAsNonSharedCache(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -74,17 +76,19 @@ public class TestProtocolAllowedBehavior extends AbstractProtocolTest { @Test public void testNonSharedCacheMayCacheResponsesWithCacheControlPrivate() throws Exception { - HttpRequest req1 = new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1)); originResponse.setHeader("Cache-Control","private,max-age=3600"); backendExpectsAnyRequest().andReturn(originResponse); - HttpRequest req2 = new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1)); replayMocks(); behaveAsNonSharedCache(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java index a3f42ee8d..0027abd91 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java @@ -37,13 +37,17 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.ProtocolVersion; import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpExecutionAware; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.impl.client.execchain.ClientExecChain; import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHttpEntityEnclosingRequest; import org.apache.http.message.BasicHttpRequest; import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.HttpContext; import org.easymock.Capture; import org.easymock.classextension.EasyMock; import org.junit.Assert; @@ -74,24 +78,27 @@ public class TestProtocolDeviations { private int entityLength = 128; private HttpHost host; + private HttpRoute route; private HttpEntity body; private HttpEntity mockEntity; - private HttpClient mockBackend; + private ClientExecChain mockBackend; private HttpCache mockCache; private HttpRequest request; - private HttpResponse originResponse; + private CloseableHttpResponse originResponse; - private CachingHttpClient impl; + private CachingExec impl; @Before public void setUp() { host = new HttpHost("foo.example.com"); + route = new HttpRoute(host); + body = makeBody(entityLength); request = new BasicHttpRequest("GET", "/foo", HTTP_1_1); - originResponse = make200Response(); + originResponse = Proxies.enhanceResponse(make200Response()); CacheConfig config = CacheConfig.custom() .setMaxCacheEntries(MAX_ENTRIES) @@ -99,11 +106,11 @@ public class TestProtocolDeviations { .build(); HttpCache cache = new BasicHttpCache(config); - mockBackend = EasyMock.createNiceMock(HttpClient.class); + mockBackend = EasyMock.createNiceMock(ClientExecChain.class); mockEntity = EasyMock.createNiceMock(HttpEntity.class); mockCache = EasyMock.createNiceMock(HttpCache.class); - impl = new CachingHttpClient(mockBackend, cache, config); + impl = new CachingExec(mockBackend, cache, config); } private HttpResponse make200Response() { @@ -162,7 +169,7 @@ public class TestProtocolDeviations { replayMocks(); - HttpResponse response = impl.execute(host, post); + HttpResponse response = impl.execute(route, HttpRequestWrapper.wrap(post)); verifyMocks(); @@ -208,16 +215,19 @@ public class TestProtocolDeviations { org.easymock.EasyMock.expect(mockBody.getContentLength()).andReturn(-1L).anyTimes(); post.setEntity(mockBody); - Capture reqCap = new Capture(); - org.easymock.EasyMock.expect( - mockBackend.execute(org.easymock.EasyMock.eq(host), org.easymock.EasyMock - .capture(reqCap), (HttpContext) org.easymock.EasyMock.isNull())).andReturn( - originResponse).times(0, 1); + Capture reqCap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(reqCap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + originResponse).times(0, 1); replayMocks(); EasyMock.replay(mockBody); - HttpResponse result = impl.execute(host, post); + HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(post)); verifyMocks(); EasyMock.verify(mockBody); @@ -247,14 +257,16 @@ public class TestProtocolDeviations { options.setEntity(body); options.setHeader("Content-Length", "1"); - Capture reqCap = new Capture(); - org.easymock.EasyMock.expect( - mockBackend.execute(org.easymock.EasyMock.eq(host), org.easymock.EasyMock - .capture(reqCap), (HttpContext) org.easymock.EasyMock.isNull())).andReturn( - originResponse); + Capture reqCap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(reqCap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, options); + impl.execute(route, HttpRequestWrapper.wrap(options)); verifyMocks(); @@ -281,19 +293,22 @@ public class TestProtocolDeviations { // this situation, but it better not just pass the response // on. request.removeHeaders("Range"); - originResponse = new BasicHttpResponse(HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, - "Partial Content"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, + "Partial Content")); originResponse.setHeader("Content-Range", "bytes 0-499/1234"); originResponse.setEntity(makeBody(500)); - org.easymock.EasyMock.expect( - mockBackend.execute(org.easymock.EasyMock.isA(HttpHost.class), - org.easymock.EasyMock.isA(HttpRequest.class), - (HttpContext) org.easymock.EasyMock.isNull())).andReturn(originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); try { - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request)); Assert.assertTrue(HttpStatus.SC_PARTIAL_CONTENT != result.getStatusLine() .getStatusCode()); } catch (ClientProtocolException acceptableBehavior) { @@ -311,14 +326,17 @@ public class TestProtocolDeviations { @Test public void testPassesOnOrigin401ResponseWithoutWWWAuthenticateHeader() throws Exception { - originResponse = new BasicHttpResponse(HTTP_1_1, 401, "Unauthorized"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HTTP_1_1, 401, "Unauthorized")); - org.easymock.EasyMock.expect( - mockBackend.execute(org.easymock.EasyMock.isA(HttpHost.class), - org.easymock.EasyMock.isA(HttpRequest.class), - (HttpContext) org.easymock.EasyMock.isNull())).andReturn(originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request)); verifyMocks(); Assert.assertSame(originResponse, result); } @@ -331,14 +349,17 @@ public class TestProtocolDeviations { */ @Test public void testPassesOnOrigin405WithoutAllowHeader() throws Exception { - originResponse = new BasicHttpResponse(HTTP_1_1, 405, "Method Not Allowed"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HTTP_1_1, 405, "Method Not Allowed")); - org.easymock.EasyMock.expect( - mockBackend.execute(org.easymock.EasyMock.isA(HttpHost.class), - org.easymock.EasyMock.isA(HttpRequest.class), - (HttpContext) org.easymock.EasyMock.isNull())).andReturn(originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request)); verifyMocks(); Assert.assertSame(originResponse, result); } @@ -352,14 +373,17 @@ public class TestProtocolDeviations { */ @Test public void testPassesOnOrigin407WithoutAProxyAuthenticateHeader() throws Exception { - originResponse = new BasicHttpResponse(HTTP_1_1, 407, "Proxy Authentication Required"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HTTP_1_1, 407, "Proxy Authentication Required")); - org.easymock.EasyMock.expect( - mockBackend.execute(org.easymock.EasyMock.isA(HttpHost.class), - org.easymock.EasyMock.isA(HttpRequest.class), - (HttpContext) org.easymock.EasyMock.isNull())).andReturn(originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request)); verifyMocks(); Assert.assertSame(originResponse, result); } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java index ab3548363..5045ce90f 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java @@ -26,8 +26,12 @@ */ package org.apache.http.impl.client.cache; -import static org.easymock.classextension.EasyMock.*; -import static org.junit.Assert.*; +import static org.apache.http.impl.cookie.DateUtils.formatDate; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.Arrays; @@ -37,20 +41,18 @@ import java.util.List; import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; -import static org.apache.http.impl.cookie.DateUtils.formatDate; - import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.message.BasicHttpEntityEnclosingRequest; import org.apache.http.message.BasicHttpRequest; import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.HttpContext; import org.easymock.Capture; import org.easymock.EasyMock; import org.junit.Before; @@ -91,7 +93,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { originResponse.setHeader("Content-Encoding", "identity"); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); boolean foundIdentity = false; for(Header h : result.getHeaders("Content-Encoding")) { @@ -115,20 +117,20 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { String headerName, String headerValue, String validatorHeader, String validator, String conditionalHeader) throws Exception, IOException { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader(validatorHeader, validator); resp1.setHeader(headerName, headerValue); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader(conditionalHeader, validator); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (HttpStatus.SC_NOT_MODIFIED == result.getStatusLine().getStatusCode()) { @@ -224,16 +226,16 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { private void cacheGenerated304ForStrongValidatorShouldNotContainContentRange( String validatorHeader, String validator, String conditionalHeader) throws Exception, IOException, ClientProtocolException { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req1.setHeader("Range","bytes=0-127"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader(validatorHeader, validator); resp1.setHeader("Content-Range", "bytes 0-127/256"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("If-Range", validator); req2.setHeader("Range","bytes=0-127"); req2.setHeader(conditionalHeader, validator); @@ -244,13 +246,18 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { // cache module does not currently deal with byte ranges, but we want // this test to work even if it does some day - Capture cap = new Capture(); - expect(mockBackend.execute(same(host), capture(cap), (HttpContext)isNull())) - .andReturn(resp2).times(0,1); + Capture cap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)).times(0,1); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (!cap.hasCaptured() @@ -305,7 +312,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { private void shouldStripEntityHeaderFromOrigin304ResponseToStrongValidation( String entityHeader, String entityHeaderValue) throws Exception, IOException { - HttpRequest req = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req.setHeader("If-None-Match", "\"etag\""); HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); @@ -313,10 +320,10 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp.setHeader("Etag", "\"etag\""); resp.setHeader(entityHeader, entityHeaderValue); - backendExpectsAnyRequest().andReturn(resp); + backendExpectsAnyRequestAndReturn(resp); replayMocks(); - HttpResponse result = impl.execute(host, req); + HttpResponse result = impl.execute(route, req); verifyMocks(); assertNull(result.getFirstHeader(entityHeader)); @@ -367,7 +374,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void shouldStripContentRangeFromOrigin304ResponseToStringValidation() throws Exception { - HttpRequest req = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req.setHeader("If-Range","\"etag\""); req.setHeader("Range","bytes=0-127"); @@ -376,10 +383,10 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp.setHeader("ETag", "\"etag\""); resp.setHeader("Content-Range", "bytes 0-127/256"); - backendExpectsAnyRequest().andReturn(resp); + backendExpectsAnyRequestAndReturn(resp); replayMocks(); - HttpResponse result = impl.execute(host, req); + HttpResponse result = impl.execute(route, req); verifyMocks(); assertNull(result.getFirstHeader("Content-Range")); @@ -397,8 +404,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { * client explicitly requests a first-hand or fresh one, unless it is * impossible to comply for technical or policy reasons." */ - private HttpRequest requestToPopulateStaleCacheEntry() throws Exception { - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + private HttpRequestWrapper requestToPopulateStaleCacheEntry() throws Exception { + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); @@ -406,21 +414,21 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control","public,max-age=5"); resp1.setHeader("Etag","\"etag\""); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); return req1; } - private void testDoesNotReturnStaleResponseOnError(HttpRequest req2) + private void testDoesNotReturnStaleResponseOnError(HttpRequestWrapper req2) throws Exception, IOException { - HttpRequest req1 = requestToPopulateStaleCacheEntry(); + HttpRequestWrapper req1 = requestToPopulateStaleCacheEntry(); backendExpectsAnyRequest().andThrow(new IOException()); replayMocks(); - impl.execute(host, req1); + impl.execute(route, req1); HttpResponse result = null; try { - result = impl.execute(host, req2); + result = impl.execute(route, req2); } catch (IOException acceptable) { } verifyMocks(); @@ -433,7 +441,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testDoesNotReturnStaleResponseIfClientExplicitlyRequestsFirstHandOneWithCacheControl() throws Exception { - HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Cache-Control","no-cache"); testDoesNotReturnStaleResponseOnError(req); } @@ -441,7 +450,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testDoesNotReturnStaleResponseIfClientExplicitlyRequestsFirstHandOneWithPragma() throws Exception { - HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Pragma","no-cache"); testDoesNotReturnStaleResponseOnError(req); } @@ -449,7 +459,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testDoesNotReturnStaleResponseIfClientExplicitlyRequestsFreshWithMaxAge() throws Exception { - HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Cache-Control","max-age=0"); testDoesNotReturnStaleResponseOnError(req); } @@ -457,7 +468,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testDoesNotReturnStaleResponseIfClientExplicitlySpecifiesLargerMaxAge() throws Exception { - HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Cache-Control","max-age=20"); testDoesNotReturnStaleResponseOnError(req); } @@ -466,7 +478,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testDoesNotReturnStaleResponseIfClientExplicitlyRequestsFreshWithMinFresh() throws Exception { - HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Cache-Control","min-fresh=2"); testDoesNotReturnStaleResponseOnError(req); @@ -475,7 +488,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testDoesNotReturnStaleResponseIfClientExplicitlyRequestsFreshWithMaxStale() throws Exception { - HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Cache-Control","max-stale=2"); testDoesNotReturnStaleResponseOnError(req); @@ -484,15 +498,16 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testMayReturnStaleResponseIfClientExplicitlySpecifiesAcceptableMaxStale() throws Exception { - HttpRequest req1 = requestToPopulateStaleCacheEntry(); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = requestToPopulateStaleCacheEntry(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control","max-stale=20"); backendExpectsAnyRequest().andThrow(new IOException()).times(0,1); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -535,7 +550,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testReturnsCachedResponsesAppropriatelyWhenNoOriginCommunication() throws Exception { - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); @@ -543,15 +559,16 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", formatDate(tenSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); backendExpectsAnyRequest().andThrow(new IOException()).anyTimes(); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -591,7 +608,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); assertNull(result.getFirstHeader("Warning")); @@ -612,7 +629,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); assertEquals(warning, result.getFirstHeader("Warning").getValue()); @@ -630,7 +647,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { .getCanonicalHeaderValue(originResponse, headerName); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); assertEquals(headerValue, result.getFirstHeader(headerName).getValue()); @@ -639,12 +656,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { private void testDoesNotModifyHeaderOnRequests(final String headerName) throws Exception { final String headerValue = HttpTestUtils.getCanonicalHeaderValue(request, headerName); - Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.isA(HttpHost.class), - EasyMock.capture(cap), (HttpContext)EasyMock.isNull())) - .andReturn(originResponse); + Capture cap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); assertEquals(headerValue, HttpTestUtils.getCanonicalHeaderValue(cap.getValue(), @@ -785,7 +805,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testDoesNotModifyIfMatchOnRequests() throws Exception { - request = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); + request = HttpRequestWrapper.wrap(HttpRequestWrapper.wrap( + new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1))); request.setHeader("If-Match", "\"etag\""); testDoesNotModifyHeaderOnRequests("If-Match"); } @@ -815,7 +836,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testDoesNotModifyIfUnmodifiedSinceOnRequests() throws Exception { - request = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); + request = HttpRequestWrapper.wrap(HttpRequestWrapper.wrap( + new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1))); request.setHeader("If-Unmodified-Since", formatDate(new Date())); testDoesNotModifyHeaderOnRequests("If-Unmodified-Since"); } @@ -911,27 +933,31 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { Date twentySecondsAgo = new Date(now.getTime() - 20 * 1000L); final String lmDate = formatDate(twentySecondsAgo); - HttpRequest req1 = - new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = + HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", formatDate(tenSecondsAgo)); resp1.setHeader("Last-Modified", lmDate); resp1.setHeader("Cache-Control","max-age=5"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - Capture cap = new Capture(); - HttpRequest req2 = - new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + Capture cap = new Capture(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); - EasyMock.expect(mockBackend.execute(EasyMock.same(host), - EasyMock.capture(cap), (HttpContext)EasyMock.isNull())) - .andReturn(resp2); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -957,28 +983,32 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final String lmDate = formatDate(twentySecondsAgo); final String etag = "\"etag\""; - HttpRequest req1 = - new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", formatDate(tenSecondsAgo)); resp1.setHeader("Last-Modified", lmDate); resp1.setHeader("Cache-Control","max-age=5"); resp1.setHeader("ETag", etag); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - Capture cap = new Capture(); - HttpRequest req2 = - new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + Capture cap = new Capture(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); - EasyMock.expect(mockBackend.execute(EasyMock.same(host), - EasyMock.capture(cap), (HttpContext)EasyMock.isNull())) - .andReturn(resp2); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -1005,20 +1035,20 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); Date oneSecondFromNow = new Date(now.getTime() + 1 * 1000L); Date twoSecondsFromNow = new Date(now.getTime() + 2 * 1000L); - HttpRequest req1 = - new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", formatDate(now)); resp1.setHeader("Expires",formatDate(oneSecondAgo)); resp1.setHeader("Cache-Control", "public"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = - new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpRequest revalidate = - new BasicHttpRequest("GET", "/",HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper revalidate = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/",HttpVersion.HTTP_1_1)); revalidate.setHeader("If-None-Match","\"etag\""); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, @@ -1027,13 +1057,17 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Expires", formatDate(oneSecondFromNow)); resp2.setHeader("ETag","\"etag\""); - expect(mockBackend.execute(isA(HttpHost.class), - eqRequest(revalidate), (HttpContext)isNull())) - .andReturn(resp2); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + eqRequest(revalidate), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_OK, @@ -1059,36 +1093,41 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L); - HttpRequest req1 = - new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","max-age=5"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); resp2.setHeader("ETag","\"etag\""); resp2.setHeader("Date", formatDate(elevenSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - Capture cap = new Capture(); + Capture cap = new Capture(); HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("ETag","\"etag2\""); resp3.setHeader("Date", formatDate(now)); resp3.setHeader("Cache-Control","max-age=5"); - expect(mockBackend.execute(isA(HttpHost.class), capture(cap), - (HttpContext)isNull())) - .andReturn(resp3); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -1128,37 +1167,44 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testSendsAllVariantEtagsInConditionalRequest() throws Exception { - HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1)); req1.setHeader("User-Agent","agent1"); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary","User-Agent"); resp1.setHeader("Etag","\"etag1\""); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1)); req2.setHeader("User-Agent","agent2"); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Vary","User-Agent"); resp2.setHeader("Etag","\"etag2\""); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - Capture cap = new Capture(); - HttpRequest req3 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); + Capture cap = new Capture(); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1)); req3.setHeader("User-Agent","agent3"); HttpResponse resp3 = HttpTestUtils.make200Response(); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - EasyMock.capture(cap), (HttpContext)EasyMock.isNull())) - .andReturn(resp3); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(host,req1); - impl.execute(host,req2); - impl.execute(host,req3); + impl.execute(route,req1); + impl.execute(route,req2); + impl.execute(route,req3); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -1191,7 +1237,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("User-Agent", "agent1"); HttpResponse resp1 = HttpTestUtils.make200Response(); @@ -1201,9 +1248,10 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("User-Agent", "agent2"); HttpResponse resp2 = HttpTestUtils.make200Response(); @@ -1212,25 +1260,27 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Cache-Control", "max-age=3600"); resp2.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.setHeader("User-Agent", "agent3"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); resp3.setHeader("Date", formatDate(now)); resp3.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); - HttpRequest req4 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req4 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req4.setHeader("User-Agent", "agent1"); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result1 = impl.execute(host, req3); - HttpResponse result2 = impl.execute(host, req4); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result1 = impl.execute(route, req3); + HttpResponse result2 = impl.execute(route, req4); verifyMocks(); assertEquals(HttpStatus.SC_OK, result1.getStatusLine().getStatusCode()); @@ -1246,7 +1296,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("User-Agent", "agent1"); HttpResponse resp1 = HttpTestUtils.make200Response(); @@ -1255,24 +1306,26 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("User-Agent", "agent2"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); resp2.setHeader("Date", formatDate(now)); resp2.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.setHeader("User-Agent", "agent2"); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -1286,16 +1339,16 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void variantNegotiationsDoNotIncludeEtagsForPartialResponses() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req1.setHeader("User-Agent", "agent1"); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Vary", "User-Agent"); resp1.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("User-Agent", "agent2"); req2.setHeader("Range", "bytes=0-49"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, @@ -1308,9 +1361,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Date", formatDate(new Date())); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req3.setHeader("User-Agent", "agent3"); HttpResponse resp3 = HttpTestUtils.make200Response(); @@ -1318,14 +1371,19 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Vary", "User-Agent"); resp1.setHeader("ETag", "\"etag3\""); - Capture cap = new Capture(); - expect(mockBackend.execute(isA(HttpHost.class), capture(cap), - (HttpContext)isNull())).andReturn(resp3); + Capture cap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -1348,31 +1406,34 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void cachedEntryShouldNotBeUsedIfMoreRecentMentionInContentLocation() throws Exception { - HttpRequest req1 = new HttpGet("http://foo.example.com/"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new HttpGet("http://foo.example.com/")); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("ETag", "\"old-etag\""); resp1.setHeader("Date", formatDate(tenSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new HttpGet("http://foo.example.com/bar"); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + 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); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = new HttpGet("http://foo.example.com"); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new HttpGet("http://foo.example.com")); HttpResponse resp3 = HttpTestUtils.make200Response(); - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -1386,33 +1447,36 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void responseToGetWithQueryFrom1_0OriginIsNotCached() throws Exception { - HttpRequest req1 = new HttpGet("http://foo.example.com/bar?baz=quux"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new HttpGet("http://foo.example.com/bar?baz=quux")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(200)); resp1.setHeader("Content-Length","200"); resp1.setHeader("Date", formatDate(now)); resp1.setHeader("Expires", formatDate(tenSecondsFromNow)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new HttpGet("http://foo.example.com/bar?baz=quux"); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + 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); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @Test public void responseToGetWithQueryFrom1_0OriginVia1_1ProxyIsNotCached() throws Exception { - HttpRequest req1 = new HttpGet("http://foo.example.com/bar?baz=quux"); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new HttpGet("http://foo.example.com/bar?baz=quux")); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(200)); resp1.setHeader("Content-Length","200"); @@ -1420,20 +1484,21 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Expires", formatDate(tenSecondsFromNow)); resp1.setHeader("Via","1.0 someproxy"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new HttpGet("http://foo.example.com/bar?baz=quux"); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + 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); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @@ -1447,28 +1512,31 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void shouldInvalidateNonvariantCacheEntryForUnknownMethod() throws Exception { - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("FROB", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("FROB", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("ETag", "\"etag\""); - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp3, result)); @@ -1477,49 +1545,54 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void shouldInvalidateAllVariantsForUnknownMethod() throws Exception { - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("User-Agent", "agent1"); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary", "User-Agent"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("User-Agent", "agent2"); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Vary", "User-Agent"); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = new BasicHttpRequest("FROB", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + 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); + backendExpectsAnyRequestAndReturn(resp3); - HttpRequest req4 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req4 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req4.setHeader("User-Agent", "agent1"); HttpResponse resp4 = HttpTestUtils.make200Response(); resp4.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequest().andReturn(resp4); + backendExpectsAnyRequestAndReturn(resp4); - HttpRequest req5 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req5 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req5.setHeader("User-Agent", "agent2"); HttpResponse resp5 = HttpTestUtils.make200Response(); resp5.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequest().andReturn(resp5); + backendExpectsAnyRequestAndReturn(resp5); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); - HttpResponse result4 = impl.execute(host, req4); - HttpResponse result5 = impl.execute(host, req5); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); + HttpResponse result4 = impl.execute(route, req4); + HttpResponse result5 = impl.execute(route, req5); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp4, result4)); @@ -1536,29 +1609,29 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void cacheShouldUpdateWithNewCacheableResponse() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(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); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); @@ -1578,24 +1651,24 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void expiresEqualToDateWithNoCacheControlIsNotCacheable() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", formatDate(now)); resp1.setHeader("Expires", formatDate(now)); resp1.removeHeaders("Cache-Control"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control", "max-stale=1000"); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); @@ -1604,24 +1677,24 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void expiresPriorToDateWithNoCacheControlIsNotCacheable() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", formatDate(now)); resp1.setHeader("Expires", formatDate(tenSecondsAgo)); resp1.removeHeaders("Cache-Control"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control", "max-stale=1000"); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); @@ -1636,16 +1709,22 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void otherFreshnessRequestDirectivesNotAllowedWithNoCache() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req1.setHeader("Cache-Control", "min-fresh=10, no-cache"); req1.addHeader("Cache-Control", "max-stale=0, max-age=0"); - Capture cap = new Capture(); - expect(mockBackend.execute(same(host), capture(cap), (HttpContext)isNull())) - .andReturn(HttpTestUtils.make200Response()); + + Capture cap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.same(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(HttpTestUtils.make200Response())); replayMocks(); - impl.execute(host, req1); + impl.execute(route, req1); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -1679,11 +1758,11 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void cacheMissResultsIn504WithOnlyIfCached() throws Exception { - HttpRequest req = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req.setHeader("Cache-Control", "only-if-cached"); replayMocks(); - HttpResponse result = impl.execute(host, req); + HttpResponse result = impl.execute(route, req); verifyMocks(); assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, @@ -1693,18 +1772,18 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void cacheHitOkWithOnlyIfCached() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control", "only-if-cached"); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); @@ -1713,19 +1792,19 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void returns504ForStaleEntryWithOnlyIfCached() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","max-age=5"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control", "only-if-cached"); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, @@ -1736,44 +1815,44 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { public void returnsStaleCacheEntryWithOnlyIfCachedAndMaxStale() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","max-age=5"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control", "max-stale=20, only-if-cached"); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); } - + @Test public void issues304EvenWithWeakETag() throws Exception { - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control", "max-age=300"); resp1.setHeader("ETag","W/\"weak-sauce\""); - - backendExpectsAnyRequest().andReturn(resp1); - - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + + backendExpectsAnyRequestAndReturn(resp1); + + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("If-None-Match","W/\"weak-sauce\""); - + replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); - + assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); - + } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java index 49001044f..d0b130d16 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java @@ -45,7 +45,11 @@ import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.cache.HttpCacheEntry; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; import org.apache.http.entity.BasicHttpEntity; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.cookie.DateUtils; @@ -54,7 +58,6 @@ import org.apache.http.message.BasicHttpEntityEnclosingRequest; import org.apache.http.message.BasicHttpRequest; import org.apache.http.message.BasicHttpResponse; import org.apache.http.protocol.HTTP; -import org.apache.http.protocol.HttpContext; import org.easymock.Capture; import org.easymock.classextension.EasyMock; import org.junit.Assert; @@ -74,11 +77,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testCacheMissOnGETUsesOriginResponse() throws Exception { - EasyMock.expect(mockBackend.execute(host, request, (HttpContext) null)).andReturn( - originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + eqRequest(request), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); @@ -100,13 +107,18 @@ public class TestProtocolRequirements extends AbstractProtocolTest { // tunnel behavior: I don't muck with request or response in // any way - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 2, 13))); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 2, 13))); - EasyMock.expect(mockBackend.execute(host, request, (HttpContext) null)).andReturn( - originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + eqRequest(request), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertSame(originResponse, result); @@ -115,16 +127,21 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testHigher1_XProtocolVersionsDowngradeTo1_1() throws Exception { - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 2))); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 2))); - HttpRequest downgraded = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); + HttpRequestWrapper downgraded = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), eqRequest(downgraded), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + eqRequest(downgraded), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); @@ -142,15 +159,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testRequestsWithLowerProtocolVersionsGetUpgradedTo1_1() throws Exception { - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0))); - HttpRequest upgraded = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0))); + HttpRequestWrapper upgraded = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), eqRequest(upgraded), (HttpContext) EasyMock - .isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + eqRequest(upgraded), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); @@ -166,8 +188,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testLowerOriginResponsesUpgradedToOurVersion1_1() throws Exception { - originResponse = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 2), HttpStatus.SC_OK, - "OK"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 2), HttpStatus.SC_OK, "OK")); originResponse.setHeader("Date", DateUtils.formatDate(new Date())); originResponse.setHeader("Server", "MockOrigin/1.0"); originResponse.setEntity(body); @@ -175,11 +197,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { // not testing this internal behavior in this test, just want // to check the protocol version that comes out the other end EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion()); @@ -187,14 +212,18 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testResponseToA1_0RequestShouldUse1_1() throws Exception { - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0))); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0))); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion()); @@ -206,20 +235,25 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testForwardsUnknownHeadersOnRequestsFromHigherProtocolVersions() throws Exception { - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 2))); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 2))); request.removeHeaders("Connection"); request.addHeader("X-Unknown-Header", "some-value"); - HttpRequestWrapper downgraded = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); + HttpRequestWrapper downgraded = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); downgraded.removeHeaders("Connection"); downgraded.addHeader("X-Unknown-Header", "some-value"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), eqRequest(downgraded), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + eqRequest(downgraded), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); } @@ -233,14 +267,18 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Transfer-Encoding", "identity"); - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0))); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0))); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); @@ -261,16 +299,19 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * these field values when a message is forwarded." * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 */ - private void testOrderOfMultipleHeadersIsPreservedOnRequests(String h, HttpRequest request) + private void testOrderOfMultipleHeadersIsPreservedOnRequests(String h, HttpRequestWrapper request) throws Exception { - Capture reqCapture = new Capture(); + Capture reqCapture = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.capture(reqCapture), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.capture(reqCapture), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); @@ -317,7 +358,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { put.addHeader("Allow", "GET, HEAD"); put.addHeader("Allow", "DELETE"); put.addHeader("Content-Length", "128"); - testOrderOfMultipleHeadersIsPreservedOnRequests("Allow", put); + testOrderOfMultipleHeadersIsPreservedOnRequests("Allow", HttpRequestWrapper.wrap(put)); } @Test @@ -335,7 +376,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.addHeader("Content-Encoding", "gzip"); post.addHeader("Content-Encoding", "compress"); post.addHeader("Content-Length", "128"); - testOrderOfMultipleHeadersIsPreservedOnRequests("Content-Encoding", post); + testOrderOfMultipleHeadersIsPreservedOnRequests("Content-Encoding", HttpRequestWrapper.wrap(post)); } @Test @@ -346,7 +387,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.addHeader("Content-Language", "mi"); post.addHeader("Content-Language", "en"); post.addHeader("Content-Length", "128"); - testOrderOfMultipleHeadersIsPreservedOnRequests("Content-Language", post); + testOrderOfMultipleHeadersIsPreservedOnRequests("Content-Language", HttpRequestWrapper.wrap(post)); } @Test @@ -357,7 +398,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.addHeader("Expect", "100-continue"); post.addHeader("Expect", "x-expect=true"); post.addHeader("Content-Length", "128"); - testOrderOfMultipleHeadersIsPreservedOnRequests("Expect", post); + testOrderOfMultipleHeadersIsPreservedOnRequests("Expect", HttpRequestWrapper.wrap(post)); } @Test @@ -383,11 +424,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { private void testOrderOfMultipleHeadersIsPreservedOnResponses(String h) throws Exception { EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); @@ -399,7 +443,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testOrderOfMultipleAllowHeadersIsPreservedOnResponses() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, 405, "Method Not Allowed"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, 405, "Method Not Allowed")); originResponse.addHeader("Allow", "HEAD"); originResponse.addHeader("Allow", "DELETE"); testOrderOfMultipleHeadersIsPreservedOnResponses("Allow"); @@ -459,19 +504,23 @@ public class TestProtocolRequirements extends AbstractProtocolTest { emptyMockCacheExpectsNoPuts(); - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, code, "Moo"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, code, "Moo")); originResponse.setHeader("Date", DateUtils.formatDate(new Date())); originResponse.setHeader("Server", "MockOrigin/1.0"); originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setEntity(body); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); // in particular, there were no storage calls on the cache verifyMocks(); @@ -505,14 +554,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testUnknownHeadersOnRequestsAreForwarded() throws Exception { request.addHeader("X-Unknown-Header", "blahblah"); - Capture reqCap = new Capture(); + Capture reqCap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.capture(reqCap), - (HttpContext) EasyMock.anyObject())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.capture(reqCap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); HttpRequest forwarded = reqCap.getValue(); @@ -525,12 +577,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testUnknownHeadersOnResponsesAreForwarded() throws Exception { originResponse.addHeader("X-Unknown-Header", "blahblah"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Header[] hdrs = result.getHeaders("X-Unknown-Header"); @@ -553,20 +608,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.setHeader("Content-Length", "128"); post.setEntity(new BasicHttpEntity()); - Capture reqCap = new Capture(); + Capture reqCap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.capture(reqCap), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(reqCap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, post); + impl.execute(route, HttpRequestWrapper.wrap(post)); verifyMocks(); - HttpEntityEnclosingRequest forwarded = reqCap.getValue(); - Assert.assertTrue(forwarded.expectContinue()); + HttpRequestWrapper forwarded = reqCap.getValue(); boolean foundExpect = false; for (Header h : forwarded.getHeaders("Expect")) { for (HeaderElement elt : h.getElements()) { @@ -594,20 +651,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.setHeader("Content-Length", "128"); post.setEntity(new BasicHttpEntity()); - Capture reqCap = new Capture(); + Capture reqCap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.capture(reqCap), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(reqCap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, post); + impl.execute(route, HttpRequestWrapper.wrap(post)); verifyMocks(); - HttpEntityEnclosingRequest forwarded = reqCap.getValue(); - Assert.assertFalse(forwarded.expectContinue()); + HttpRequestWrapper forwarded = reqCap.getValue(); boolean foundExpect = false; for (Header h : forwarded.getHeaders("Expect")) { for (HeaderElement elt : h.getElements()) { @@ -630,13 +689,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testExpect100ContinueIsNotSentIfThereIsNoRequestBody() throws Exception { request.addHeader("Expect", "100-continue"); - Capture reqCap = new Capture(); + Capture reqCap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.capture(reqCap), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(reqCap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); HttpRequest forwarded = reqCap.getValue(); boolean foundExpectContinue = false; @@ -690,16 +752,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.setEntity(body); post.setHeader("Content-Length", "128"); - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, 100, "Continue"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, 100, "Continue")); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); try { // if a 100 response gets up to us from the HttpClient // backend, we can't really handle it at that point - impl.execute(host, post); + impl.execute(route, HttpRequestWrapper.wrap(post)); Assert.fail("should have thrown an exception"); } catch (ClientProtocolException expected) { } @@ -719,12 +785,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Cache-Control", "max-age=3600"); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); } @@ -743,11 +812,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Content-Length", "0"); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Header contentLength = result.getFirstHeader("Content-Length"); @@ -771,7 +843,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request.setHeader("Max-Forwards", "0"); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); } @@ -787,14 +859,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS", "*", HttpVersion.HTTP_1_1)); request.setHeader("Max-Forwards", "7"); - Capture cap = new Capture(); + Capture cap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.capture(cap), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -810,13 +885,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testDoesNotAddAMaxForwardsHeaderToForwardedOPTIONSRequests() throws Exception { request = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS", "/", HttpVersion.HTTP_1_1)); - Capture reqCap = new Capture(); + Capture reqCap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.capture(reqCap), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(reqCap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); HttpRequest forwarded = reqCap.getValue(); @@ -833,12 +911,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testResponseToAHEADRequestMustNotHaveABody() throws Exception { request = HttpRequestWrapper.wrap(new BasicHttpRequest("HEAD", "/", HttpVersion.HTTP_1_1)); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); @@ -857,39 +938,52 @@ public class TestProtocolRequirements extends AbstractProtocolTest { String oldVal, String newVal) throws Exception { // put something cacheable in the cache - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.addHeader("Cache-Control", "max-age=3600"); resp1.setHeader(eHeader, oldVal); // get a head that penetrates the cache - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("HEAD", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("HEAD", "/", HttpVersion.HTTP_1_1)); req2.addHeader("Cache-Control", "no-cache"); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setEntity(null); resp2.setHeader(eHeader, newVal); // next request doesn't tolerate stale entry - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.addHeader("Cache-Control", "max-stale=0"); HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader(eHeader, newVal); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), eqRequest(req1), (HttpContext) EasyMock - .isNull())).andReturn(resp1); + mockBackend.execute( + EasyMock.eq(route), + eqRequest(req1), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), eqRequest(req2), (HttpContext) EasyMock - .isNull())).andReturn(resp2); + mockBackend.execute( + EasyMock.eq(route), + eqRequest(req2), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp3); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -941,12 +1035,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.removeHeaders("Expires"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, post); + impl.execute(route, HttpRequestWrapper.wrap(post)); verifyMocks(); } @@ -968,12 +1065,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Cache-Control", "max-age=3600"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, put); + impl.execute(route, HttpRequestWrapper.wrap(put)); verifyMocks(); } @@ -991,12 +1091,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Cache-Control", "max-age=3600"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); } @@ -1013,14 +1116,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { trace.setEntity(HttpTestUtils.makeBody(entityLength)); trace.setHeader("Content-Length", Integer.toString(entityLength)); - Capture reqCap = new Capture(); + Capture reqCap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.capture(reqCap), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(reqCap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, trace); + impl.execute(route, HttpRequestWrapper.wrap(trace)); verifyMocks(); HttpRequest forwarded = reqCap.getValue(); @@ -1046,12 +1152,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Cache-Control", "max-age=3600"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); } @@ -1064,16 +1173,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void test204ResponsesDoNotContainMessageBodies() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content")); originResponse.setEntity(HttpTestUtils.makeBody(entityLength)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); @@ -1087,17 +1200,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void test205ResponsesDoNotContainMessageBodies() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_RESET_CONTENT, - "Reset Content"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_RESET_CONTENT, "Reset Content")); originResponse.setEntity(HttpTestUtils.makeBody(entityLength)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); @@ -1127,19 +1243,21 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void test206ResponseGeneratedFromCacheMustHaveContentRangeOrMultipartByteRangesContentType() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag\""); resp1.setHeader("Cache-Control", "max-age=3600"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range", "bytes=0-50"); - backendExpectsAnyRequest().andReturn(resp1).times(1, 2); + backendExpectsAnyRequestAndReturn(resp1).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) { @@ -1157,19 +1275,21 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void test206ResponseGeneratedFromCacheMustHaveABodyThatMatchesContentLengthHeaderIfPresent() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag\""); resp1.setHeader("Cache-Control", "max-age=3600"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range", "bytes=0-50"); - backendExpectsAnyRequest().andReturn(resp1).times(1, 2); + backendExpectsAnyRequestAndReturn(resp1).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) { @@ -1189,19 +1309,21 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test206ResponseGeneratedFromCacheMustHaveDateHeader() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag\""); resp1.setHeader("Cache-Control", "max-age=3600"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range", "bytes=0-50"); - backendExpectsAnyRequest().andReturn(resp1).times(1, 2); + backendExpectsAnyRequestAndReturn(resp1).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) { @@ -1212,8 +1334,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test206ResponseReturnedToClientMustHaveDateHeader() throws Exception { request.addHeader("Range", "bytes=0-50"); - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, - "Partial Content"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content")); originResponse.setHeader("Date", DateUtils.formatDate(new Date())); originResponse.setHeader("Server", "MockOrigin/1.0"); originResponse.setEntity(HttpTestUtils.makeBody(500)); @@ -1221,12 +1343,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.removeHeaders("Date"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); Assert.assertTrue(result.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT || result.getFirstHeader("Date") != null); @@ -1235,20 +1360,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test206ContainsETagIfA200ResponseWouldHaveIncludedIt() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); originResponse.addHeader("Cache-Control", "max-age=3600"); originResponse.addHeader("ETag", "\"etag1\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.addHeader("Range", "bytes=0-50"); backendExpectsAnyRequest().andReturn(originResponse).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); @@ -1259,20 +1386,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test206ContainsContentLocationIfA200ResponseWouldHaveIncludedIt() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); originResponse.addHeader("Cache-Control", "max-age=3600"); originResponse.addHeader("Content-Location", "http://foo.example.com/other/url"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.addHeader("Range", "bytes=0-50"); backendExpectsAnyRequest().andReturn(originResponse).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); @@ -1284,7 +1413,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test206ResponseIncludesVariantHeadersIfValueMightDiffer() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.addHeader("Accept-Encoding", "gzip"); Date now = new Date(); @@ -1293,7 +1423,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Expires", DateUtils.formatDate(inOneHour)); originResponse.addHeader("Vary", "Accept-Encoding"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.addHeader("Cache-Control", "no-cache"); req2.addHeader("Accept-Encoding", "gzip"); Date nextSecond = new Date(now.getTime() + 1000L); @@ -1305,18 +1436,19 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse2.setHeader("Expires", DateUtils.formatDate(inTwoHoursPlusASec)); originResponse2.setHeader("Vary", "Accept-Encoding"); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.addHeader("Range", "bytes=0-50"); req3.addHeader("Accept-Encoding", "gzip"); backendExpectsAnyRequest().andReturn(originResponse); - backendExpectsAnyRequest().andReturn(originResponse2).times(1, 2); + backendExpectsAnyRequestAndReturn(originResponse2).times(1, 2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); @@ -1339,11 +1471,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void test206ResponseToConditionalRangeRequestDoesNotIncludeOtherEntityHeaders() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); Date now = new Date(); Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L); - originResponse = HttpTestUtils.make200Response(); + originResponse = Proxies.enhanceResponse(HttpTestUtils.make200Response()); originResponse.addHeader("Allow", "GET,HEAD"); originResponse.addHeader("Cache-Control", "max-age=3600"); originResponse.addHeader("Content-Language", "en"); @@ -1354,7 +1487,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Last-Modified", DateUtils.formatDate(oneHourAgo)); originResponse.addHeader("ETag", "W/\"weak-tag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.addHeader("If-Range", "W/\"weak-tag\""); req2.addHeader("Range", "bytes=0-50"); @@ -1362,8 +1496,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); @@ -1387,7 +1521,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void test206ResponseToIfRangeWithStrongValidatorReturnsAllEntityHeaders() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); Date now = new Date(); Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L); @@ -1401,7 +1536,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Last-Modified", DateUtils.formatDate(oneHourAgo)); originResponse.addHeader("ETag", "\"strong-tag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.addHeader("If-Range", "\"strong-tag\""); req2.addHeader("Range", "bytes=0-50"); @@ -1409,8 +1545,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); @@ -1439,7 +1575,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("ETag", "\"etag1\""); @@ -1449,7 +1586,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { } resp1.setEntity(new ByteArrayEntity(bytes1)); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control", "no-cache"); req2.setHeader("Range", "bytes=0-50"); @@ -1467,7 +1605,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setEntity(new ByteArrayEntity(bytes2)); Date inTwoSeconds = new Date(now.getTime() + 2000L); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Date", DateUtils.formatDate(inTwoSeconds)); resp3.setHeader("Cache-Control", "max-age=3600"); @@ -1479,19 +1618,31 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setEntity(new ByteArrayEntity(bytes3)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp3).times(0, 1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp3)).times(0, 1); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); @@ -1515,7 +1666,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); Date oneHourAgo = new Date(now.getTime() - 3600L); resp1.setHeader("Cache-Control", "max-age=3600"); @@ -1526,7 +1678,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { } resp1.setEntity(new ByteArrayEntity(bytes1)); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control", "no-cache"); req2.setHeader("Range", "bytes=0-50"); @@ -1544,7 +1697,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setEntity(new ByteArrayEntity(bytes2)); Date inTwoSeconds = new Date(now.getTime() + 2000L); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Date", DateUtils.formatDate(inTwoSeconds)); resp3.setHeader("Cache-Control", "max-age=3600"); @@ -1556,19 +1710,31 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setEntity(new ByteArrayEntity(bytes3)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp3).times(0, 1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp3)).times(0, 1); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); @@ -1599,11 +1765,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { if (!impl.supportsRangeAndContentRangeHeaders()) { emptyMockCacheExpectsNoPuts(); - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); request.addHeader("Range", "bytes=0-50"); - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, - "Partial Content"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, + "Partial Content")); originResponse.setHeader("Content-Range", "bytes 0-50/128"); originResponse.setHeader("Cache-Control", "max-age=3600"); byte[] bytes = new byte[51]; @@ -1611,12 +1779,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setEntity(new ByteArrayEntity(bytes)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock - .isA(HttpRequest.class), (HttpContext) EasyMock.isNull())).andReturn( - originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); } } @@ -1633,7 +1804,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other")); originResponse.setHeader("Date", DateUtils.formatDate(new Date())); originResponse.setHeader("Server", "MockServer/1.0"); originResponse.setHeader("Cache-Control", "max-age=3600"); @@ -1642,11 +1814,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setEntity(HttpTestUtils.makeBody(entityLength)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); } @@ -1660,19 +1835,24 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void test304ResponseDoesNotContainABody() throws Exception { request.setHeader("If-None-Match", "\"etag\""); - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, + "Not Modified")); originResponse.setHeader("Date", DateUtils.formatDate(new Date())); originResponse.setHeader("Server", "MockServer/1.0"); originResponse.setHeader("Content-Length", "128"); originResponse.setEntity(HttpTestUtils.makeBody(entityLength)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); @@ -1692,17 +1872,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request.setHeader("If-None-Match", "\"etag\""); - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, + "Not Modified")); originResponse.setHeader("Date", DateUtils.formatDate(new Date())); originResponse.setHeader("Server", "MockServer/1.0"); originResponse.setHeader("ETag", "\"etag\""); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Date")); @@ -1711,20 +1896,25 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test304ResponseGeneratedFromCacheIncludesDateHeader() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setHeader("ETag", "\"etag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("If-None-Match", "\"etag\""); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse).times(1, 2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { @@ -1741,20 +1931,25 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void test304ResponseGeneratedFromCacheIncludesEtagIfOriginResponseDid() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setHeader("ETag", "\"etag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("If-None-Match", "\"etag\""); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse).times(1, 2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { @@ -1765,21 +1960,26 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test304ResponseGeneratedFromCacheIncludesContentLocationIfOriginResponseDid() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setHeader("Content-Location", "http://foo.example.com/other"); originResponse.setHeader("ETag", "\"etag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("If-None-Match", "\"etag\""); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse).times(1, 2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { @@ -1801,7 +2001,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date inTwoHours = new Date(now.getTime() + 2 * 3600 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Accept-Encoding", "gzip"); HttpResponse resp1 = HttpTestUtils.make200Response(); @@ -1811,7 +2012,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Vary", "Accept-Encoding"); resp1.setEntity(HttpTestUtils.makeBody(entityLength)); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Accept-Encoding", "gzip"); req1.setHeader("Cache-Control", "no-cache"); @@ -1822,21 +2024,30 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Vary", "Accept-Encoding"); resp2.setEntity(HttpTestUtils.makeBody(entityLength)); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.setHeader("Accept-Encoding", "gzip"); req3.setHeader("If-None-Match", "\"v2\""); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp2).times(1, 2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)).times(1, 2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); @@ -1861,7 +2072,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "W/\"v1\""); @@ -1874,16 +2086,21 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Last-Modified", DateUtils.formatDate(oneHourAgo)); resp1.setHeader("Cache-Control", "max-age=7200"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("If-None-Match", "W/\"v1\""); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1).times(1, 2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); @@ -1911,13 +2128,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); // load cache with cacheable entry - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag1\""); resp1.setHeader("Cache-Control", "max-age=3600"); // force a revalidation - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control", "max-age=0,max-stale=0"); // updated ETag provided to a conditional revalidation @@ -1928,31 +2147,45 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("ETag", "\"etag2\""); // conditional validation uses If-None-Match - HttpRequest conditionalValidation = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper conditionalValidation = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); conditionalValidation.setHeader("If-None-Match", "\"etag1\""); // unconditional validation doesn't use If-None-Match - HttpRequest unconditionalValidation = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper unconditionalValidation = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); // new response to unconditional validation provides new body HttpResponse resp3 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag2\""); resp1.setHeader("Cache-Control", "max-age=3600"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)); // this next one will happen once if the cache tries to // conditionally validate, zero if it goes full revalidation EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), eqRequest(conditionalValidation), - (HttpContext) EasyMock.isNull())).andReturn(resp2).times(0, 1); + mockBackend.execute( + EasyMock.eq(route), + eqRequest(conditionalValidation), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)).times(0, 1); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), eqRequest(unconditionalValidation), - (HttpContext) EasyMock.isNull())).andReturn(resp3); + mockBackend.execute( + EasyMock.eq(route), + eqRequest(unconditionalValidation), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @@ -1970,22 +2203,27 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date inFiveSeconds = new Date(now.getTime() + 5000L); - HttpRequest initialRequest = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper initialRequest = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse cachedResponse = HttpTestUtils.make200Response(); cachedResponse.setHeader("Cache-Control", "max-age=3600"); cachedResponse.setHeader("ETag", "\"etag\""); - HttpRequest secondRequest = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper secondRequest = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); secondRequest.setHeader("Cache-Control", "max-age=0,max-stale=0"); - HttpRequest conditionalValidationRequest = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper conditionalValidationRequest = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); conditionalValidationRequest.setHeader("If-None-Match", "\"etag\""); - HttpRequest unconditionalValidationRequest = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper unconditionalValidationRequest = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); // to be used if the cache generates a conditional validation - HttpResponse conditionalResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + HttpResponse conditionalResponse = new BasicHttpResponse( + HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); conditionalResponse.setHeader("Date", DateUtils.formatDate(inFiveSeconds)); conditionalResponse.setHeader("Server", "MockUtils/1.0"); conditionalResponse.setHeader("ETag", "\"etag\""); @@ -1996,25 +2234,35 @@ public class TestProtocolRequirements extends AbstractProtocolTest { unconditionalResponse.setHeader("Date", DateUtils.formatDate(inFiveSeconds)); unconditionalResponse.setHeader("ETag", "\"etag\""); - Capture cap1 = new Capture(); - Capture cap2 = new Capture(); + Capture cap1 = new Capture(); + Capture cap2 = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(cachedResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(cachedResponse)); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.and( - eqRequest(conditionalValidationRequest), EasyMock.capture(cap1)), - (HttpContext) EasyMock.isNull())).andReturn(conditionalResponse).times(0, 1); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.and(eqRequest(conditionalValidationRequest), EasyMock.capture(cap1)), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(conditionalResponse)).times(0, 1); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.and( - eqRequest(unconditionalValidationRequest), EasyMock.capture(cap2)), - (HttpContext) EasyMock.isNull())).andReturn(unconditionalResponse).times(0, 1); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.and(eqRequest(unconditionalValidationRequest), EasyMock.capture(cap2)), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(unconditionalResponse)).times(0, 1); replayMocks(); - impl.execute(host, initialRequest); - HttpResponse result = impl.execute(host, secondRequest); + impl.execute(route, initialRequest); + HttpResponse result = impl.execute(route, secondRequest); verifyMocks(); @@ -2037,15 +2285,19 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testMustIncludeWWWAuthenticateHeaderOnAnOrigin401Response() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Unauthorized"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Unauthorized")); originResponse.setHeader("WWW-Authenticate", "x-scheme x-param"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); if (result.getStatusLine().getStatusCode() == 401) { Assert.assertNotNull(result.getFirstHeader("WWW-Authenticate")); } @@ -2061,14 +2313,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testMustIncludeAllowHeaderFromAnOrigin405Response() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, 405, "Method Not Allowed"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, 405, "Method Not Allowed")); originResponse.setHeader("Allow", "GET, HEAD"); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); if (result.getStatusLine().getStatusCode() == 405) { Assert.assertNotNull(result.getFirstHeader("Allow")); } @@ -2085,15 +2338,19 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testMustIncludeProxyAuthenticateHeaderFromAnOrigin407Response() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, 407, "Proxy Authentication Required"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, 407, "Proxy Authentication Required")); originResponse.setHeader("Proxy-Authenticate", "x-scheme x-param"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); if (result.getStatusLine().getStatusCode() == 407) { Assert.assertNotNull(result.getFirstHeader("Proxy-Authenticate")); } @@ -2109,14 +2366,18 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testMustNotAddMultipartByteRangeContentTypeTo416Response() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, 416, "Requested Range Not Satisfiable"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, 416, "Requested Range Not Satisfiable")); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); if (result.getStatusLine().getStatusCode() == 416) { @@ -2136,24 +2397,32 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Content-Length", "128"); originResponse.setHeader("Cache-Control", "max-age=3600"); - HttpRequest rangeReq = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper rangeReq = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); rangeReq.setHeader("Range", "bytes=1000-1200"); HttpResponse orig416 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 416, "Requested Range Not Satisfiable"); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(originResponse); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); // cache may 416 me right away if it understands byte ranges, // ok to delegate to origin though EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(orig416).times(0, 1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(orig416)).times(0, 1); replayMocks(); - impl.execute(host, request); - HttpResponse result = impl.execute(host, rangeReq); + impl.execute(route, request); + HttpResponse result = impl.execute(route, rangeReq); verifyMocks(); // might have gotten a 416 from the origin or the cache @@ -2214,30 +2483,39 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, config); + impl = new CachingExec(mockBackend, mockCache, config); - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); - HttpRequest validate = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); + HttpRequestWrapper validate = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); validate.setHeader("If-None-Match", "\"etag\""); - HttpResponse notModified = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, - "Not Modified"); + CloseableHttpResponse notModified = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified")); notModified.setHeader("Date", DateUtils.formatDate(now)); notModified.setHeader("ETag", "\"etag\""); mockCache.flushInvalidatedCacheEntriesFor(host, request); EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), eqRequest(validate), (HttpContext) EasyMock - .isNull())).andReturn(notModified); - EasyMock.expect(mockCache.updateCacheEntry(EasyMock.same(host), EasyMock.same(request), - EasyMock.same(entry), EasyMock.same(notModified), EasyMock.isA(Date.class), + mockBackend.execute( + EasyMock.eq(route), + eqRequest(validate), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(notModified); + EasyMock.expect(mockCache.updateCacheEntry( + EasyMock.same(host), + EasyMock.same(request), + EasyMock.same(entry), + EasyMock.same(notModified), + EasyMock.isA(Date.class), EasyMock.isA(Date.class))) .andReturn(HttpTestUtils.makeCacheEntry()); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); } @@ -2260,14 +2538,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, config); + impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); mockCache.flushInvalidatedCacheEntriesFor(host, request); EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(200, result.getStatusLine().getStatusCode()); @@ -2308,19 +2586,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, config); + impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); mockCache.flushInvalidatedCacheEntriesFor(host, request); EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andThrow( + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andThrow( new IOException("can't talk to origin!")).anyTimes(); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); @@ -2360,7 +2641,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 25 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag", "\"etag\""); @@ -2368,9 +2649,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Warning", "110 squid \"stale stuff\""); resp1.setHeader("Via", "1.1 fred"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpRequest validate = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper validate = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); validate.setHeader("If-None-Match", "\"etag\""); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, @@ -2380,21 +2662,24 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("ETag", "\"etag\""); resp2.setHeader("Via", "1.1 fred"); - backendExpectsAnyRequest().andReturn(resp1); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - eqRequest(validate), - (HttpContext)EasyMock.isNull())) - .andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + eqRequest(validate), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); replayMocks(); - HttpResponse stale = impl.execute(host, req1); + HttpResponse stale = impl.execute(route, req1); Assert.assertNotNull(stale.getFirstHeader("Warning")); - HttpResponse result1 = impl.execute(host, req2); - HttpResponse result2 = impl.execute(host, req3); + HttpResponse result1 = impl.execute(route, req2); + HttpResponse result2 = impl.execute(route, req3); verifyMocks(); @@ -2425,7 +2710,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void test2xxWarningsAreNotDeletedAfterSuccessfulRevalidation() throws Exception { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag", "\"etag\""); @@ -2433,9 +2718,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Via", "1.1 xproxy"); resp1.setHeader("Warning", "214 xproxy \"transformed stuff\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpRequest validate = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper validate = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); validate.setHeader("If-None-Match", "\"etag\""); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, @@ -2445,21 +2731,25 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("ETag", "\"etag\""); resp1.setHeader("Via", "1.1 xproxy"); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), eqRequest(validate), (HttpContext) EasyMock - .isNull())).andReturn(resp2); + mockBackend.execute( + EasyMock.eq(route), + eqRequest(validate), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); replayMocks(); - HttpResponse stale = impl.execute(host, req1); + HttpResponse stale = impl.execute(route, req1); Assert.assertNotNull(stale.getFirstHeader("Warning")); - HttpResponse result1 = impl.execute(host, req2); - HttpResponse result2 = impl.execute(host, req3); + HttpResponse result1 = impl.execute(route, req2); + HttpResponse result2 = impl.execute(route, req3); verifyMocks(); @@ -2510,14 +2800,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, config); + impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); mockCache.flushInvalidatedCacheEntriesFor(host, request); EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(200, result.getStatusLine().getStatusCode()); @@ -2561,11 +2851,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(requestTime, responseTime, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, config); + impl = new CachingExec(mockBackend, mockCache, config); - request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); - HttpResponse validated = HttpTestUtils.make200Response(); + CloseableHttpResponse validated = Proxies.enhanceResponse(HttpTestUtils.make200Response()); validated.setHeader("Cache-Control", "public"); validated.setHeader("Last-Modified", DateUtils.formatDate(oneYearAgo)); validated.setHeader("Content-Length", "128"); @@ -2573,23 +2864,32 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpResponse reconstructed = HttpTestUtils.make200Response(); - Capture cap = new Capture(); + Capture cap = new Capture(); mockCache.flushInvalidatedCacheEntriesFor(host, request); - mockCache.flushInvalidatedCacheEntriesFor(EasyMock.isA(HttpHost.class), - EasyMock.isA(HttpRequest.class), EasyMock.isA(HttpResponse.class)); + mockCache.flushInvalidatedCacheEntriesFor( + EasyMock.isA(HttpHost.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpResponse.class)); EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.capture(cap), - (HttpContext) EasyMock.isNull())).andReturn(validated).times(0, 1); - EasyMock.expect(mockCache.getCacheEntry(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class))) - .andReturn(entry).times(0, 1); - EasyMock.expect(mockCache.cacheAndReturnResponse(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - EasyMock.same(validated), EasyMock.isA(Date.class), EasyMock.isA(Date.class))) - .andReturn(reconstructed).times(0, 1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(validated).times(0, 1); + EasyMock.expect(mockCache.getCacheEntry( + EasyMock.isA(HttpHost.class), + EasyMock.isA(HttpRequestWrapper.class))).andReturn(entry).times(0, 1); + EasyMock.expect(mockCache.cacheAndReturnResponse( + EasyMock.isA(HttpHost.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.same(validated), + EasyMock.isA(Date.class), + EasyMock.isA(Date.class))).andReturn(reconstructed).times(0, 1); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(200, result.getStatusLine().getStatusCode()); @@ -2623,7 +2923,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date inFiveSecond = new Date(now.getTime() + 5 * 1000L); // put an entry in the cache - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(inFiveSecond)); @@ -2632,7 +2933,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Content-Length", "128"); // force another origin hit - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control", "no-cache"); HttpResponse resp2 = HttpTestUtils.make200Response(); @@ -2641,18 +2943,23 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Cache-Control", "max-age=3600"); resp2.setHeader("Content-Length", "128"); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), eqRequest(req1), - (HttpContext) EasyMock.isNull())).andReturn(resp1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + eqRequest(req1), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - HttpResponse result = impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + HttpResponse result = impl.execute(route, req3); verifyMocks(); Assert.assertEquals("\"etag1\"", result.getFirstHeader("ETag").getValue()); } @@ -2673,13 +2980,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ private HttpResponse testRequestWithWeakETagValidatorIsNotAllowed(String header) throws Exception { - Capture cap = new Capture(); + Capture cap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.capture(cap), - (HttpContext) EasyMock.isNull())).andReturn(originResponse).times(0, 1); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse).times(0, 1); replayMocks(); - HttpResponse response = impl.execute(host, request); + HttpResponse response = impl.execute(route, request); verifyMocks(); // it's probably ok to return a 400 (Bad Request) to this client @@ -2728,7 +3038,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testDELETEWithIfMatchWeakETagIsNotAllowed() throws Exception { - request = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); request.setHeader("If-Match", "W/\"etag\""); testRequestWithWeakETagValidatorIsNotAllowed("If-Match"); @@ -2736,7 +3047,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testDELETEWithIfNoneMatchWeakETagIsNotAllowed() throws Exception { - request = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); request.setHeader("If-None-Match", "W/\"etag\""); testRequestWithWeakETagValidatorIsNotAllowed("If-None-Match"); @@ -2752,7 +3064,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testSubrangeGETMustUseStrongComparisonForCachedResponse() throws Exception { Date now = new Date(); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); @@ -2763,17 +3076,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { // marked weak. Therefore, the If-Range must fail and we must // either get an error back or the full entity, but we better // not get the conditionally-requested Partial Content (206). - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range", "bytes=0-50"); req2.setHeader("If-Range", "W/\"etag\""); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1).times(1, 2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)).times(1, 2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertFalse(HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()); @@ -2792,28 +3110,38 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag", "W/\"etag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control", "max-age=0,max-stale=0"); - Capture cap = new Capture(); + Capture cap = new Capture(); EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)); EasyMock.expect( - mockBackend.execute(EasyMock.eq(host), EasyMock.capture(cap), - (HttpContext) EasyMock.isNull())).andReturn(resp1); + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); HttpRequest validation = cap.getValue(); @@ -2862,25 +3190,31 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); Date twentySecondsAgo = new Date(now.getTime() - 20 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag", "W/\"etag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("If-None-Match", "W/\"etag\""); req2.setHeader("If-Modified-Since", DateUtils.formatDate(twentySecondsAgo)); // must hit the origin again for the second request EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1).times(2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)).times(2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertFalse(HttpStatus.SC_NOT_MODIFIED == result.getStatusLine().getStatusCode()); @@ -2892,26 +3226,31 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag", "W/\"etag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("If-None-Match", "W/\"etag\""); req2.setHeader("If-Modified-Since", DateUtils.formatDate(tenSecondsAgo)); // may hit the origin again for the second request EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), - EasyMock.isA(HttpRequest.class), - (HttpContext) EasyMock.isNull())).andReturn(resp1).times(1,2); + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp1)).times(1,2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @@ -2929,7 +3268,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { if (!impl.supportsRangeAndContentRangeHeaders()) { emptyMockCacheExpectsNoPuts(); - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Range", "bytes=0-50"); HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, 206, "Partial Content"); @@ -2937,13 +3277,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp.setHeader("ETag", "\"etag\""); resp.setHeader("Cache-Control", "max-age=3600"); - EasyMock.expect( - mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock - .isA(HttpRequest.class), (HttpContext) EasyMock.isNull())).andReturn( - resp); + EasyMock.expect(mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(Proxies.enhanceResponse(resp)); replayMocks(); - impl.execute(host, req); + impl.execute(route, req); verifyMocks(); } } @@ -2961,7 +3302,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void test302ResponseWithoutExplicitCacheabilityIsNotReturnedFromCache() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, 302, "Temporary Redirect"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, 302, "Temporary Redirect")); originResponse.setHeader("Location", "http://foo.example.com/other"); originResponse.removeHeaders("Expires"); originResponse.removeHeaders("Cache-Control"); @@ -2969,8 +3311,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse).times(2); replayMocks(); - impl.execute(host, request); - impl.execute(host, request); + impl.execute(route, request); + impl.execute(route, request); verifyMocks(); } @@ -2980,13 +3322,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * already present: - Content-Location - Content-MD5 - ETag - Last-Modified */ private void testDoesNotModifyHeaderFromOrigin(String header, String value) throws Exception { - originResponse = HttpTestUtils.make200Response(); + originResponse = Proxies.enhanceResponse(HttpTestUtils.make200Response()); originResponse.setHeader(header, value); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); @@ -3021,7 +3363,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertNull(result.getFirstHeader(header)); @@ -3050,18 +3392,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest { private void testDoesNotModifyHeaderFromOriginOnCacheHit(String header, String value) throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - originResponse = HttpTestUtils.make200Response(); + originResponse = Proxies.enhanceResponse(HttpTestUtils.make200Response()); originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setHeader(header, value); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); @@ -3091,8 +3435,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { private void testDoesNotAddHeaderOnCacheHit(String header) throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); originResponse.addHeader("Cache-Control", "max-age=3600"); originResponse.removeHeaders(header); @@ -3100,8 +3446,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertNull(result.getFirstHeader(header)); @@ -3134,15 +3480,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req.setHeader("Content-Length","128"); req.setHeader(header,value); - Capture cap = new Capture(); + Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - EasyMock.capture(cap), - (HttpContext)EasyMock.isNull())) - .andReturn(originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, req); + impl.execute(route, HttpRequestWrapper.wrap(req)); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -3179,15 +3527,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req.setHeader("Content-Length","128"); req.removeHeaders(header); - Capture cap = new Capture(); + Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - EasyMock.capture(cap), - (HttpContext)EasyMock.isNull())) - .andReturn(originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, req); + impl.execute(route, HttpRequestWrapper.wrap(req)); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -3241,7 +3591,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Header expHdr = result.getFirstHeader("Expires"); @@ -3253,8 +3603,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testExpiresHeaderMatchesDateIfAddedToCacheHit() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); originResponse.setHeader("Cache-Control","max-age=3600"); originResponse.removeHeaders("Expires"); @@ -3262,8 +3614,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Header expHdr = result.getFirstHeader("Expires"); @@ -3286,7 +3638,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); @@ -3302,7 +3654,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request.setHeader("If-Range","\"etag\""); request.setHeader("Range","bytes=0-49"); - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, 206, "Partial Content"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_1, 206, "Partial Content")); originResponse.setEntity(HttpTestUtils.makeBody(50)); testDoesNotModifyHeaderFromOriginResponseWithNoTransform("Content-Range","bytes 0-49/128"); } @@ -3313,8 +3666,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { } private void testDoesNotModifyHeaderOnCachedResponseWithNoTransform(String header, String value) throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); originResponse.addHeader("Cache-Control","max-age=3600, no-transform"); originResponse.setHeader(header, value); @@ -3322,8 +3677,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); @@ -3341,10 +3696,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testDoesNotModifyContentRangeHeaderOnCachedResponseWithNoTransform() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("If-Range","\"etag\""); req1.setHeader("Range","bytes=0-49"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("If-Range","\"etag\""); req2.setHeader("Range","bytes=0-49"); @@ -3354,8 +3711,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse).times(1,2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); Assert.assertEquals("bytes 0-49/128", @@ -3442,21 +3799,23 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.3 */ public void testCachedEntityBodyIsUsedForResponseAfter304Validation() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("ETag","\"etag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control","max-age=0, max-stale=0"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); - backendExpectsAnyRequest().andReturn(resp1); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); InputStream i1 = resp1.getEntity().getContent(); @@ -3500,24 +3859,26 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testResponseIncludesCacheEntryEndToEndHeadersForResponseAfter304Validation() throws Exception { - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("ETag","\"etag\""); decorateWithEndToEndHeaders(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control", "max-age=0, max-stale=0"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); resp2.setHeader("Date", DateUtils.formatDate(new Date())); resp2.setHeader("Server", "MockServer/1.0"); - backendExpectsAnyRequest().andReturn(resp1); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); String[] endToEndHeaders = { @@ -3535,13 +3896,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testUpdatedEndToEndHeadersFrom304ArePassedOnResponseAndUpdatedInCacheEntry() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("ETag","\"etag\""); decorateWithEndToEndHeaders(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control", "max-age=0, max-stale=0"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); resp2.setHeader("Cache-Control", "max-age=1800"); @@ -3556,15 +3919,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Pragma","x-new-pragma"); resp2.setHeader("Retry-After","120"); - backendExpectsAnyRequest().andReturn(resp1); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); replayMocks(); - impl.execute(host, req1); - HttpResponse result1 = impl.execute(host, req2); - HttpResponse result2 = impl.execute(host, req3); + impl.execute(route, req1); + HttpResponse result1 = impl.execute(route, req2); + HttpResponse result2 = impl.execute(route, req3); verifyMocks(); String[] endToEndHeaders = { @@ -3586,26 +3950,29 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testMultiHeadersAreSuccessfullyReplacedOn304Validation() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.addHeader("Cache-Control","max-age=3600"); resp1.addHeader("Cache-Control","public"); resp1.setHeader("ETag","\"etag\""); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control", "max-age=0, max-stale=0"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); resp2.setHeader("Cache-Control", "max-age=1800"); - backendExpectsAnyRequest().andReturn(resp1); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); replayMocks(); - impl.execute(host, req1); - HttpResponse result1 = impl.execute(host, req2); - HttpResponse result2 = impl.execute(host, req3); + impl.execute(route, req1); + HttpResponse result1 = impl.execute(route, req2); + HttpResponse result2 = impl.execute(route, req3); verifyMocks(); final String h = "Cache-Control"; @@ -3638,7 +4005,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testCannotCombinePartialResponseIfIncomingResponseDoesNotHaveACacheValidator() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Range","bytes=0-49"); Date now = new Date(); @@ -3653,9 +4021,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("ETag","\"etag1\""); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3665,21 +4034,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -3691,7 +4061,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); Date twoSecondsAgo = new Date(now.getTime() - 2 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3701,9 +4072,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3714,21 +4086,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -3740,7 +4113,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); Date twoSecondsAgo = new Date(now.getTime() - 2 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3751,9 +4125,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3764,21 +4139,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -3790,7 +4166,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); Date twoSecondsAgo = new Date(now.getTime() - 2 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3801,9 +4178,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3813,9 +4191,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.setHeader("Range","bytes=0-49"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -3824,12 +4203,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -3841,7 +4220,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); Date twoSecondsAgo = new Date(now.getTime() - 2 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3851,9 +4231,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3864,9 +4245,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.setHeader("Range","bytes=0-49"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -3875,12 +4257,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -3892,7 +4274,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); Date twoSecondsAgo = new Date(now.getTime() - 2 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3903,9 +4286,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3916,9 +4300,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.setHeader("Range","bytes=0-49"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -3927,12 +4312,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -3944,7 +4329,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); Date twoSecondsAgo = new Date(now.getTime() - 2 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3955,9 +4341,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -3968,9 +4355,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.setHeader("Range","bytes=50-127"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -3979,12 +4367,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -3995,7 +4383,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -4006,9 +4395,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); @@ -4019,9 +4409,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req3.setHeader("Range","bytes=0-49"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); @@ -4030,12 +4421,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, req2); + impl.execute(route, req3); verifyMocks(); } @@ -4052,7 +4443,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testCannotUseVariantCacheEntryIfNotAllSelectingRequestHeadersMatch() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Accept-Encoding","gzip"); HttpResponse resp1 = HttpTestUtils.make200Response(); @@ -4060,9 +4452,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary","Accept-Encoding"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.removeHeaders("Accept-Encoding"); HttpResponse resp2 = HttpTestUtils.make200Response(); @@ -4070,11 +4463,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Cache-Control","max-age=3600"); // not allowed to have a cache hit; must forward request - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @@ -4086,27 +4479,29 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testCannotServeFromCacheForVaryStar() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag1\""); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary","*"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag","\"etag1\""); resp2.setHeader("Cache-Control","max-age=3600"); // not allowed to have a cache hit; must forward request - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @@ -4136,7 +4531,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testNonmatchingVariantCannotBeServedFromCacheUnlessConditionallyValidated() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("User-Agent","MyBrowser/1.0"); HttpResponse resp1 = HttpTestUtils.make200Response(); @@ -4145,12 +4541,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Vary","User-Agent"); resp1.setHeader("Content-Type","application/octet-stream"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("User-Agent","MyBrowser/1.5"); - HttpRequest conditional = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper conditional = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); conditional.setHeader("User-Agent","MyBrowser/1.5"); conditional.setHeader("If-None-Match","\"etag1\""); @@ -4162,23 +4560,27 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp304.setHeader("ETag","\"etag1\""); resp304.setHeader("Vary","User-Agent"); - Capture condCap = new Capture(); - Capture uncondCap = new Capture(); + Capture condCap = new Capture(); + Capture uncondCap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.isA(HttpHost.class), - EasyMock.and(eqRequest(conditional), - EasyMock.capture(condCap)), - (HttpContext)EasyMock.isNull())) - .andReturn(resp304).times(0,1); - EasyMock.expect(mockBackend.execute(EasyMock.isA(HttpHost.class), - EasyMock.and(eqRequest(req2), - EasyMock.capture(uncondCap)), - (HttpContext)EasyMock.isNull())) - .andReturn(resp200).times(0,1); + EasyMock.expect( + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.and(eqRequest(conditional), EasyMock.capture(condCap)), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp304)).times(0,1); + EasyMock.expect( + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.and(eqRequest(req2), EasyMock.capture(uncondCap)), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp200)).times(0,1); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); if (HttpStatus.SC_OK == result.getStatusLine().getStatusCode()) { @@ -4210,7 +4612,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); int status = result.getStatusLine().getStatusCode(); @@ -4233,144 +4635,148 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.9 */ protected void testUnsafeOperationInvalidatesCacheForThatUri( - HttpRequest unsafeReq) throws Exception, IOException { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper unsafeReq) throws Exception, IOException { + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Cache-Control","public, max-age=3600"); // this origin request MUST happen due to invalidation - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, unsafeReq); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, unsafeReq); + impl.execute(route, req3); verifyMocks(); } @Test public void testPutToUriInvalidatesCacheForThatUri() throws Exception { HttpRequest req = makeRequestWithBody("PUT","/"); - testUnsafeOperationInvalidatesCacheForThatUri(req); + testUnsafeOperationInvalidatesCacheForThatUri(HttpRequestWrapper.wrap(req)); } @Test public void testDeleteToUriInvalidatesCacheForThatUri() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE","/")); + HttpRequestWrapper req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE","/")); testUnsafeOperationInvalidatesCacheForThatUri(req); } @Test public void testPostToUriInvalidatesCacheForThatUri() throws Exception { - HttpRequest req = makeRequestWithBody("POST","/"); + HttpRequestWrapper req = makeRequestWithBody("POST","/"); testUnsafeOperationInvalidatesCacheForThatUri(req); } protected void testUnsafeMethodInvalidatesCacheForHeaderUri( - HttpRequest unsafeReq) throws Exception, IOException { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); + HttpRequestWrapper unsafeReq) throws Exception, IOException { + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Cache-Control","public, max-age=3600"); // this origin request MUST happen due to invalidation - backendExpectsAnyRequest().andReturn(resp3); + backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(host, req1); - impl.execute(host, unsafeReq); - impl.execute(host, req3); + impl.execute(route, req1); + impl.execute(route, unsafeReq); + impl.execute(route, req3); verifyMocks(); } protected void testUnsafeMethodInvalidatesCacheForUriInContentLocationHeader( - HttpRequest unsafeReq) throws Exception, IOException { + HttpRequestWrapper unsafeReq) throws Exception, IOException { unsafeReq.setHeader("Content-Location","http://foo.example.com/content"); testUnsafeMethodInvalidatesCacheForHeaderUri(unsafeReq); } protected void testUnsafeMethodInvalidatesCacheForRelativeUriInContentLocationHeader( - HttpRequest unsafeReq) throws Exception, IOException { + HttpRequestWrapper unsafeReq) throws Exception, IOException { unsafeReq.setHeader("Content-Location","/content"); testUnsafeMethodInvalidatesCacheForHeaderUri(unsafeReq); } protected void testUnsafeMethodInvalidatesCacheForUriInLocationHeader( - HttpRequest unsafeReq) throws Exception, IOException { + HttpRequestWrapper unsafeReq) throws Exception, IOException { unsafeReq.setHeader("Location","http://foo.example.com/content"); testUnsafeMethodInvalidatesCacheForHeaderUri(unsafeReq); } @Test public void testPutInvalidatesCacheForThatUriInContentLocationHeader() throws Exception { - HttpRequest req2 = makeRequestWithBody("PUT","/"); + HttpRequestWrapper req2 = makeRequestWithBody("PUT","/"); testUnsafeMethodInvalidatesCacheForUriInContentLocationHeader(req2); } @Test public void testPutInvalidatesCacheForThatUriInLocationHeader() throws Exception { - HttpRequest req = makeRequestWithBody("PUT","/"); + HttpRequestWrapper req = makeRequestWithBody("PUT","/"); testUnsafeMethodInvalidatesCacheForUriInLocationHeader(req); } @Test public void testPutInvalidatesCacheForThatUriInRelativeContentLocationHeader() throws Exception { - HttpRequest req = makeRequestWithBody("PUT","/"); + HttpRequestWrapper req = makeRequestWithBody("PUT","/"); testUnsafeMethodInvalidatesCacheForRelativeUriInContentLocationHeader(req); } @Test public void testDeleteInvalidatesCacheForThatUriInContentLocationHeader() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/")); + HttpRequestWrapper req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/")); testUnsafeMethodInvalidatesCacheForUriInContentLocationHeader(req); } @Test public void testDeleteInvalidatesCacheForThatUriInRelativeContentLocationHeader() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/")); + HttpRequestWrapper req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/")); testUnsafeMethodInvalidatesCacheForRelativeUriInContentLocationHeader(req); } @Test public void testDeleteInvalidatesCacheForThatUriInLocationHeader() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/")); + HttpRequestWrapper req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/")); testUnsafeMethodInvalidatesCacheForUriInLocationHeader(req); } @Test public void testPostInvalidatesCacheForThatUriInContentLocationHeader() throws Exception { - HttpRequest req = makeRequestWithBody("POST","/"); + HttpRequestWrapper req = makeRequestWithBody("POST","/"); testUnsafeMethodInvalidatesCacheForUriInContentLocationHeader(req); } @Test public void testPostInvalidatesCacheForThatUriInLocationHeader() throws Exception { - HttpRequest req = makeRequestWithBody("POST","/"); + HttpRequestWrapper req = makeRequestWithBody("POST","/"); testUnsafeMethodInvalidatesCacheForUriInLocationHeader(req); } @Test public void testPostInvalidatesCacheForRelativeUriInContentLocationHeader() throws Exception { - HttpRequest req = makeRequestWithBody("POST","/"); + HttpRequestWrapper req = makeRequestWithBody("POST","/"); testUnsafeMethodInvalidatesCacheForRelativeUriInContentLocationHeader(req); } @@ -4381,82 +4787,87 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.10 */ protected void testUnsafeMethodDoesNotInvalidateCacheForHeaderUri( - HttpRequest unsafeReq) throws Exception, IOException { + HttpRequestWrapper unsafeReq) throws Exception, IOException { HttpHost otherHost = new HttpHost("bar.example.com"); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); + HttpRoute otherRoute = new HttpRoute(otherHost); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); - HttpRequest req3 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req3 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); replayMocks(); - impl.execute(otherHost, req1); - impl.execute(host, unsafeReq); - impl.execute(otherHost, req3); + impl.execute(otherRoute, req1); + impl.execute(route, unsafeReq); + impl.execute(otherRoute, req3); verifyMocks(); } protected void testUnsafeMethodDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts( - HttpRequest unsafeReq) throws Exception, IOException { + HttpRequestWrapper unsafeReq) throws Exception, IOException { unsafeReq.setHeader("Content-Location","http://bar.example.com/content"); testUnsafeMethodDoesNotInvalidateCacheForHeaderUri(unsafeReq); } protected void testUnsafeMethodDoesNotInvalidateCacheForUriInLocationHeadersFromOtherHosts( - HttpRequest unsafeReq) throws Exception, IOException { + HttpRequestWrapper unsafeReq) throws Exception, IOException { unsafeReq.setHeader("Location","http://bar.example.com/content"); testUnsafeMethodDoesNotInvalidateCacheForHeaderUri(unsafeReq); } - protected HttpRequest makeRequestWithBody(String method, String requestUri) { + protected HttpRequestWrapper makeRequestWithBody(String method, String requestUri) { HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest(method, requestUri, HttpVersion.HTTP_1_1); int nbytes = 128; request.setEntity(HttpTestUtils.makeBody(nbytes)); request.setHeader("Content-Length",""+nbytes); - return request; + return HttpRequestWrapper.wrap(request); } @Test public void testPutDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts() throws Exception { - HttpRequest req = makeRequestWithBody("PUT","/"); + HttpRequestWrapper req = makeRequestWithBody("PUT","/"); testUnsafeMethodDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts(req); } @Test public void testPutDoesNotInvalidateCacheForUriInLocationHeadersFromOtherHosts() throws Exception { - HttpRequest req = makeRequestWithBody("PUT","/"); + HttpRequestWrapper req = makeRequestWithBody("PUT","/"); testUnsafeMethodDoesNotInvalidateCacheForUriInLocationHeadersFromOtherHosts(req); } @Test public void testPostDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts() throws Exception { - HttpRequest req = makeRequestWithBody("POST","/"); + HttpRequestWrapper req = makeRequestWithBody("POST","/"); testUnsafeMethodDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts(req); } @Test public void testPostDoesNotInvalidateCacheForUriInLocationHeadersFromOtherHosts() throws Exception { - HttpRequest req = makeRequestWithBody("POST","/"); + HttpRequestWrapper req = makeRequestWithBody("POST","/"); testUnsafeMethodDoesNotInvalidateCacheForUriInLocationHeadersFromOtherHosts(req); } @Test public void testDeleteDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); testUnsafeMethodDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts(req); } @Test public void testDeleteDoesNotInvalidateCacheForUriInLocationHeadersFromOtherHosts() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); testUnsafeMethodDoesNotInvalidateCacheForUriInLocationHeadersFromOtherHosts(req); } @@ -4472,20 +4883,25 @@ public class TestProtocolRequirements extends AbstractProtocolTest { private void testRequestIsWrittenThroughToOrigin(HttpRequest req) throws Exception { HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - eqRequest(req), - (HttpContext)EasyMock.isNull())) - .andReturn(resp); + HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + eqRequest(wrapper), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp)); replayMocks(); - impl.execute(host, req); + impl.execute(route, wrapper); verifyMocks(); } @Test @Ignore public void testOPTIONSRequestsAreWrittenThroughToOrigin() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS","*",HttpVersion.HTTP_1_1)); + HttpRequest req = HttpRequestWrapper.wrap( + new BasicHttpRequest("OPTIONS","*",HttpVersion.HTTP_1_1)); testRequestIsWrittenThroughToOrigin(req); } @@ -4510,28 +4926,32 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testDELETERequestsAreWrittenThroughToOrigin() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); + HttpRequest req = HttpRequestWrapper.wrap( + new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1)); testRequestIsWrittenThroughToOrigin(req); } @Test public void testTRACERequestsAreWrittenThroughToOrigin() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("TRACE","/",HttpVersion.HTTP_1_1)); + HttpRequest req = HttpRequestWrapper.wrap( + new BasicHttpRequest("TRACE","/",HttpVersion.HTTP_1_1)); testRequestIsWrittenThroughToOrigin(req); } @Test public void testCONNECTRequestsAreWrittenThroughToOrigin() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("CONNECT","/",HttpVersion.HTTP_1_1)); + HttpRequest req = HttpRequestWrapper.wrap( + new BasicHttpRequest("CONNECT","/",HttpVersion.HTTP_1_1)); testRequestIsWrittenThroughToOrigin(req); } @Test public void testUnknownMethodRequestsAreWrittenThroughToOrigin() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("UNKNOWN","/",HttpVersion.HTTP_1_1)); + HttpRequest req = HttpRequestWrapper.wrap( + new BasicHttpRequest("UNKNOWN","/",HttpVersion.HTTP_1_1)); testRequestIsWrittenThroughToOrigin(req); } @@ -4551,7 +4971,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host,request); + HttpResponse result = impl.execute(route,request); verifyMocks(); Assert.assertEquals("2147483648", @@ -4571,7 +4991,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Allow",allowHeaderValue); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host,request); + HttpResponse result = impl.execute(route,request); verifyMocks(); Assert.assertEquals(HttpTestUtils.getCanonicalHeaderValue(originResponse,"Allow"), HttpTestUtils.getCanonicalHeaderValue(result, "Allow")); @@ -4605,26 +5025,28 @@ public class TestProtocolRequirements extends AbstractProtocolTest { protected void testSharedCacheRevalidatesAuthorizedResponse( HttpResponse authorizedResponse, int minTimes, int maxTimes) throws Exception, IOException { - if (impl.isSharedCache()) { + if (config.isSharedCache()) { String authorization = "Basic dXNlcjpwYXNzd2Q="; - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Authorization",authorization); - backendExpectsAnyRequest().andReturn(authorizedResponse); + backendExpectsAnyRequestAndReturn(authorizedResponse); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","max-age=3600"); if (maxTimes > 0) { // this request MUST happen - backendExpectsAnyRequest().andReturn(resp2) - .times(minTimes,maxTimes); + backendExpectsAnyRequest().andReturn( + Proxies.enhanceResponse(resp2)).times(minTimes,maxTimes); } replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } } @@ -4676,29 +5098,34 @@ public class TestProtocolRequirements extends AbstractProtocolTest { protected void testSharedCacheMustUseNewRequestHeadersWhenRevalidatingAuthorizedResponse( HttpResponse authorizedResponse) throws Exception, IOException, ClientProtocolException { - if (impl.isSharedCache()) { + if (config.isSharedCache()) { String authorization1 = "Basic dXNlcjpwYXNzd2Q="; String authorization2 = "Basic dXNlcjpwYXNzd2Qy"; - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req1.setHeader("Authorization",authorization1); - backendExpectsAnyRequest().andReturn(authorizedResponse); + backendExpectsAnyRequestAndReturn(authorizedResponse); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Authorization",authorization2); HttpResponse resp2 = HttpTestUtils.make200Response(); - Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - EasyMock.capture(cap), - (HttpContext)EasyMock.isNull())) - .andReturn(resp2); + Capture cap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(host,req1); - impl.execute(host,req2); + impl.execute(route,req1); + impl.execute(route,req2); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -4751,27 +5178,32 @@ public class TestProtocolRequirements extends AbstractProtocolTest { throws Exception { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","max-age=5"); resp1.setHeader("Etag","\"etag\""); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control","max-stale=60"); HttpResponse resp2 = HttpTestUtils.make200Response(); - Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - EasyMock.capture(cap), - (HttpContext)EasyMock.isNull())) - .andReturn(resp2).times(0,1); + Capture cap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)).times(0,1); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); if (!cap.hasCaptured()) { @@ -4798,15 +5230,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testDoesNotTransmitNoCacheDirectivesWithFieldsDownstream() throws Exception { request.setHeader("Cache-Control","no-cache=\"X-Field\""); - Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - EasyMock.capture(cap), - (HttpContext)EasyMock.isNull())) - .andReturn(originResponse).times(0,1); + Capture cap = new Capture(); + EasyMock.expect(mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse).times(0,1); replayMocks(); try { - impl.execute(host, request); + impl.execute(route, request); } catch (ClientProtocolException acceptable) { } verifyMocks(); @@ -4829,28 +5262,31 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4 */ - protected void testCacheIsNotUsedWhenRespondingToRequest(HttpRequest req) + protected void testCacheIsNotUsedWhenRespondingToRequest(HttpRequestWrapper req) throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Etag","\"etag\""); resp1.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Etag","\"etag2\""); resp2.setHeader("Cache-Control","max-age=1200"); - Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), + Capture cap = new Capture(); + EasyMock.expect(mockBackend.execute( + EasyMock.eq(route), EasyMock.capture(cap), - (HttpContext)EasyMock.isNull())) - .andReturn(resp2); + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req); verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); @@ -4861,7 +5297,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testCacheIsNotUsedWhenRespondingToRequestWithCacheControlNoCache() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Cache-Control","no-cache"); testCacheIsNotUsedWhenRespondingToRequest(req); } @@ -4869,7 +5306,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testCacheIsNotUsedWhenRespondingToRequestWithPragmaNoCache() throws Exception { - HttpRequest req = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req.setHeader("Pragma","no-cache"); testCacheIsNotUsedWhenRespondingToRequest(req); } @@ -4885,26 +5323,31 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ protected void testStaleCacheResponseMustBeRevalidatedWithOrigin( HttpResponse staleResponse) throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - backendExpectsAnyRequest().andReturn(staleResponse); + backendExpectsAnyRequestAndReturn(staleResponse); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control","max-stale=3600"); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag","\"etag2\""); resp2.setHeader("Cache-Control","max-age=5, must-revalidate"); - Capture cap = new Capture(); + Capture cap = new Capture(); // this request MUST happen - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - EasyMock.capture(cap), - (HttpContext)EasyMock.isNull())) - .andReturn(resp2); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(host,req1); - impl.execute(host,req2); + impl.execute(route,req1); + impl.execute(route,req2); verifyMocks(); HttpRequest reval = cap.getValue(); @@ -4940,17 +5383,19 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ protected void testGenerates504IfCannotRevalidateStaleResponse( HttpResponse staleResponse) throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - backendExpectsAnyRequest().andReturn(staleResponse); + backendExpectsAnyRequestAndReturn(staleResponse); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); backendExpectsAnyRequest().andThrow(new SocketTimeoutException()); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, @@ -4979,7 +5424,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testStaleEntryWithProxyRevalidateOnSharedCacheIsNotUsedWithoutRevalidatingWithOrigin() throws Exception { - if (impl.isSharedCache()) { + if (config.isSharedCache()) { HttpResponse response = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); @@ -4994,7 +5439,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testGenerates504IfSharedCacheCannotRevalidateAProxyRevalidateEntry() throws Exception { - if (impl.isSharedCache()) { + if (config.isSharedCache()) { HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); @@ -5015,21 +5460,23 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testCacheControlPrivateIsNotCacheableBySharedCache() throws Exception { - if (impl.isSharedCache()) { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + if (config.isSharedCache()) { + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","private,max-age=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); // this backend request MUST happen - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - impl.execute(host,req2); + impl.execute(route,req1); + impl.execute(route,req2); verifyMocks(); } } @@ -5037,23 +5484,25 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testCacheControlPrivateOnFieldIsNotReturnedBySharedCache() throws Exception { - if (impl.isSharedCache()) { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + if (config.isSharedCache()) { + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("X-Personal","stuff"); resp1.setHeader("Cache-Control","private=\"X-Personal\",s-maxage=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); // this backend request MAY happen - backendExpectsAnyRequest().andReturn(resp2).times(0,1); + backendExpectsAnyRequestAndReturn(resp2).times(0,1); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); Assert.assertNull(result.getFirstHeader("X-Personal")); } @@ -5070,45 +5519,49 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testNoCacheCannotSatisfyASubsequentRequestWithoutRevalidation() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Cache-Control","no-cache"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); // this MUST happen - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - impl.execute(host,req2); + impl.execute(route,req1); + impl.execute(route,req2); verifyMocks(); } @Test public void testNoCacheCannotSatisfyASubsequentRequestWithoutRevalidationEvenWithContraryIndications() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Cache-Control","no-cache,s-maxage=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control","max-stale=7200"); HttpResponse resp2 = HttpTestUtils.make200Response(); // this MUST happen - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - impl.execute(host,req2); + impl.execute(route,req1); + impl.execute(route,req2); verifyMocks(); } @@ -5121,29 +5574,34 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testNoCacheOnFieldIsNotReturnedWithoutRevalidation() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("X-Stuff","things"); resp1.setHeader("Cache-Control","no-cache=\"X-Stuff\", max-age=3600"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag","\"etag\""); resp2.setHeader("X-Stuff","things"); resp2.setHeader("Cache-Control","no-cache=\"X-Stuff\",max-age=3600"); - Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.eq(host), - EasyMock.capture(cap), - (HttpContext)EasyMock.isNull())) - .andReturn(resp2).times(0,1); + Capture cap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.eq(route), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn( + Proxies.enhanceResponse(resp2)).times(0,1); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); if (!cap.hasCaptured()) { @@ -5174,7 +5632,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(host,request); + impl.execute(route,request); verifyMocks(); } @@ -5187,7 +5645,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(host,request); + impl.execute(route,request); verifyMocks(); } @@ -5199,7 +5657,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(host,request); + impl.execute(route,request); verifyMocks(); } @@ -5211,7 +5669,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(host,request); + impl.execute(route,request); verifyMocks(); } @@ -5228,7 +5686,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host,request); + HttpResponse result = impl.execute(route,request); verifyMocks(); int total_encodings = 0; for(Header hdr : result.getHeaders("Content-Encoding")) { @@ -5256,7 +5714,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host,request); + HttpResponse result = impl.execute(route,request); verifyMocks(); int total_encodings = 0; for(Header hdr : result.getHeaders("Content-Encoding")) { @@ -5286,23 +5744,25 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testCacheDoesNotAssumeContentLocationHeaderIndicatesAnotherCacheableResource() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public,max-age=3600"); resp1.setHeader("Etag","\"etag\""); resp1.setHeader("Content-Location","http://foo.example.com/bar"); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/bar", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/bar", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","public,max-age=3600"); resp2.setHeader("Etag","\"etag\""); - backendExpectsAnyRequest().andReturn(resp1); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @@ -5322,7 +5782,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Date")); } @@ -5336,22 +5796,24 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ private void testInvalidExpiresHeaderIsTreatedAsStale( final String expiresHeader) throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public"); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Expires", expiresHeader); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); // second request to origin MUST happen - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @@ -5375,22 +5837,24 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testExpiresHeaderEqualToDateHeaderIsTreatedAsStale() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public"); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Expires", resp1.getFirstHeader("Date").getValue()); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); // second request to origin MUST happen - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - impl.execute(host, req2); + impl.execute(route, req1); + impl.execute(route, req2); verifyMocks(); } @@ -5408,7 +5872,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(server, result.getFirstHeader("Server").getValue()); } @@ -5427,7 +5891,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); int transfer_encodings = 0; for(Header h : result.getHeaders("Transfer-Encoding")) { @@ -5456,7 +5920,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); int transfer_encodings = 0; for(Header h : result.getHeaders("Transfer-Encoding")) { @@ -5496,7 +5960,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); for(Header h : result.getHeaders("Vary")) { for(HeaderElement elt : h.getElements()) { @@ -5514,14 +5978,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testProperlyFormattedViaHeaderIsAddedToRequests() throws Exception { - Capture cap = new Capture(); + Capture cap = new Capture(); request.removeHeaders("Via"); - EasyMock.expect(mockBackend.execute(EasyMock.isA(HttpHost.class), - EasyMock.capture(cap), (HttpContext)EasyMock.isNull())) - .andReturn(originResponse); + EasyMock.expect( + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -5534,7 +6001,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.removeHeaders("Via"); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); assertValidViaHeader(result.getFirstHeader("Via").getValue()); } @@ -5607,13 +6074,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { throws Exception { request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_0)); request.removeHeaders("Via"); - Capture cap = new Capture(); - EasyMock.expect(mockBackend.execute(EasyMock.isA(HttpHost.class), - EasyMock.capture(cap), (HttpContext)EasyMock.isNull())) - .andReturn(originResponse); + Capture cap = new Capture(); + EasyMock.expect( + mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(host, request); + impl.execute(route, request); verifyMocks(); HttpRequest captured = cap.getValue(); @@ -5630,12 +6100,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testViaHeaderOnResponseProperlyRecordsOriginProtocol() throws Exception { - originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_NO_CONTENT, "No Content"); + originResponse = Proxies.enhanceResponse( + new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_NO_CONTENT, "No Content")); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); String via = result.getFirstHeader("Via").getValue(); @@ -5663,7 +6134,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Assert.assertEquals(warning, result.getFirstHeader("Warning").getValue()); @@ -5679,8 +6150,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testUpdatesWarningHeadersOnValidation() throws Exception { - HttpRequest req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); - HttpRequest req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); Date now = new Date(); Date twentySecondsAgo = new Date(now.getTime() - 20 * 1000L); @@ -5698,12 +6171,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final String newWarning = "113 betty \"stale too\""; resp2.setHeader("Warning", newWarning); - backendExpectsAnyRequest().andReturn(resp1); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); boolean oldWarningFound = false; @@ -5738,7 +6211,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Date", dateHdr); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); // note that currently the implementation acts as an HTTP/1.1 proxy, // which means that all the responses from the caching module should @@ -5782,7 +6255,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); for(Header h : result.getHeaders("Warning")) { @@ -5802,7 +6275,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); for(Header h : result.getHeaders("Warning")) { @@ -5821,7 +6294,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - HttpResponse result = impl.execute(host, request); + HttpResponse result = impl.execute(route, request); verifyMocks(); Header[] warningHeaders = result.getHeaders("Warning"); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java index 3bd8479f1..948d81a2f 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java @@ -33,10 +33,10 @@ import java.util.Date; import org.apache.http.Header; import org.apache.http.HttpEntity; -import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; +import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHttpRequest; @@ -68,20 +68,20 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { public void testStaleIfErrorInResponseIsTrueReturnsStaleEntryWithWarning() throws Exception{ Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); HttpTestUtils.assert110WarningFound(result); @@ -91,13 +91,13 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { public void testConsumesErrorResponseWhenServingStale() throws Exception{ Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp2 = HttpTestUtils.make500Response(); byte[] body = HttpTestUtils.getRandomBytes(101); ByteArrayInputStream buf = new ByteArrayInputStream(body); @@ -105,11 +105,11 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { HttpEntity entity = new InputStreamEntity(cis, 101); resp2.setEntity(entity); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - impl.execute(host,req2); + impl.execute(route,req1); + impl.execute(route,req2); verifyMocks(); assertTrue(cis.wasClosed()); @@ -119,20 +119,20 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { public void testStaleIfErrorInResponseYieldsToMustRevalidate() throws Exception{ Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60, must-revalidate"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); @@ -141,22 +141,22 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { @Test public void testStaleIfErrorInResponseYieldsToProxyRevalidateForSharedCache() throws Exception{ - assertTrue(impl.isSharedCache()); + assertTrue(config.isSharedCache()); Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60, proxy-revalidate"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); @@ -167,23 +167,23 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { throws Exception{ CacheConfig config = CacheConfig.custom() .setSharedCache(false).build(); - impl = new CachingHttpClient(mockBackend, config); + impl = new CachingExec(mockBackend, new BasicHttpCache(config), config); Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60, proxy-revalidate"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); HttpTestUtils.assert110WarningFound(result); @@ -193,21 +193,21 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { public void testStaleIfErrorInResponseYieldsToExplicitFreshnessRequest() throws Exception{ Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control","min-fresh=2"); HttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); @@ -217,21 +217,21 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { public void testStaleIfErrorInRequestIsTrueReturnsStaleEntryWithWarning() throws Exception{ Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control","public, stale-if-error=60"); HttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); HttpTestUtils.assert110WarningFound(result); @@ -242,20 +242,20 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { throws Exception{ Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=2"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, @@ -267,21 +267,21 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { throws Exception{ Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpRequest req1 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5"); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = HttpTestUtils.makeDefaultRequest(); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); req2.setHeader("Cache-Control","stale-if-error=2"); HttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequest().andReturn(resp2); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host,req1); - HttpResponse result = impl.execute(host,req2); + impl.execute(route,req1); + HttpResponse result = impl.execute(route,req2); verifyMocks(); assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, @@ -305,9 +305,10 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { .setAsynchronousWorkersMax(1) .build(); - impl = new CachingHttpClient(mockBackend, cache, config); + impl = new CachingExec(mockBackend, cache, config); - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); @@ -315,13 +316,14 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1).times(1,2); + backendExpectsAnyRequestAndReturn(resp1).times(1,2); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -347,9 +349,10 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { .setAsynchronousWorkersMax(1) .setSharedCache(false) .build(); - impl = new CachingHttpClient(mockBackend, cache, config); + impl = new CachingExec(mockBackend, cache, config); - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); @@ -357,14 +360,15 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1).times(1,2); + backendExpectsAnyRequestAndReturn(resp1).times(1,2); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("If-None-Match","\"etag\""); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); @@ -393,27 +397,29 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { .setMaxObjectSize(MAX_BYTES) .setAsynchronousWorkersMax(1) .build(); - impl = new CachingHttpClient(mockBackend, cache, config); + impl = new CachingExec(mockBackend, cache, config); - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + 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"); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); 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); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -442,27 +448,29 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { .setAsynchronousWorkersMax(1) .setSharedCache(true) .build(); - impl = new CachingHttpClient(mockBackend, cache, config); + impl = new CachingExec(mockBackend, cache, config); - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + 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"); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp2 = HttpTestUtils.make200Response(); 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); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -491,28 +499,30 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { .setAsynchronousWorkersMax(1) .setSharedCache(true) .build(); - impl = new CachingHttpClient(mockBackend, cache, config); + impl = new CachingExec(mockBackend, cache, config); - HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req1 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15"); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequest().andReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); - HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequestWrapper req2 = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); req2.setHeader("Cache-Control","min-fresh=2"); HttpResponse resp2 = HttpTestUtils.make200Response(); 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); + backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(host, req1); - HttpResponse result = impl.execute(host, req2); + impl.execute(route, req1); + HttpResponse result = impl.execute(route, req2); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtocolRequirements.java index 7d76bb4fc..7ba56c22e 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtocolRequirements.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtocolRequirements.java @@ -31,12 +31,12 @@ import net.sf.ehcache.config.CacheConfiguration; import net.sf.ehcache.config.Configuration; import net.sf.ehcache.store.MemoryStoreEvictionPolicy; -import org.apache.http.client.HttpClient; import org.apache.http.client.cache.HttpCacheStorage; import org.apache.http.impl.client.cache.CacheConfig; -import org.apache.http.impl.client.cache.CachingHttpClient; +import org.apache.http.impl.client.cache.CachingExec; import org.apache.http.impl.client.cache.HeapResourceFactory; import org.apache.http.impl.client.cache.TestProtocolRequirements; +import org.apache.http.impl.client.execchain.ClientExecChain; import org.easymock.classextension.EasyMock; import org.junit.After; import org.junit.AfterClass; @@ -70,9 +70,9 @@ public class TestEhcacheProtocolRequirements extends TestProtocolRequirements{ } CACHE_MANAGER.addCache(TEST_EHCACHE_NAME); HttpCacheStorage storage = new EhcacheHttpCacheStorage(CACHE_MANAGER.getCache(TEST_EHCACHE_NAME)); - mockBackend = EasyMock.createNiceMock(HttpClient.class); + mockBackend = EasyMock.createNiceMock(ClientExecChain.class); - impl = new CachingHttpClient(mockBackend, new HeapResourceFactory(), storage, config); + impl = new CachingExec(mockBackend, new HeapResourceFactory(), storage, config); } @After diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/memcached/TestMemcachedHttpCacheStorage.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/memcached/TestMemcachedHttpCacheStorage.java index c579d9a37..e06b2eb29 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/memcached/TestMemcachedHttpCacheStorage.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/memcached/TestMemcachedHttpCacheStorage.java @@ -109,7 +109,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { impl.putEntry(url, value); verifyMocks(); } - + @Test public void testCachePutFailsSilentlyWhenWeCannotHashAKey() throws IOException { final String url = "foo"; @@ -127,7 +127,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { impl.putEntry(url, value); verifyMocks(); } - + public void testThrowsIOExceptionWhenMemcachedPutTimesOut() { final String url = "foo"; final String key = "key"; @@ -170,11 +170,11 @@ public class TestMemcachedHttpCacheStorage extends TestCase { impl.putEntry(url, value); fail("should have thrown exception"); } catch (IOException expected) { - + } verifyMocks(); } - + @Test public void testSuccessfulCacheGet() throws UnsupportedEncodingException, IOException { @@ -182,7 +182,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { final String key = "key"; byte[] serialized = HttpTestUtils.getRandomBytes(128); final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(); - + EasyMock.expect(mockKeyHashingScheme.hash(url)).andReturn(key); EasyMock.expect(mockMemcachedClient.get(key)).andReturn(serialized); EasyMock.expect(mockMemcachedCacheEntryFactory.getUnsetCacheEntry()) @@ -190,57 +190,57 @@ public class TestMemcachedHttpCacheStorage extends TestCase { mockMemcachedCacheEntry.set(serialized); EasyMock.expect(mockMemcachedCacheEntry.getStorageKey()).andReturn(url); EasyMock.expect(mockMemcachedCacheEntry.getHttpCacheEntry()).andReturn(cacheEntry); - + replayMocks(); HttpCacheEntry resultingEntry = impl.getEntry(url); verifyMocks(); assertSame(cacheEntry, resultingEntry); } - + @Test public void testTreatsNoneByteArrayFromMemcachedAsCacheMiss() throws UnsupportedEncodingException, IOException { final String url = "foo"; final String key = "key"; - + EasyMock.expect(mockKeyHashingScheme.hash(url)).andReturn(key); EasyMock.expect(mockMemcachedClient.get(key)).andReturn(new Object()); - + replayMocks(); HttpCacheEntry resultingEntry = impl.getEntry(url); verifyMocks(); assertNull(resultingEntry); } - + @Test public void testTreatsNullFromMemcachedAsCacheMiss() throws UnsupportedEncodingException, IOException { final String url = "foo"; final String key = "key"; - + EasyMock.expect(mockKeyHashingScheme.hash(url)).andReturn(key); EasyMock.expect(mockMemcachedClient.get(key)).andReturn(null); - + replayMocks(); HttpCacheEntry resultingEntry = impl.getEntry(url); verifyMocks(); assertNull(resultingEntry); } - + @Test public void testTreatsAsCacheMissIfCannotReconstituteEntry() throws UnsupportedEncodingException, IOException { final String url = "foo"; final String key = "key"; byte[] serialized = HttpTestUtils.getRandomBytes(128); - + EasyMock.expect(mockKeyHashingScheme.hash(url)).andReturn(key); EasyMock.expect(mockMemcachedClient.get(key)).andReturn(serialized); EasyMock.expect(mockMemcachedCacheEntryFactory.getUnsetCacheEntry()) .andReturn(mockMemcachedCacheEntry); mockMemcachedCacheEntry.set(serialized); EasyMock.expectLastCall().andThrow(new MemcachedSerializationException(new Exception())); - + replayMocks(); assertNull(impl.getEntry(url)); verifyMocks(); @@ -250,9 +250,9 @@ public class TestMemcachedHttpCacheStorage extends TestCase { public void testTreatsAsCacheMissIfCantHashStorageKey() throws UnsupportedEncodingException, IOException { final String url = "foo"; - + EasyMock.expect(mockKeyHashingScheme.hash(url)).andThrow(new MemcachedKeyHashingException(new Exception())); - + replayMocks(); assertNull(impl.getEntry(url)); verifyMocks(); @@ -265,7 +265,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { EasyMock.expect(mockKeyHashingScheme.hash(url)).andReturn(key); EasyMock.expect(mockMemcachedClient.get(key)) .andThrow(new OperationTimeoutException("")); - + replayMocks(); try { impl.getEntry(url); @@ -285,7 +285,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { impl.removeEntry(url); verifyMocks(); } - + @Test public void testCacheRemoveHandlesKeyHashingFailure() throws IOException { final String url = "foo"; @@ -302,7 +302,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { EasyMock.expect(mockKeyHashingScheme.hash(url)).andReturn(key); EasyMock.expect(mockMemcachedClient.delete(key)) .andThrow(new OperationTimeoutException("")); - + replayMocks(); try { impl.removeEntry(url); @@ -341,7 +341,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { impl.updateEntry(url, callback); verifyMocks(); } - + @Test public void testCacheUpdateOverwritesNonMatchingHashCollision() throws IOException, HttpCacheUpdateException { @@ -366,7 +366,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { .andReturn(mockMemcachedCacheEntry); mockMemcachedCacheEntry.set(oldBytes); EasyMock.expect(mockMemcachedCacheEntry.getStorageKey()).andReturn("not" + url).anyTimes(); - + EasyMock.expect(mockMemcachedCacheEntryFactory.getMemcachedCacheEntry(url, updatedValue)) .andReturn(mockMemcachedCacheEntry2); EasyMock.expect(mockMemcachedCacheEntry2.toByteArray()).andReturn(newBytes); @@ -389,7 +389,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { final byte[] oldBytes = HttpTestUtils.getRandomBytes(128); CASValue casValue = new CASValue(1, oldBytes); final byte[] newBytes = HttpTestUtils.getRandomBytes(128); - + HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() { public HttpCacheEntry update(HttpCacheEntry old) { @@ -406,7 +406,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { mockMemcachedCacheEntry.set(oldBytes); EasyMock.expect(mockMemcachedCacheEntry.getStorageKey()).andReturn(url); EasyMock.expect(mockMemcachedCacheEntry.getHttpCacheEntry()).andReturn(existingValue); - + EasyMock.expect(mockMemcachedCacheEntryFactory.getMemcachedCacheEntry(url, updatedValue)) .andReturn(mockMemcachedCacheEntry2); EasyMock.expect(mockMemcachedCacheEntry2.toByteArray()).andReturn(newBytes); @@ -419,7 +419,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { impl.updateEntry(url, callback); verifyMocks(); } - + @Test public void testCacheUpdateThrowsExceptionsIfCASFailsEnoughTimes() throws IOException { final String url = "foo"; @@ -429,7 +429,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { final byte[] oldBytes = HttpTestUtils.getRandomBytes(128); CASValue casValue = new CASValue(1, oldBytes); final byte[] newBytes = HttpTestUtils.getRandomBytes(128); - + CacheConfig config = CacheConfig.custom().setMaxUpdateRetries(0).build(); impl = new MemcachedHttpCacheStorage(mockMemcachedClient, config, mockMemcachedCacheEntryFactory, mockKeyHashingScheme); @@ -449,7 +449,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { mockMemcachedCacheEntry.set(oldBytes); EasyMock.expect(mockMemcachedCacheEntry.getStorageKey()).andReturn(url); EasyMock.expect(mockMemcachedCacheEntry.getHttpCacheEntry()).andReturn(existingValue); - + EasyMock.expect(mockMemcachedCacheEntryFactory.getMemcachedCacheEntry(url, updatedValue)) .andReturn(mockMemcachedCacheEntry2); EasyMock.expect(mockMemcachedCacheEntry2.toByteArray()).andReturn(newBytes); @@ -467,7 +467,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { verifyMocks(); } - + @Test public void testCacheUpdateCanUpdateExistingEntryWithRetry() throws IOException, HttpCacheUpdateException { @@ -499,7 +499,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { mockMemcachedCacheEntry.set(oldBytes); EasyMock.expect(mockMemcachedCacheEntry.getStorageKey()).andReturn(url); EasyMock.expect(mockMemcachedCacheEntry.getHttpCacheEntry()).andReturn(existingValue); - + EasyMock.expect(mockMemcachedCacheEntryFactory.getMemcachedCacheEntry(url, updatedValue)) .andReturn(mockMemcachedCacheEntry2); EasyMock.expect(mockMemcachedCacheEntry2.toByteArray()).andReturn(newBytes); @@ -515,7 +515,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { mockMemcachedCacheEntry3.set(oldBytes2); EasyMock.expect(mockMemcachedCacheEntry3.getStorageKey()).andReturn(url); EasyMock.expect(mockMemcachedCacheEntry3.getHttpCacheEntry()).andReturn(existingValue2); - + EasyMock.expect(mockMemcachedCacheEntryFactory.getMemcachedCacheEntry(url, updatedValue2)) .andReturn(mockMemcachedCacheEntry4); EasyMock.expect(mockMemcachedCacheEntry4.toByteArray()).andReturn(newBytes2); @@ -523,7 +523,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { EasyMock.expect( mockMemcachedClient.cas(EasyMock.eq(key), EasyMock.eq(casValue2.getCas()), EasyMock.aryEq(newBytes2))).andReturn(CASResponse.OK); - + replayMocks(); impl.updateEntry(url, callback); verifyMocks(); @@ -557,7 +557,7 @@ public class TestMemcachedHttpCacheStorage extends TestCase { verifyMocks(); } - + @Test(expected=HttpCacheUpdateException.class) public void testThrowsExceptionOnUpdateIfCannotHashStorageKey() throws Exception { final String url = "foo"; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/execchain/MainClientExec.java b/httpclient/src/main/java/org/apache/http/impl/client/execchain/MainClientExec.java index cbf6cf2dc..0dbad4641 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/execchain/MainClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/execchain/MainClientExec.java @@ -167,7 +167,7 @@ public class MainClientExec implements ClientExecChain { } if (request instanceof HttpEntityEnclosingRequest) { - ExecProxies.enhanceEntity((HttpEntityEnclosingRequest) request); + Proxies.enhanceEntity((HttpEntityEnclosingRequest) request); } Object userToken = context.getUserToken(); @@ -220,7 +220,7 @@ public class MainClientExec implements ClientExecChain { HttpResponse response = null; for (int execCount = 1;; execCount++) { - if (execCount > 1 && !ExecProxies.isRepeatable(request)) { + if (execCount > 1 && !Proxies.isRepeatable(request)) { throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity."); } @@ -333,9 +333,9 @@ public class MainClientExec implements ClientExecChain { if (entity == null || !entity.isStreaming()) { // connection not needed and (assumed to be) in re-usable state releaseTrigger.releaseConnection(); - return ExecProxies.enhanceResponse(response, null); + return Proxies.enhanceResponse(response, null); } else { - return ExecProxies.enhanceResponse(response, releaseTrigger); + return Proxies.enhanceResponse(response, releaseTrigger); } } catch (ConnectionShutdownException ex) { InterruptedIOException ioex = new InterruptedIOException( diff --git a/httpclient/src/main/java/org/apache/http/impl/client/execchain/ExecProxies.java b/httpclient/src/main/java/org/apache/http/impl/client/execchain/Proxies.java similarity index 99% rename from httpclient/src/main/java/org/apache/http/impl/client/execchain/ExecProxies.java rename to httpclient/src/main/java/org/apache/http/impl/client/execchain/Proxies.java index a4c19c212..f8d0e7319 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/execchain/ExecProxies.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/execchain/Proxies.java @@ -16,7 +16,7 @@ import org.apache.http.client.methods.CloseableHttpResponse; * @since 4.3 */ @NotThreadSafe -class ExecProxies { +class Proxies { static void enhanceEntity(final HttpEntityEnclosingRequest request) { HttpEntity entity = request.getEntity(); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/execchain/RedirectExec.java b/httpclient/src/main/java/org/apache/http/impl/client/execchain/RedirectExec.java index 607dfde99..bd2c12bbb 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/execchain/RedirectExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/execchain/RedirectExec.java @@ -119,7 +119,7 @@ public class RedirectExec implements ClientExecChain { currentRequest = HttpRequestWrapper.wrap(redirect); currentRequest.setHeaders(original.getAllHeaders()); if (original instanceof HttpEntityEnclosingRequest) { - ExecProxies.enhanceEntity((HttpEntityEnclosingRequest) request); + Proxies.enhanceEntity((HttpEntityEnclosingRequest) request); } URI uri = currentRequest.getURI(); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/execchain/RetryExec.java b/httpclient/src/main/java/org/apache/http/impl/client/execchain/RetryExec.java index f6ca1f90b..70dd1d648 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/execchain/RetryExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/execchain/RetryExec.java @@ -98,7 +98,7 @@ public class RetryExec implements ClientExecChain { if (this.log.isDebugEnabled()) { this.log.debug(ex.getMessage(), ex); } - if (!ExecProxies.isRepeatable(request)) { + if (!Proxies.isRepeatable(request)) { this.log.debug("Cannot retry non-repeatable request"); throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity", ex);