You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2017/10/03 08:51:38 UTC
[3/7] httpcomponents-client git commit: Removed dependency on classic
(blocking) I/O APIs from HttpCache
Removed dependency on classic (blocking) I/O APIs from HttpCache
Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/commit/20f4290d
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/tree/20f4290d
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/diff/20f4290d
Branch: refs/heads/master
Commit: 20f4290d01e55536e93653f1f18cdf347a9aa45c
Parents: 73c67f2
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Mon Oct 2 11:13:42 2017 +0200
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Mon Oct 2 17:34:40 2017 +0200
----------------------------------------------------------------------
.../client5/http/impl/cache/BasicHttpCache.java | 91 +------
.../hc/client5/http/impl/cache/CachingExec.java | 143 +++++++---
.../impl/cache/CachingHttpClientBuilder.java | 2 +-
.../hc/client5/http/impl/cache/HttpCache.java | 15 +-
.../client5/http/impl/cache/HttpTestUtils.java | 8 +
.../http/impl/cache/TestBasicHttpCache.java | 263 ++-----------------
.../http/impl/cache/TestCachingExec.java | 9 +-
.../http/impl/cache/TestCachingExecChain.java | 176 ++++++++++---
.../impl/cache/TestHttpCacheJiraNumber1147.java | 2 +-
.../impl/cache/TestProtocolRequirements.java | 8 +-
.../http/async/methods/SimpleHttpResponse.java | 32 +++
11 files changed, 334 insertions(+), 415 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/BasicHttpCache.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/BasicHttpCache.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/BasicHttpCache.java
index d692fa4..d58b30e 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/BasicHttpCache.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/BasicHttpCache.java
@@ -27,7 +27,6 @@
package org.apache.hc.client5.http.impl.cache;
import java.io.IOException;
-import java.io.InputStream;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
@@ -43,16 +42,10 @@ import org.apache.hc.client5.http.cache.HttpCacheUpdateCallback;
import org.apache.hc.client5.http.cache.HttpCacheUpdateException;
import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.client5.http.cache.ResourceFactory;
-import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.HttpEntity;
-import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
-import org.apache.hc.core5.http.HttpStatus;
-import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
-import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.util.ByteArrayBuffer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -65,9 +58,7 @@ class BasicHttpCache implements HttpCache {
private final CacheKeyGenerator uriExtractor;
private final ResourceFactory resourceFactory;
- private final long maxObjectSizeBytes;
private final CacheEntryUpdater cacheEntryUpdater;
- private final CachedHttpResponseGenerator responseGenerator;
private final HttpCacheInvalidator cacheInvalidator;
private final HttpCacheStorage storage;
@@ -76,14 +67,11 @@ class BasicHttpCache implements HttpCache {
public BasicHttpCache(
final ResourceFactory resourceFactory,
final HttpCacheStorage storage,
- final CacheConfig config,
final CacheKeyGenerator uriExtractor,
final HttpCacheInvalidator cacheInvalidator) {
this.resourceFactory = resourceFactory;
this.uriExtractor = uriExtractor;
this.cacheEntryUpdater = new CacheEntryUpdater(resourceFactory);
- this.maxObjectSizeBytes = config.getMaxObjectSize();
- this.responseGenerator = new CachedHttpResponseGenerator();
this.storage = storage;
this.cacheInvalidator = cacheInvalidator;
}
@@ -91,21 +79,16 @@ class BasicHttpCache implements HttpCache {
public BasicHttpCache(
final ResourceFactory resourceFactory,
final HttpCacheStorage storage,
- final CacheConfig config,
final CacheKeyGenerator uriExtractor) {
- this( resourceFactory, storage, config, uriExtractor,
- new CacheInvalidator(uriExtractor, storage));
+ this(resourceFactory, storage, uriExtractor, new CacheInvalidator(uriExtractor, storage));
}
- public BasicHttpCache(
- final ResourceFactory resourceFactory,
- final HttpCacheStorage storage,
- final CacheConfig config) {
- this( resourceFactory, storage, config, new CacheKeyGenerator());
+ public BasicHttpCache(final ResourceFactory resourceFactory, final HttpCacheStorage storage) {
+ this( resourceFactory, storage, new CacheKeyGenerator());
}
public BasicHttpCache(final CacheConfig config) {
- this(new HeapResourceFactory(), new BasicHttpCacheStorage(config), config);
+ this(new HeapResourceFactory(), new BasicHttpCacheStorage(config));
}
public BasicHttpCache() {
@@ -194,42 +177,6 @@ class BasicHttpCache implements HttpCache {
}
}
- boolean isIncompleteResponse(final HttpResponse resp, final Resource resource) {
- final int status = resp.getCode();
- if (status != HttpStatus.SC_OK
- && status != HttpStatus.SC_PARTIAL_CONTENT) {
- return false;
- }
- final Header hdr = resp.getFirstHeader(HttpHeaders.CONTENT_LENGTH);
- if (hdr == null) {
- return false;
- }
- final int contentLength;
- try {
- contentLength = Integer.parseInt(hdr.getValue());
- } catch (final NumberFormatException nfe) {
- return false;
- }
- if (resource == null) {
- return false;
- }
- return (resource.length() < contentLength);
- }
-
- ClassicHttpResponse generateIncompleteResponseError(
- final HttpResponse response, final Resource resource) {
- final Integer contentLength = Integer.valueOf(response.getFirstHeader(HttpHeaders.CONTENT_LENGTH).getValue());
- final ClassicHttpResponse error = new BasicClassicHttpResponse(HttpStatus.SC_BAD_GATEWAY, "Bad Gateway");
- error.setHeader("Content-Type","text/plain;charset=UTF-8");
- final String msg = String.format("Received incomplete response " +
- "with Content-Length %d but actual body length %d",
- contentLength, resource.length());
- final byte[] msgBytes = msg.getBytes();
- error.setHeader("Content-Length", Integer.toString(msgBytes.length));
- error.setEntity(new ByteArrayEntity(msgBytes));
- return error;
- }
-
HttpCacheEntry doGetUpdatedParentEntry(
final String requestId,
final HttpCacheEntry existing,
@@ -284,37 +231,19 @@ class BasicHttpCache implements HttpCache {
return updatedEntry;
}
- @Override
- public ClassicHttpResponse cacheAndReturnResponse(
+ public HttpCacheEntry createCacheEntry(
final HttpHost host,
final HttpRequest request,
- final ClassicHttpResponse originResponse,
+ final HttpResponse originResponse,
+ final ByteArrayBuffer content,
final Date requestSent,
final Date responseReceived) throws IOException {
final Resource resource;
- final HttpEntity entity = originResponse.getEntity();
- if (entity != null) {
- final ByteArrayBuffer buf = new ByteArrayBuffer(1024);
- final InputStream instream = entity.getContent();
- final byte[] tmp = new byte[2048];
- long total = 0;
- int l;
- while ((l = instream.read(tmp)) != -1) {
- buf.append(tmp, 0, l);
- total += l;
- if (total > maxObjectSizeBytes) {
- originResponse.setEntity(new CombinedEntity(entity, buf));
- return originResponse;
- }
- }
- resource = resourceFactory.generate(request.getRequestUri(), buf.array(), 0, buf.length());
+ if (content != null) {
+ resource = resourceFactory.generate(request.getRequestUri(), content.array(), 0, content.length());
} else {
resource = null;
}
- originResponse.close();
- if (isIncompleteResponse(originResponse, resource)) {
- return generateIncompleteResponseError(originResponse, resource);
- }
final HttpCacheEntry entry = new HttpCacheEntry(
requestSent,
responseReceived,
@@ -322,7 +251,7 @@ class BasicHttpCache implements HttpCache {
originResponse.getAllHeaders(),
resource);
storeInCache(host, request, entry);
- return responseGenerator.generateResponse(request, entry);
+ return entry;
}
@Override
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
index d1670b1..51c13d8 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
@@ -27,6 +27,7 @@
package org.apache.hc.client5.http.impl.cache;
import java.io.IOException;
+import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
@@ -49,8 +50,10 @@ import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement;
+import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost;
@@ -60,12 +63,14 @@ import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.net.URIAuthority;
import org.apache.hc.core5.util.Args;
+import org.apache.hc.core5.util.ByteArrayBuffer;
import org.apache.hc.core5.util.VersionInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -155,7 +160,7 @@ public class CachingExec implements ExecChainHandler {
final ResourceFactory resourceFactory,
final HttpCacheStorage storage,
final CacheConfig config) {
- this(new BasicHttpCache(resourceFactory, storage, config), config);
+ this(new BasicHttpCache(resourceFactory, storage), config);
}
public CachingExec() {
@@ -423,7 +428,7 @@ public class CachingExec implements ExecChainHandler {
final ClassicHttpRequest request,
final HttpContext context,
final HttpCacheEntry entry,
- final Date now) {
+ final Date now) throws IOException {
if (staleResponseNotAllowed(request, entry, now)) {
return generateGatewayTimeout(context);
} else {
@@ -723,48 +728,52 @@ public class CachingExec implements ExecChainHandler {
Date requestDate = getCurrentDate();
ClassicHttpResponse backendResponse = chain.proceed(conditionalRequest, scope);
- Date responseDate = getCurrentDate();
+ try {
+ Date responseDate = getCurrentDate();
- if (revalidationResponseIsTooOld(backendResponse, cacheEntry)) {
- backendResponse.close();
- final ClassicHttpRequest unconditional = conditionalRequestBuilder.buildUnconditionalRequest(
- scope.originalRequest);
- requestDate = getCurrentDate();
- backendResponse = chain.proceed(unconditional, scope);
- responseDate = getCurrentDate();
- }
+ if (revalidationResponseIsTooOld(backendResponse, cacheEntry)) {
+ backendResponse.close();
+ final ClassicHttpRequest unconditional = conditionalRequestBuilder.buildUnconditionalRequest(
+ scope.originalRequest);
+ requestDate = getCurrentDate();
+ backendResponse = chain.proceed(unconditional, scope);
+ responseDate = getCurrentDate();
+ }
- backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse));
+ backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse));
- final int statusCode = backendResponse.getCode();
- if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
- recordCacheUpdate(scope.clientContext);
- }
+ final int statusCode = backendResponse.getCode();
+ if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
+ recordCacheUpdate(scope.clientContext);
+ }
- if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
- final HttpCacheEntry updatedEntry = responseCache.updateCacheEntry(
- target, request, cacheEntry,
- backendResponse, requestDate, responseDate);
- if (suitabilityChecker.isConditional(request)
- && suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) {
- return responseGenerator
- .generateNotModifiedResponse(updatedEntry);
+ if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
+ final HttpCacheEntry updatedEntry = responseCache.updateCacheEntry(
+ target, request, cacheEntry,
+ backendResponse, requestDate, responseDate);
+ if (suitabilityChecker.isConditional(request)
+ && suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) {
+ return responseGenerator.generateNotModifiedResponse(updatedEntry);
+ }
+ return responseGenerator.generateResponse(request, updatedEntry);
}
- return responseGenerator.generateResponse(request, updatedEntry);
- }
- if (staleIfErrorAppliesTo(statusCode)
- && !staleResponseNotAllowed(request, cacheEntry, getCurrentDate())
- && validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
- try {
- final ClassicHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry);
- cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
- return cachedResponse;
- } finally {
- backendResponse.close();
+ if (staleIfErrorAppliesTo(statusCode)
+ && !staleResponseNotAllowed(request, cacheEntry, getCurrentDate())
+ && validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
+ try {
+ final ClassicHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry);
+ cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
+ return cachedResponse;
+ } finally {
+ backendResponse.close();
+ }
}
+ return handleBackendResponse(target, conditionalRequest, scope, requestDate, responseDate, backendResponse);
+ } catch (final IOException | RuntimeException ex) {
+ backendResponse.close();
+ throw ex;
}
- return handleBackendResponse(target, conditionalRequest, scope, requestDate, responseDate, backendResponse);
}
private boolean staleIfErrorAppliesTo(final int statusCode) {
@@ -774,6 +783,66 @@ public class CachingExec implements ExecChainHandler {
|| statusCode == HttpStatus.SC_GATEWAY_TIMEOUT;
}
+ boolean isIncompleteResponse(final HttpResponse resp, final ByteArrayBuffer buffer) {
+ if (buffer == null) {
+ return false;
+ }
+ final int status = resp.getCode();
+ if (status != HttpStatus.SC_OK && status != HttpStatus.SC_PARTIAL_CONTENT) {
+ return false;
+ }
+ final Header hdr = resp.getFirstHeader(HttpHeaders.CONTENT_LENGTH);
+ if (hdr == null) {
+ return false;
+ }
+ final int contentLength;
+ try {
+ contentLength = Integer.parseInt(hdr.getValue());
+ } catch (final NumberFormatException nfe) {
+ return false;
+ }
+ return buffer.length() < contentLength;
+ }
+
+ public ClassicHttpResponse cacheAndReturnResponse(
+ final HttpHost target,
+ final HttpRequest request,
+ final ClassicHttpResponse backendResponse,
+ final Date requestSent,
+ final Date responseReceived) throws IOException { final ByteArrayBuffer buf;
+ final HttpEntity entity = backendResponse.getEntity();
+ if (entity != null) {
+ buf = new ByteArrayBuffer(1024);
+ final InputStream instream = entity.getContent();
+ final byte[] tmp = new byte[2048];
+ long total = 0;
+ int l;
+ while ((l = instream.read(tmp)) != -1) {
+ buf.append(tmp, 0, l);
+ total += l;
+ if (total > cacheConfig.getMaxObjectSize()) {
+ backendResponse.setEntity(new CombinedEntity(entity, buf));
+ return backendResponse;
+ }
+ }
+ } else {
+ buf = null;
+ }
+ if (buf != null && isIncompleteResponse(backendResponse, buf)) {
+ final Header h = backendResponse.getFirstHeader(HttpHeaders.CONTENT_LENGTH);
+ final ClassicHttpResponse error = new BasicClassicHttpResponse(HttpStatus.SC_BAD_GATEWAY, "Bad Gateway");
+ final String msg = String.format("Received incomplete response " +
+ "with Content-Length %s but actual body length %d",
+ h != null ? h.getValue() : null, buf.length());
+ error.setEntity(new StringEntity(msg, ContentType.TEXT_PLAIN));
+ backendResponse.close();
+ return error;
+ }
+ backendResponse.close();
+ final HttpCacheEntry entry = responseCache.createCacheEntry(target, request, backendResponse, buf, requestSent, responseReceived);
+ return responseGenerator.generateResponse(request, entry);
+ }
+
ClassicHttpResponse handleBackendResponse(
final HttpHost target,
final ClassicHttpRequest request,
@@ -789,7 +858,7 @@ public class CachingExec implements ExecChainHandler {
responseCache.flushInvalidatedCacheEntriesFor(target, request, backendResponse);
if (cacheable && !alreadyHaveNewerCacheEntry(target, request, backendResponse)) {
storeRequestIfModifiedSinceFor304Response(request, backendResponse);
- return responseCache.cacheAndReturnResponse(target, request, backendResponse, requestDate, responseDate);
+ return cacheAndReturnResponse(target, request, backendResponse, requestDate, responseDate);
}
if (!cacheable) {
try {
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java
index cf0252e..8f5babf 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java
@@ -147,7 +147,7 @@ public class CachingHttpClientBuilder extends HttpClientBuilder {
final CacheKeyGenerator uriExtractor = new CacheKeyGenerator();
final HttpCache httpCache = new BasicHttpCache(
resourceFactoryCopy,
- storageCopy, config,
+ storageCopy,
uriExtractor,
this.httpCacheInvalidator != null ? this.httpCacheInvalidator : new CacheInvalidator(uriExtractor, storageCopy));
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/HttpCache.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/HttpCache.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/HttpCache.java
index d2cf58e..3f03604 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/HttpCache.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/HttpCache.java
@@ -31,10 +31,10 @@ import java.util.Date;
import java.util.Map;
import org.apache.hc.client5.http.cache.HttpCacheEntry;
-import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.util.ByteArrayBuffer;
/**
* @since 4.1
@@ -94,14 +94,19 @@ interface HttpCache {
* @param host
* @param request
* @param originResponse
+ * @param content
* @param requestSent
* @param responseReceived
- * @return the {@link HttpResponse}
+ * @return new {@link HttpCacheEntry}
* @throws IOException
*/
- ClassicHttpResponse cacheAndReturnResponse(HttpHost host,
- HttpRequest request, ClassicHttpResponse originResponse,
- Date requestSent, Date responseReceived)
+ HttpCacheEntry createCacheEntry(
+ HttpHost host,
+ HttpRequest request,
+ HttpResponse originResponse,
+ ByteArrayBuffer content,
+ Date requestSent,
+ Date responseReceived)
throws IOException;
/**
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java
index fe25050..a6fce24 100644
--- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java
+++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java
@@ -52,6 +52,7 @@ import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.MessageSupport;
+import org.apache.hc.core5.util.ByteArrayBuffer;
import org.apache.hc.core5.util.LangUtils;
import org.junit.Assert;
@@ -243,6 +244,13 @@ public class HttpTestUtils {
return bytes;
}
+ public static ByteArrayBuffer getRandomBuffer(final int nbytes) {
+ final ByteArrayBuffer buf = new ByteArrayBuffer(nbytes);
+ buf.setLength(nbytes);
+ new Random().nextBytes(buf.array());
+ return buf;
+ }
+
/** Generates a response body with random content.
* @param nbytes length of the desired response body
* @return an {@link HttpEntity}
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestBasicHttpCache.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestBasicHttpCache.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestBasicHttpCache.java
index 6b4d473..e5b9b57 100644
--- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestBasicHttpCache.java
+++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestBasicHttpCache.java
@@ -31,18 +31,13 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
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.ByteArrayOutputStream;
-import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry;
-import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.client5.http.classic.methods.HttpDelete;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpHead;
@@ -50,16 +45,14 @@ import org.apache.hc.client5.http.classic.methods.HttpOptions;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpTrace;
import org.apache.hc.client5.http.utils.DateUtils;
-import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus;
-import org.apache.hc.core5.http.io.entity.BasicHttpEntity;
-import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
-import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHeader;
+import org.apache.hc.core5.http.message.BasicHttpResponse;
+import org.apache.hc.core5.util.ByteArrayBuffer;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -72,7 +65,7 @@ public class TestBasicHttpCache {
@Before
public void setUp() throws Exception {
backing = new SimpleHttpCacheStorage();
- impl = new BasicHttpCache(new HeapResourceFactory(), backing, CacheConfig.DEFAULT);
+ impl = new BasicHttpCache(new HeapResourceFactory(), backing);
}
@Test
@@ -136,7 +129,7 @@ public class TestBasicHttpCache {
throws Exception {
final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpPost("/foo");
- final ClassicHttpResponse resp = HttpTestUtils.make200Response();
+ final HttpResponse resp = HttpTestUtils.make200Response();
resp.setHeader("Content-Location", "/bar");
resp.setHeader(HeaderConstants.ETAG, "\"etag\"");
final String key = (new CacheKeyGenerator()).generateKey(host, new HttpGet("/bar"));
@@ -158,7 +151,7 @@ public class TestBasicHttpCache {
throws Exception {
final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpGet("/foo");
- final ClassicHttpResponse resp = HttpTestUtils.make200Response();
+ final HttpResponse resp = HttpTestUtils.make200Response();
resp.setHeader("Content-Location", "/bar");
final String key = (new CacheKeyGenerator()).generateKey(host, new HttpGet("/bar"));
@@ -189,127 +182,6 @@ public class TestBasicHttpCache {
}
@Test
- public void testRecognizesComplete200Response()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- final byte[] bytes = HttpTestUtils.getRandomBytes(128);
- resp.setEntity(new ByteArrayEntity(bytes));
- resp.setHeader("Content-Length","128");
- final Resource resource = new HeapResource(bytes);
-
- assertFalse(impl.isIncompleteResponse(resp, resource));
- }
-
- @Test
- public void testRecognizesComplete206Response()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
- final byte[] bytes = HttpTestUtils.getRandomBytes(128);
- final Resource resource = new HeapResource(bytes);
- resp.setEntity(new ByteArrayEntity(bytes));
- resp.setHeader("Content-Length","128");
- resp.setHeader("Content-Range","bytes 0-127/255");
-
- assertFalse(impl.isIncompleteResponse(resp, resource));
- }
-
- @Test
- public void testRecognizesIncomplete200Response()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- final byte[] bytes = HttpTestUtils.getRandomBytes(128);
- final Resource resource = new HeapResource(bytes);
- resp.setEntity(new ByteArrayEntity(bytes));
- resp.setHeader("Content-Length","256");
-
- assertTrue(impl.isIncompleteResponse(resp, resource));
- }
-
- @Test
- public void testIgnoresIncompleteNon200Or206Responses()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_FORBIDDEN, "Forbidden");
- final byte[] bytes = HttpTestUtils.getRandomBytes(128);
- final Resource resource = new HeapResource(bytes);
- resp.setEntity(new ByteArrayEntity(bytes));
- resp.setHeader("Content-Length","256");
-
- assertFalse(impl.isIncompleteResponse(resp, resource));
- }
-
- @Test
- public void testResponsesWithoutExplicitContentLengthAreComplete()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- final byte[] bytes = HttpTestUtils.getRandomBytes(128);
- final Resource resource = new HeapResource(bytes);
- resp.setEntity(new ByteArrayEntity(bytes));
-
- assertFalse(impl.isIncompleteResponse(resp, resource));
- }
-
- @Test
- public void testResponsesWithUnparseableContentLengthHeaderAreComplete()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- final byte[] bytes = HttpTestUtils.getRandomBytes(128);
- final Resource resource = new HeapResource(bytes);
- resp.setHeader("Content-Length","foo");
- resp.setEntity(new ByteArrayEntity(bytes));
-
- assertFalse(impl.isIncompleteResponse(resp, resource));
- }
-
- @Test
- public void testNullResourcesAreComplete()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- resp.setHeader("Content-Length","256");
-
- assertFalse(impl.isIncompleteResponse(resp, null));
- }
-
- @Test
- public void testIncompleteResponseErrorProvidesPlainTextErrorMessage()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- final byte[] bytes = HttpTestUtils.getRandomBytes(128);
- final Resource resource = new HeapResource(bytes);
- resp.setEntity(new ByteArrayEntity(bytes));
- resp.setHeader("Content-Length","256");
-
- final ClassicHttpResponse result = impl.generateIncompleteResponseError(resp, resource);
- final Header ctype = result.getFirstHeader("Content-Type");
- assertEquals("text/plain;charset=UTF-8", ctype.getValue());
- }
-
- @Test
- public void testIncompleteResponseErrorProvidesNonEmptyErrorMessage()
- throws Exception {
- final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- final byte[] bytes = HttpTestUtils.getRandomBytes(128);
- final Resource resource = new HeapResource(bytes);
- resp.setEntity(new ByteArrayEntity(bytes));
- resp.setHeader("Content-Length","256");
-
- final ClassicHttpResponse result = impl.generateIncompleteResponseError(resp, resource);
- final int clen = Integer.parseInt(result.getFirstHeader("Content-Length").getValue());
- assertTrue(clen > 0);
- final HttpEntity body = result.getEntity();
- if (body.getContentLength() < 0) {
- final InputStream is = body.getContent();
- int bytes_read = 0;
- while((is.read()) != -1) {
- bytes_read++;
- }
- is.close();
- assertEquals(clen, bytes_read);
- } else {
- assertTrue(body.getContentLength() == clen);
- }
- }
-
- @Test
public void testCacheUpdateAddsVariantURIToParentEntry() throws Exception {
final String parentCacheKey = "parentCacheKey";
final String variantCacheKey = "variantCacheKey";
@@ -341,50 +213,6 @@ public class TestBasicHttpCache {
}
@Test
- public void testTooLargeResponsesAreNotCached() throws Exception {
- final HttpHost host = new HttpHost("foo.example.com");
- final HttpRequest request = new HttpGet("http://foo.example.com/bar");
-
- final Date now = new Date();
- final Date requestSent = new Date(now.getTime() - 3 * 1000L);
- final Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
- final Date responseReceived = new Date(now.getTime() - 1 * 1000L);
-
- final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES + 1));
- originResponse.setHeader("Cache-Control","public, max-age=3600");
- originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
- originResponse.setHeader("ETag", "\"etag\"");
-
- final ClassicHttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
- assertEquals(0, backing.map.size());
- assertSame(originResponse, result);
- }
-
-
- @Test
- public void testSmallEnoughResponsesAreCached() throws Exception {
- final HttpHost host = new HttpHost("foo.example.com");
- final HttpRequest request = new HttpGet("http://foo.example.com/bar");
-
- final Date now = new Date();
- final Date requestSent = new Date(now.getTime() - 3 * 1000L);
- final Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
- final Date responseReceived = new Date(now.getTime() - 1 * 1000L);
-
- final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES - 1));
- originResponse.setHeader("Cache-Control","public, max-age=3600");
- originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
- originResponse.setHeader("ETag", "\"etag\"");
-
- final ClassicHttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
- assertEquals(1, backing.map.size());
- assertTrue(backing.map.containsKey((new CacheKeyGenerator()).generateKey(host, request)));
- assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result));
- }
-
- @Test
public void testGetCacheEntryReturnsNullOnCacheMiss() throws Exception {
final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest request = new HttpGet("http://foo.example.com/bar");
@@ -410,20 +238,21 @@ public class TestBasicHttpCache {
@Test
public void testGetCacheEntryReturnsNullIfNoVariantInCache() throws Exception {
final HttpHost host = new HttpHost("foo.example.com");
- final HttpRequest request = new HttpGet("http://foo.example.com/bar");
final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
origRequest.setHeader("Accept-Encoding","gzip");
- final ClassicHttpResponse origResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- origResponse.setEntity(HttpTestUtils.makeBody(128));
+ final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
+ final HttpResponse origResponse = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
origResponse.setHeader("Date", DateUtils.formatDate(new Date()));
origResponse.setHeader("Cache-Control", "max-age=3600, public");
origResponse.setHeader("ETag", "\"etag\"");
origResponse.setHeader("Vary", "Accept-Encoding");
origResponse.setHeader("Content-Encoding","gzip");
- impl.cacheAndReturnResponse(host, origRequest, origResponse, new Date(), new Date());
+ impl.createCacheEntry(host, origRequest, origResponse, buf, new Date(), new Date());
+
+ final HttpRequest request = new HttpGet("http://foo.example.com/bar");
final HttpCacheEntry result = impl.getCacheEntry(host, request);
assertNull(result);
}
@@ -431,21 +260,22 @@ public class TestBasicHttpCache {
@Test
public void testGetCacheEntryReturnsVariantIfPresentInCache() throws Exception {
final HttpHost host = new HttpHost("foo.example.com");
- final HttpRequest request = new HttpGet("http://foo.example.com/bar");
- request.setHeader("Accept-Encoding","gzip");
final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
origRequest.setHeader("Accept-Encoding","gzip");
- final ClassicHttpResponse origResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- origResponse.setEntity(HttpTestUtils.makeBody(128));
+ final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
+ final HttpResponse origResponse = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
origResponse.setHeader("Date", DateUtils.formatDate(new Date()));
origResponse.setHeader("Cache-Control", "max-age=3600, public");
origResponse.setHeader("ETag", "\"etag\"");
origResponse.setHeader("Vary", "Accept-Encoding");
origResponse.setHeader("Content-Encoding","gzip");
- impl.cacheAndReturnResponse(host, origRequest, origResponse, new Date(), new Date());
+ impl.createCacheEntry(host, origRequest, origResponse, buf, new Date(), new Date());
+
+ final HttpRequest request = new HttpGet("http://foo.example.com/bar");
+ request.setHeader("Accept-Encoding","gzip");
final HttpCacheEntry result = impl.getCacheEntry(host, request);
assertNotNull(result);
}
@@ -467,7 +297,7 @@ public class TestBasicHttpCache {
final HttpRequest req1 = new HttpGet("http://foo.example.com/bar");
req1.setHeader("Accept-Encoding", "gzip");
- final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
+ final HttpResponse resp1 = HttpTestUtils.make200Response();
resp1.setHeader("Date", DateUtils.formatDate(new Date()));
resp1.setHeader("Cache-Control", "max-age=3600, public");
resp1.setHeader("ETag", "\"etag1\"");
@@ -478,7 +308,7 @@ public class TestBasicHttpCache {
final HttpRequest req2 = new HttpGet("http://foo.example.com/bar");
req2.setHeader("Accept-Encoding", "identity");
- final ClassicHttpResponse resp2 = HttpTestUtils.make200Response();
+ final HttpResponse resp2 = HttpTestUtils.make200Response();
resp2.setHeader("Date", DateUtils.formatDate(new Date()));
resp2.setHeader("Cache-Control", "max-age=3600, public");
resp2.setHeader("ETag", "\"etag2\"");
@@ -486,8 +316,8 @@ public class TestBasicHttpCache {
resp2.setHeader("Content-Encoding","gzip");
resp2.setHeader("Vary", "Accept-Encoding");
- impl.cacheAndReturnResponse(host, req1, resp1, new Date(), new Date());
- impl.cacheAndReturnResponse(host, req2, resp2, new Date(), new Date());
+ impl.createCacheEntry(host, req1, resp1, null, new Date(), new Date());
+ impl.createCacheEntry(host, req2, resp2, null, new Date(), new Date());
final Map<String,Variant> variants = impl.getVariantCacheEntriesWithEtags(host, req1);
@@ -496,55 +326,4 @@ public class TestBasicHttpCache {
}
- @Test
- public void testOriginalResponseWithNoContentSizeHeaderIsReleased() throws Exception {
- final HttpHost host = new HttpHost("foo.example.com");
- final HttpRequest request = new HttpGet("http://foo.example.com/bar");
-
- final Date now = new Date();
- final Date requestSent = new Date(now.getTime() - 3 * 1000L);
- final Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
- final Date responseReceived = new Date(now.getTime() - 1 * 1000L);
-
- final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- final BasicHttpEntity entity = new BasicHttpEntity();
- final ConsumableInputStream inputStream = new ConsumableInputStream(new ByteArrayInputStream(HttpTestUtils.getRandomBytes(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES - 1)));
- entity.setContent(inputStream);
- originResponse.setEntity(entity);
- originResponse.setHeader("Cache-Control","public, max-age=3600");
- originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
- originResponse.setHeader("ETag", "\"etag\"");
-
- final ClassicHttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
- IOUtils.consume(result.getEntity());
- assertTrue(inputStream.wasClosed());
- }
-
- @Test
- public void testEntryUpdate() throws Exception {
-
- final HeapResourceFactory rf = new HeapResourceFactory();
-
- impl = new BasicHttpCache(rf, backing, CacheConfig.DEFAULT);
-
- final HttpHost host = new HttpHost("foo.example.com");
-
- final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
- origRequest.setHeader("Accept-Encoding","gzip");
-
- final ClassicHttpResponse origResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
- origResponse.setEntity(HttpTestUtils.makeBody(128));
- origResponse.setHeader("Date", DateUtils.formatDate(new Date()));
- origResponse.setHeader("Cache-Control", "max-age=3600, public");
- origResponse.setHeader("ETag", "\"etag\"");
- origResponse.setHeader("Vary", "Accept-Encoding");
- origResponse.setHeader("Content-Encoding","gzip");
-
- final ClassicHttpResponse response = impl.cacheAndReturnResponse(
- host, origRequest, origResponse, new Date(), new Date());
- final HttpEntity entity = response.getEntity();
- Assert.assertNotNull(entity);
- IOUtils.copyAndClose(entity.getContent(), new ByteArrayOutputStream());
- }
-
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java
index 366dea0..daeb468 100644
--- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java
+++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java
@@ -290,7 +290,7 @@ public class TestCachingExec extends TestCachingExecChain {
eq(responseDate)))
.andReturn(updatedEntry);
expect(mockSuitabilityChecker.isConditional(request)).andReturn(false);
- responseIsGeneratedFromCache();
+ responseIsGeneratedFromCache(HttpTestUtils.make200Response());
replayMocks();
impl.revalidateCacheEntry(host, request, scope, mockExecChain, entry);
@@ -396,14 +396,11 @@ public class TestCachingExec extends TestCachingExecChain {
cacheEntrySuitable(true);
cacheEntryValidatable(true);
- expect(mockResponseGenerator.generateResponse(isA(HttpRequest.class), isA(HttpCacheEntry.class)))
- .andReturn(mockBackendResponse);
+ responseIsGeneratedFromCache(HttpTestUtils.make200Response());
replayMocks();
- final HttpResponse result = impl.execute(request, scope, mockExecChain);
+ impl.execute(request, scope, mockExecChain);
verifyMocks();
-
- Assert.assertSame(mockBackendResponse, result);
}
private IExpectationSetters<ClassicHttpResponse> implExpectsAnyRequestAndReturn(
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java
index bd9f0a8..8a3dfce 100644
--- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java
+++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java
@@ -31,10 +31,12 @@ import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.same;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -54,7 +56,6 @@ import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheStorage;
import org.apache.hc.client5.http.classic.ExecChain;
-import org.apache.hc.client5.http.classic.ExecChainHandler;
import org.apache.hc.client5.http.classic.ExecRuntime;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpOptions;
@@ -77,6 +78,7 @@ import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.net.URIAuthority;
+import org.apache.hc.core5.util.ByteArrayBuffer;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IExpectationSetters;
@@ -89,7 +91,7 @@ import junit.framework.AssertionFailedError;
@SuppressWarnings("boxing") // test code
public abstract class TestCachingExecChain {
- private ExecChainHandler impl;
+ private CachingExec impl;
protected CacheValidityPolicy mockValidityPolicy;
protected CacheableRequestPolicy mockRequestPolicy;
@@ -103,7 +105,6 @@ public abstract class TestCachingExecChain {
protected CachedHttpResponseGenerator mockResponseGenerator;
private HttpClientResponseHandler<Object> mockHandler;
private ClassicHttpRequest mockUriRequest;
- private ClassicHttpResponse mockCachedResponse;
protected ConditionalRequestBuilder mockConditionalRequestBuilder;
private HttpRequest mockConditionalRequest;
protected ResponseProtocolCompliance mockResponseProtocolCompliance;
@@ -131,7 +132,6 @@ public abstract class TestCachingExecChain {
mockUriRequest = createNiceMock(ClassicHttpRequest.class);
mockCacheEntry = createNiceMock(HttpCacheEntry.class);
mockResponseGenerator = createNiceMock(CachedHttpResponseGenerator.class);
- mockCachedResponse = createNiceMock(ClassicHttpResponse.class);
mockConditionalRequestBuilder = createNiceMock(ConditionalRequestBuilder.class);
mockConditionalRequest = createNiceMock(HttpRequest.class);
mockResponseProtocolCompliance = createNiceMock(ResponseProtocolCompliance.class);
@@ -151,7 +151,7 @@ public abstract class TestCachingExecChain {
mockRequestProtocolCompliance, config, asyncValidator);
}
- public abstract ExecChainHandler createCachingExecChain(HttpCache responseCache, CacheValidityPolicy validityPolicy,
+ public abstract CachingExec createCachingExecChain(HttpCache responseCache, CacheValidityPolicy validityPolicy,
ResponseCachingPolicy responseCachingPolicy, CachedHttpResponseGenerator responseGenerator,
CacheableRequestPolicy cacheableRequestPolicy,
CachedResponseSuitabilityChecker suitabilityChecker,
@@ -159,7 +159,7 @@ public abstract class TestCachingExecChain {
ResponseProtocolCompliance responseCompliance, RequestProtocolCompliance requestCompliance,
CacheConfig config, AsynchronousValidator asynchRevalidator);
- public abstract ExecChainHandler createCachingExecChain(HttpCache cache, CacheConfig config);
+ public abstract CachingExec createCachingExecChain(HttpCache cache, CacheConfig config);
protected ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException {
return impl.execute(ClassicRequestCopier.INSTANCE.copy(request), new ExecChain.Scope(
@@ -187,7 +187,6 @@ public abstract class TestCachingExecChain {
replay(mockCache);
replay(mockHandler);
replay(mockUriRequest);
- replay(mockCachedResponse);
replay(mockConditionalRequestBuilder);
replay(mockConditionalRequest);
replay(mockResponseProtocolCompliance);
@@ -206,7 +205,6 @@ public abstract class TestCachingExecChain {
verify(mockCache);
verify(mockHandler);
verify(mockUriRequest);
- verify(mockCachedResponse);
verify(mockConditionalRequestBuilder);
verify(mockConditionalRequest);
verify(mockResponseProtocolCompliance);
@@ -314,22 +312,20 @@ public abstract class TestCachingExecChain {
requestPolicyAllowsCaching(true);
getCacheEntryReturns(mockCacheEntry);
cacheEntrySuitable(true);
- responseIsGeneratedFromCache();
+ responseIsGeneratedFromCache(HttpTestUtils.make200Response());
requestIsFatallyNonCompliant(null);
entryHasStaleness(0L);
replayMocks();
final ClassicHttpResponse result = execute(request);
verifyMocks();
-
- Assert.assertSame(mockCachedResponse, result);
}
@Test
public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Exception {
final CacheConfig configDefault = CacheConfig.DEFAULT;
impl = createCachingExecChain(new BasicHttpCache(new HeapResourceFactory(),
- mockStorage, configDefault), configDefault);
+ mockStorage), configDefault);
final ClassicHttpRequest req1 = HttpTestUtils.makeDefaultRequest();
final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
@@ -354,7 +350,7 @@ public abstract class TestCachingExecChain {
requestPolicyAllowsCaching(true);
cacheEntrySuitable(true);
getCacheEntryReturns(mockCacheEntry);
- responseIsGeneratedFromCache();
+ responseIsGeneratedFromCache(HttpTestUtils.make200Response());
entryHasStaleness(0L);
replayMocks();
@@ -1265,31 +1261,134 @@ public abstract class TestCachingExecChain {
}
@Test
- public void testTreatsCacheIOExceptionsAsCacheMiss() throws Exception {
+ public void testRecognizesComplete200Response()
+ throws Exception {
+ final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
+ final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
+ resp.setHeader("Content-Length","128");
+ assertFalse(impl.isIncompleteResponse(resp, buf));
+ }
- impl = createCachingExecChain(mockCache, CacheConfig.DEFAULT);
- final ClassicHttpResponse resp = HttpTestUtils.make200Response();
+ @Test
+ public void testRecognizesComplete206Response()
+ throws Exception {
+ final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
+ final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
+ resp.setHeader("Content-Length","128");
+ resp.setHeader("Content-Range","bytes 0-127/255");
+ assertFalse(impl.isIncompleteResponse(resp, buf));
+ }
- mockCache.flushInvalidatedCacheEntriesFor(host, request);
- expectLastCall().andThrow(new IOException()).anyTimes();
- mockCache.flushInvalidatedCacheEntriesFor(isA(HttpHost.class), isA(HttpRequest.class),
- isA(HttpResponse.class));
- expectLastCall().anyTimes();
- expect(mockCache.getCacheEntry(eq(host), isA(HttpRequest.class))).andThrow(
- new IOException()).anyTimes();
- expect(mockCache.getVariantCacheEntriesWithEtags(eq(host), isA(HttpRequest.class)))
- .andThrow(new IOException()).anyTimes();
- expect(
- mockCache.cacheAndReturnResponse(eq(host), isA(HttpRequest.class),
- isA(ClassicHttpResponse.class), isA(Date.class), isA(Date.class)))
- .andReturn(resp).anyTimes();
- expect(
- mockExecChain.proceed(isA(ClassicHttpRequest.class), isA(ExecChain.Scope.class))).andReturn(resp);
+ @Test
+ public void testRecognizesIncomplete200Response()
+ throws Exception {
+ final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
+ final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
+ resp.setHeader("Content-Length","256");
+
+ assertTrue(impl.isIncompleteResponse(resp, buf));
+ }
+
+ @Test
+ public void testIgnoresIncompleteNon200Or206Responses()
+ throws Exception {
+ final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_FORBIDDEN, "Forbidden");
+ final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
+ resp.setHeader("Content-Length","256");
+
+ assertFalse(impl.isIncompleteResponse(resp, buf));
+ }
+
+ @Test
+ public void testResponsesWithoutExplicitContentLengthAreComplete()
+ throws Exception {
+ final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
+ final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
+
+ assertFalse(impl.isIncompleteResponse(resp, buf));
+ }
+
+ @Test
+ public void testResponsesWithUnparseableContentLengthHeaderAreComplete()
+ throws Exception {
+ final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
+ final ByteArrayBuffer buf = HttpTestUtils.getRandomBuffer(128);
+ resp.setHeader("Content-Length","foo");
+ assertFalse(impl.isIncompleteResponse(resp, buf));
+ }
+
+ @Test
+ public void testNullResourcesAreComplete()
+ throws Exception {
+ final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
+ resp.setHeader("Content-Length","256");
+
+ assertFalse(impl.isIncompleteResponse(resp, null));
+ }
+
+ @Test
+ public void testTooLargeResponsesAreNotCached() throws Exception {
+ mockCache = EasyMock.createStrictMock(HttpCache.class);
+ impl = createCachingExecChain(mockCache, mockValidityPolicy,
+ mockResponsePolicy, mockResponseGenerator, mockRequestPolicy, mockSuitabilityChecker,
+ mockConditionalRequestBuilder, mockResponseProtocolCompliance,
+ mockRequestProtocolCompliance, config, asyncValidator);
+
+ final HttpHost host = new HttpHost("foo.example.com");
+ final HttpRequest request = new HttpGet("http://foo.example.com/bar");
+
+ final Date now = new Date();
+ final Date requestSent = new Date(now.getTime() - 3 * 1000L);
+ final Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
+ final Date responseReceived = new Date(now.getTime() - 1 * 1000L);
+
+ final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
+ originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES + 1));
+ originResponse.setHeader("Cache-Control","public, max-age=3600");
+ originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
+ originResponse.setHeader("ETag", "\"etag\"");
replayMocks();
- final ClassicHttpResponse result = execute(request);
+
+ impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
+
+ verifyMocks();
+ }
+
+ @Test
+ public void testSmallEnoughResponsesAreCached() throws Exception {
+ final HttpHost host = new HttpHost("foo.example.com");
+ final HttpRequest request = new HttpGet("http://foo.example.com/bar");
+
+ final Date now = new Date();
+ final Date requestSent = new Date(now.getTime() - 3 * 1000L);
+ final Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
+ final Date responseReceived = new Date(now.getTime() - 1 * 1000L);
+
+ final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
+ originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES - 1));
+ originResponse.setHeader("Cache-Control","public, max-age=3600");
+ originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
+ originResponse.setHeader("ETag", "\"etag\"");
+
+ final HttpCacheEntry httpCacheEntry = HttpTestUtils.makeCacheEntry();
+ final ClassicHttpResponse response = HttpTestUtils.make200Response();
+
+ EasyMock.expect(mockCache.createCacheEntry(
+ eq(host),
+ same(request),
+ same(originResponse),
+ isA(ByteArrayBuffer.class),
+ eq(requestSent),
+ eq(responseReceived))).andReturn(httpCacheEntry).once();
+ EasyMock.expect(mockResponseGenerator.generateResponse(
+ same(request),
+ same(httpCacheEntry))).andReturn(response).once();
+ replayMocks();
+
+ impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
+
verifyMocks();
- Assert.assertSame(resp, result);
}
@Test
@@ -1332,14 +1431,12 @@ public abstract class TestCachingExecChain {
requestPolicyAllowsCaching(true);
getCacheEntryReturns(entry);
cacheEntrySuitable(true);
- responseIsGeneratedFromCache();
+ responseIsGeneratedFromCache(HttpTestUtils.make200Response());
entryHasStaleness(0);
replayMocks();
final ClassicHttpResponse resp = execute(request);
verifyMocks();
-
- Assert.assertSame(mockCachedResponse, resp);
}
@Test
@@ -1669,10 +1766,11 @@ public abstract class TestCachingExecChain {
.andReturn(staleness);
}
- protected void responseIsGeneratedFromCache() {
+ protected void responseIsGeneratedFromCache(final ClassicHttpResponse cachedResponse) throws IOException {
expect(
- mockResponseGenerator.generateResponse((ClassicHttpRequest) anyObject(), (HttpCacheEntry) anyObject()))
- .andReturn(mockCachedResponse);
+ mockResponseGenerator.generateResponse(
+ (ClassicHttpRequest) anyObject(),
+ (HttpCacheEntry) anyObject())).andReturn(cachedResponse);
}
protected void doesNotFlushCache() throws IOException {
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestHttpCacheJiraNumber1147.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestHttpCacheJiraNumber1147.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestHttpCacheJiraNumber1147.java
index 72aa987..8754afe 100644
--- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestHttpCacheJiraNumber1147.java
+++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestHttpCacheJiraNumber1147.java
@@ -113,7 +113,7 @@ public class TestHttpCacheJiraNumber1147 {
isA(ClassicHttpRequest.class),
isA(ExecChain.Scope.class))).thenReturn(response);
- final BasicHttpCache cache = new BasicHttpCache(resourceFactory, httpCacheStorage, cacheConfig);
+ final BasicHttpCache cache = new BasicHttpCache(resourceFactory, httpCacheStorage);
final ExecChainHandler t = createCachingExecChain(cache, cacheConfig);
final ExecChain.Scope scope = new ExecChain.Scope("teset", route, get, mockEndpoint, context);
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java
index 5729a81..6eb3436 100644
--- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java
+++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java
@@ -56,6 +56,7 @@ import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.MessageSupport;
+import org.apache.hc.core5.util.ByteArrayBuffer;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.junit.Assert;
@@ -2617,7 +2618,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
validated.setHeader("Content-Length", "128");
validated.setEntity(new ByteArrayEntity(bytes));
- final ClassicHttpResponse reconstructed = HttpTestUtils.make200Response();
+ final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry();
final Capture<ClassicHttpRequest> cap = new Capture<>();
@@ -2633,12 +2634,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
EasyMock.expect(mockCache.getCacheEntry(
EasyMock.isA(HttpHost.class),
EasyMock.isA(ClassicHttpRequest.class))).andReturn(entry).times(0, 1);
- EasyMock.expect(mockCache.cacheAndReturnResponse(
+ EasyMock.expect(mockCache.createCacheEntry(
EasyMock.isA(HttpHost.class),
EasyMock.isA(ClassicHttpRequest.class),
eqCloseableResponse(validated),
+ EasyMock.isA(ByteArrayBuffer.class),
EasyMock.isA(Date.class),
- EasyMock.isA(Date.class))).andReturn(reconstructed).times(0, 1);
+ EasyMock.isA(Date.class))).andReturn(cacheEntry).times(0, 1);
replayMocks();
final ClassicHttpResponse result = execute(request);
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/20f4290d/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java
index 7d1686d..47a98b1 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java
@@ -43,6 +43,10 @@ public final class SimpleHttpResponse extends BasicHttpResponse {
super(code);
}
+ public SimpleHttpResponse(final int code, final String reasonPhrase) {
+ super(code, reasonPhrase);
+ }
+
public static SimpleHttpResponse copy(final HttpResponse original) {
Args.notNull(original, "HTTP response");
final SimpleHttpResponse copy = new SimpleHttpResponse(original.getCode());
@@ -53,6 +57,34 @@ public final class SimpleHttpResponse extends BasicHttpResponse {
return copy;
}
+ public static SimpleHttpResponse create(final int code) {
+ return new SimpleHttpResponse(code);
+ }
+
+ public static SimpleHttpResponse create(final int code, final String content, final ContentType contentType) {
+ final SimpleHttpResponse response = new SimpleHttpResponse(code);
+ if (content != null) {
+ response.setBodyText(content, contentType);
+ }
+ return response;
+ }
+
+ public static SimpleHttpResponse create(final int code, final String content) {
+ return create(code, content, ContentType.TEXT_PLAIN);
+ }
+
+ public static SimpleHttpResponse create(final int code, final byte[] content, final ContentType contentType) {
+ final SimpleHttpResponse response = new SimpleHttpResponse(code);
+ if (content != null) {
+ response.setBodyBytes(content, contentType);
+ }
+ return response;
+ }
+
+ public static SimpleHttpResponse create(final int code, final byte[] content) {
+ return create(code, content, ContentType.TEXT_PLAIN);
+ }
+
public void setBody(final SimpleBody body) {
this.body = body;
}