Removed dependency on classic (blocking) I/O APIs from CachedHttpResponseGenerator
This commit is contained in:
parent
0226eaff6d
commit
1d66105c3a
|
@ -49,6 +49,9 @@ public enum CacheResponseStatus {
|
|||
/** The response was generated from the cache after validating the
|
||||
* entry with the origin server.
|
||||
*/
|
||||
VALIDATED
|
||||
VALIDATED,
|
||||
|
||||
/** The response came from an upstream server after a cache failure */
|
||||
FAILURE
|
||||
|
||||
}
|
||||
|
|
|
@ -1,116 +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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.hc.client5.http.impl.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.core5.annotation.Contract;
|
||||
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
||||
import org.apache.hc.core5.function.Supplier;
|
||||
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.util.Args;
|
||||
|
||||
@Contract(threading = ThreadingBehavior.IMMUTABLE)
|
||||
class CacheEntity implements HttpEntity, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3467082284120936233L;
|
||||
|
||||
private final HttpCacheEntry cacheEntry;
|
||||
|
||||
public CacheEntity(final HttpCacheEntry cacheEntry) {
|
||||
super();
|
||||
this.cacheEntry = cacheEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
final Header header = this.cacheEntry.getFirstHeader(HttpHeaders.CONTENT_TYPE);
|
||||
return header != null ? header.getValue() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentEncoding() {
|
||||
final Header header = this.cacheEntry.getFirstHeader(HttpHeaders.CONTENT_ENCODING);
|
||||
return header != null ? header.getValue() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getContentLength() {
|
||||
return this.cacheEntry.getResource().length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getContent() throws IOException {
|
||||
return this.cacheEntry.getResource().getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final OutputStream outstream) throws IOException {
|
||||
Args.notNull(outstream, "Output stream");
|
||||
try (InputStream instream = this.cacheEntry.getResource().getInputStream()) {
|
||||
IOUtils.copy(instream, outstream);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStreaming() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Supplier<List<? extends Header>> getTrailers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getTrailerNames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
}
|
||||
|
||||
}
|
|
@ -26,22 +26,23 @@
|
|||
*/
|
||||
package org.apache.hc.client5.http.impl.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.cache.Resource;
|
||||
import org.apache.hc.client5.http.utils.DateUtils;
|
||||
import org.apache.hc.core5.annotation.Contract;
|
||||
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
||||
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.HttpEntity;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
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.HttpVersion;
|
||||
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
|
||||
import org.apache.hc.core5.http.message.BasicHeader;
|
||||
|
||||
/**
|
||||
|
@ -59,28 +60,27 @@ class CachedHttpResponseGenerator {
|
|||
this.validityStrategy = validityStrategy;
|
||||
}
|
||||
|
||||
CachedHttpResponseGenerator() {
|
||||
this(new CacheValidityPolicy());
|
||||
}
|
||||
|
||||
/**
|
||||
* If I was able to use a {@link CacheEntity} to response to the {@link HttpRequest} then
|
||||
* generate an {@link HttpResponse} based on the cache entry.
|
||||
* If it is legal to use cached content in response response to the {@link HttpRequest} then
|
||||
* generate an {@link HttpResponse} based on {@link HttpCacheEntry}.
|
||||
* @param request {@link HttpRequest} to generate the response for
|
||||
* @param entry {@link CacheEntity} to transform into an {@link HttpResponse}
|
||||
* @return {@link HttpResponse} that was constructed
|
||||
* @param entry {@link HttpCacheEntry} to transform into an {@link HttpResponse}
|
||||
* @return {@link SimpleHttpResponse} constructed response
|
||||
*/
|
||||
ClassicHttpResponse generateResponse(final HttpRequest request, final HttpCacheEntry entry) {
|
||||
SimpleHttpResponse generateResponse(final HttpRequest request, final HttpCacheEntry entry) throws IOException {
|
||||
final Date now = new Date();
|
||||
final ClassicHttpResponse response = new BasicClassicHttpResponse(entry.getStatus());
|
||||
final SimpleHttpResponse response = new SimpleHttpResponse(entry.getStatus());
|
||||
response.setVersion(HttpVersion.DEFAULT);
|
||||
|
||||
response.setHeaders(entry.getAllHeaders());
|
||||
|
||||
if (responseShouldContainEntity(request, entry)) {
|
||||
final HttpEntity entity = new CacheEntity(entry);
|
||||
addMissingContentLengthHeader(response, entity);
|
||||
response.setEntity(entity);
|
||||
final Resource resource = entry.getResource();
|
||||
final Header h = entry.getFirstHeader(HttpHeaders.CONTENT_TYPE);
|
||||
final ContentType contentType = h != null ? ContentType.parse(h.getValue()) : null;
|
||||
final byte[] content = resource.get();
|
||||
addMissingContentLengthHeader(response, content);
|
||||
response.setBodyBytes(content, contentType);
|
||||
}
|
||||
|
||||
final long age = this.validityStrategy.getCurrentAgeSecs(entry, now);
|
||||
|
@ -96,12 +96,12 @@ class CachedHttpResponseGenerator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Generate a 304 - Not Modified response from a {@link CacheEntity}. This should be
|
||||
* Generate a 304 - Not Modified response from the {@link HttpCacheEntry}. This should be
|
||||
* used to respond to conditional requests, when the entry exists or has been re-validated.
|
||||
*/
|
||||
ClassicHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) {
|
||||
SimpleHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) {
|
||||
|
||||
final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified");
|
||||
final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified");
|
||||
|
||||
// The response MUST include the following headers
|
||||
// (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
|
||||
|
@ -109,7 +109,7 @@ class CachedHttpResponseGenerator {
|
|||
// - Date, unless its omission is required by section 14.8.1
|
||||
Header dateHeader = entry.getFirstHeader(HttpHeaders.DATE);
|
||||
if (dateHeader == null) {
|
||||
dateHeader = new BasicHeader(HttpHeaders.DATE, DateUtils.formatDate(new Date()));
|
||||
dateHeader = new BasicHeader(HttpHeaders.DATE, DateUtils.formatDate(new Date()));
|
||||
}
|
||||
response.addHeader(dateHeader);
|
||||
|
||||
|
@ -146,16 +146,13 @@ class CachedHttpResponseGenerator {
|
|||
return response;
|
||||
}
|
||||
|
||||
private void addMissingContentLengthHeader(final HttpResponse response, final HttpEntity entity) {
|
||||
private void addMissingContentLengthHeader(final HttpResponse response, final byte[] body) {
|
||||
if (transferEncodingIsPresent(response)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Header contentLength = response.getFirstHeader(HttpHeaders.CONTENT_LENGTH);
|
||||
final Header contentLength = response.getFirstHeader(HttpHeaders.CONTENT_LENGTH);
|
||||
if (contentLength == null) {
|
||||
contentLength = new BasicHeader(HttpHeaders.CONTENT_LENGTH, Long.toString(entity
|
||||
.getContentLength()));
|
||||
response.setHeader(contentLength);
|
||||
response.setHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(body.length));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,23 +170,23 @@ class CachedHttpResponseGenerator {
|
|||
* that a problem occured.
|
||||
*
|
||||
* @param errorCheck What type of error should I get
|
||||
* @return The {@link ClassicHttpResponse} that is the error generated
|
||||
* @return The {@link HttpResponse} that is the error generated
|
||||
*/
|
||||
public ClassicHttpResponse getErrorForRequest(final RequestProtocolError errorCheck) {
|
||||
public SimpleHttpResponse getErrorForRequest(final RequestProtocolError errorCheck) {
|
||||
switch (errorCheck) {
|
||||
case BODY_BUT_NO_LENGTH_ERROR:
|
||||
return new BasicClassicHttpResponse(HttpStatus.SC_LENGTH_REQUIRED, "");
|
||||
return SimpleHttpResponse.create(HttpStatus.SC_LENGTH_REQUIRED);
|
||||
|
||||
case WEAK_ETAG_AND_RANGE_ERROR:
|
||||
return new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST,
|
||||
"Weak eTag not compatible with byte range");
|
||||
return SimpleHttpResponse.create(HttpStatus.SC_BAD_REQUEST,
|
||||
"Weak eTag not compatible with byte range", ContentType.DEFAULT_TEXT);
|
||||
|
||||
case WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR:
|
||||
return new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST,
|
||||
return SimpleHttpResponse.create(HttpStatus.SC_BAD_REQUEST,
|
||||
"Weak eTag not compatible with PUT or DELETE requests");
|
||||
|
||||
case NO_CACHE_DIRECTIVE_WITH_FIELD_NAME:
|
||||
return new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST,
|
||||
return SimpleHttpResponse.create(HttpStatus.SC_BAD_REQUEST,
|
||||
"No-Cache directive MUST NOT include a field name");
|
||||
|
||||
default:
|
||||
|
|
|
@ -36,12 +36,15 @@ import java.util.Map;
|
|||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.apache.hc.client5.http.HttpRoute;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleBody;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.client5.http.cache.CacheResponseStatus;
|
||||
import org.apache.hc.client5.http.cache.HeaderConstants;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheContext;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheStorage;
|
||||
import org.apache.hc.client5.http.cache.ResourceFactory;
|
||||
import org.apache.hc.client5.http.cache.ResourceIOException;
|
||||
import org.apache.hc.client5.http.classic.ExecChain;
|
||||
import org.apache.hc.client5.http.classic.ExecChainHandler;
|
||||
import org.apache.hc.client5.http.impl.classic.ClassicRequestCopier;
|
||||
|
@ -64,6 +67,7 @@ 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.ByteArrayEntity;
|
||||
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;
|
||||
|
@ -220,6 +224,26 @@ public class CachingExec implements ExecChainHandler {
|
|||
return cacheUpdates.get();
|
||||
}
|
||||
|
||||
private static ClassicHttpResponse convert(final SimpleHttpResponse cacheResponse) {
|
||||
if (cacheResponse == null) {
|
||||
return null;
|
||||
}
|
||||
final ClassicHttpResponse response = new BasicClassicHttpResponse(cacheResponse.getCode(), cacheResponse.getReasonPhrase());
|
||||
for (final Iterator<Header> it = cacheResponse.headerIterator(); it.hasNext(); ) {
|
||||
response.addHeader(it.next());
|
||||
}
|
||||
response.setVersion(cacheResponse.getVersion() != null ? cacheResponse.getVersion() : HttpVersion.DEFAULT);
|
||||
final SimpleBody body = cacheResponse.getBody();
|
||||
if (body != null) {
|
||||
if (body.isText()) {
|
||||
response.setEntity(new StringEntity(body.getBodyText(), body.getContentType()));
|
||||
} else {
|
||||
response.setEntity(new ByteArrayEntity(body.getBodyBytes(), body.getContentType()));
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassicHttpResponse execute(
|
||||
final ClassicHttpRequest request,
|
||||
|
@ -263,7 +287,12 @@ public class CachingExec implements ExecChainHandler {
|
|||
log.debug("Cache miss");
|
||||
return handleCacheMiss(target, request, scope, chain);
|
||||
} else {
|
||||
return handleCacheHit(target, request, scope, chain, entry);
|
||||
try {
|
||||
return handleCacheHit(target, request, scope, chain, entry);
|
||||
} catch (final ResourceIOException ex) {
|
||||
log.debug("Cache resource I/O error");
|
||||
return handleCacheFailure(target, request, scope, chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,6 +370,20 @@ public class CachingExec implements ExecChainHandler {
|
|||
return callBackend(target, request, scope, chain);
|
||||
}
|
||||
|
||||
private ClassicHttpResponse handleCacheFailure(
|
||||
final HttpHost target,
|
||||
final ClassicHttpRequest request,
|
||||
final ExecChain.Scope scope,
|
||||
final ExecChain chain) throws IOException, HttpException {
|
||||
recordCacheFailure(target, request);
|
||||
|
||||
if (!mayCallBackend(request)) {
|
||||
return new BasicClassicHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
|
||||
}
|
||||
|
||||
setResponseStatus(scope.clientContext, CacheResponseStatus.FAILURE);
|
||||
return chain.proceed(request, scope);
|
||||
}
|
||||
private HttpCacheEntry satisfyFromCache(
|
||||
final HttpHost target, final ClassicHttpRequest request) {
|
||||
HttpCacheEntry entry = null;
|
||||
|
@ -355,14 +398,13 @@ public class CachingExec implements ExecChainHandler {
|
|||
private ClassicHttpResponse getFatallyNoncompliantResponse(
|
||||
final ClassicHttpRequest request,
|
||||
final HttpContext context) {
|
||||
ClassicHttpResponse fatalErrorResponse = null;
|
||||
final List<RequestProtocolError> fatalError = requestCompliance.requestIsFatallyNonCompliant(request);
|
||||
|
||||
for (final RequestProtocolError error : fatalError) {
|
||||
if (fatalError != null && !fatalError.isEmpty()) {
|
||||
setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
|
||||
fatalErrorResponse = responseGenerator.getErrorForRequest(error);
|
||||
return convert(responseGenerator.getErrorForRequest(fatalError.get(0)));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return fatalErrorResponse;
|
||||
}
|
||||
|
||||
private Map<String, Variant> getExistingCacheVariants(
|
||||
|
@ -391,6 +433,13 @@ public class CachingExec implements ExecChainHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private void recordCacheFailure(final HttpHost target, final ClassicHttpRequest request) {
|
||||
cacheMisses.getAndIncrement();
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Cache failure [host: " + target + "; uri: " + request.getRequestUri() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private void recordCacheUpdate(final HttpContext context) {
|
||||
cacheUpdates.getAndIncrement();
|
||||
setResponseStatus(context, CacheResponseStatus.VALIDATED);
|
||||
|
@ -410,13 +459,13 @@ public class CachingExec implements ExecChainHandler {
|
|||
final ClassicHttpRequest request,
|
||||
final HttpContext context,
|
||||
final HttpCacheEntry entry,
|
||||
final Date now) {
|
||||
final Date now) throws IOException {
|
||||
final ClassicHttpResponse cachedResponse;
|
||||
if (request.containsHeader(HeaderConstants.IF_NONE_MATCH)
|
||||
|| request.containsHeader(HeaderConstants.IF_MODIFIED_SINCE)) {
|
||||
cachedResponse = responseGenerator.generateNotModifiedResponse(entry);
|
||||
cachedResponse = convert(responseGenerator.generateNotModifiedResponse(entry));
|
||||
} else {
|
||||
cachedResponse = responseGenerator.generateResponse(request, entry);
|
||||
cachedResponse = convert(responseGenerator.generateResponse(request, entry));
|
||||
}
|
||||
setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
|
||||
if (validityPolicy.getStalenessSecs(entry, now) > 0L) {
|
||||
|
@ -446,8 +495,8 @@ public class CachingExec implements ExecChainHandler {
|
|||
private ClassicHttpResponse unvalidatedCacheHit(
|
||||
final ClassicHttpRequest request,
|
||||
final HttpContext context,
|
||||
final HttpCacheEntry entry) {
|
||||
final ClassicHttpResponse cachedResponse = responseGenerator.generateResponse(request, entry);
|
||||
final HttpCacheEntry entry) throws IOException {
|
||||
final ClassicHttpResponse cachedResponse = convert(responseGenerator.generateResponse(request, entry));
|
||||
setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
|
||||
cachedResponse.addHeader(HeaderConstants.WARNING, "111 localhost \"Revalidation failed\"");
|
||||
return cachedResponse;
|
||||
|
@ -657,13 +706,13 @@ public class CachingExec implements ExecChainHandler {
|
|||
backendResponse, matchingVariant, matchedEntry);
|
||||
backendResponse.close();
|
||||
|
||||
final ClassicHttpResponse resp = responseGenerator.generateResponse(request, responseEntry);
|
||||
final SimpleHttpResponse resp = responseGenerator.generateResponse(request, responseEntry);
|
||||
tryToUpdateVariantMap(target, request, matchingVariant);
|
||||
|
||||
if (shouldSendNotModifiedResponse(request, responseEntry)) {
|
||||
return responseGenerator.generateNotModifiedResponse(responseEntry);
|
||||
return convert(responseGenerator.generateNotModifiedResponse(responseEntry));
|
||||
}
|
||||
return resp;
|
||||
return convert(resp);
|
||||
} catch (final IOException | RuntimeException ex) {
|
||||
backendResponse.close();
|
||||
throw ex;
|
||||
|
@ -754,18 +803,18 @@ public class CachingExec implements ExecChainHandler {
|
|||
backendResponse, requestDate, responseDate);
|
||||
if (suitabilityChecker.isConditional(request)
|
||||
&& suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) {
|
||||
return responseGenerator.generateNotModifiedResponse(updatedEntry);
|
||||
return convert(responseGenerator.generateNotModifiedResponse(updatedEntry));
|
||||
}
|
||||
return responseGenerator.generateResponse(request, updatedEntry);
|
||||
return convert(responseGenerator.generateResponse(request, updatedEntry));
|
||||
}
|
||||
|
||||
if (staleIfErrorAppliesTo(statusCode)
|
||||
&& !staleResponseNotAllowed(request, cacheEntry, getCurrentDate())
|
||||
&& validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
|
||||
try {
|
||||
final ClassicHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry);
|
||||
final SimpleHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry);
|
||||
cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
|
||||
return cachedResponse;
|
||||
return convert(cachedResponse);
|
||||
} finally {
|
||||
backendResponse.close();
|
||||
}
|
||||
|
@ -841,7 +890,7 @@ public class CachingExec implements ExecChainHandler {
|
|||
}
|
||||
backendResponse.close();
|
||||
final HttpCacheEntry entry = responseCache.createCacheEntry(target, request, backendResponse, buf, requestSent, responseReceived);
|
||||
return responseGenerator.generateResponse(request, entry);
|
||||
return convert(responseGenerator.generateResponse(request, entry));
|
||||
}
|
||||
|
||||
ClassicHttpResponse handleBackendResponse(
|
||||
|
|
|
@ -35,9 +35,9 @@ import static org.mockito.Mockito.when;
|
|||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.core5.http.ClassicHttpRequest;
|
||||
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.message.BasicHeader;
|
||||
import org.junit.Assert;
|
||||
|
@ -61,11 +61,11 @@ public class TestCachedHttpResponseGenerator {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testResponseHasContentLength() {
|
||||
public void testResponseHasContentLength() throws Exception {
|
||||
final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
|
||||
final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(buf);
|
||||
|
||||
final ClassicHttpResponse response = impl.generateResponse(request, entry1);
|
||||
final SimpleHttpResponse response = impl.generateResponse(request, entry1);
|
||||
|
||||
final Header length = response.getFirstHeader("Content-Length");
|
||||
Assert.assertNotNull("Content-Length Header is missing", length);
|
||||
|
@ -75,13 +75,13 @@ public class TestCachedHttpResponseGenerator {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testContentLengthIsNotAddedWhenTransferEncodingIsPresent() {
|
||||
public void testContentLengthIsNotAddedWhenTransferEncodingIsPresent() throws Exception {
|
||||
|
||||
final Header[] hdrs = new Header[] { new BasicHeader("Transfer-Encoding", "chunked") };
|
||||
final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
|
||||
final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(hdrs, buf);
|
||||
|
||||
final ClassicHttpResponse response = impl.generateResponse(request, entry1);
|
||||
final SimpleHttpResponse response = impl.generateResponse(request, entry1);
|
||||
|
||||
final Header length = response.getFirstHeader("Content-Length");
|
||||
|
||||
|
@ -89,8 +89,8 @@ public class TestCachedHttpResponseGenerator {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testResponseMatchesCacheEntry() {
|
||||
final ClassicHttpResponse response = impl.generateResponse(request, entry);
|
||||
public void testResponseMatchesCacheEntry() throws Exception {
|
||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||
|
||||
Assert.assertTrue(response.containsHeader("Content-Length"));
|
||||
|
||||
|
@ -100,17 +100,17 @@ public class TestCachedHttpResponseGenerator {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testResponseStatusCodeMatchesCacheEntry() {
|
||||
final ClassicHttpResponse response = impl.generateResponse(request, entry);
|
||||
public void testResponseStatusCodeMatchesCacheEntry() throws Exception {
|
||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||
|
||||
Assert.assertEquals(entry.getStatus(), response.getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() {
|
||||
public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() throws Exception {
|
||||
currentAge(10L);
|
||||
|
||||
final ClassicHttpResponse response = impl.generateResponse(request, entry);
|
||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||
|
||||
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
|
||||
|
||||
|
@ -120,10 +120,10 @@ public class TestCachedHttpResponseGenerator {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() {
|
||||
public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() throws Exception {
|
||||
currentAge(0L);
|
||||
|
||||
final ClassicHttpResponse response = impl.generateResponse(request, entry);
|
||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||
|
||||
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
|
||||
|
||||
|
@ -132,10 +132,10 @@ public class TestCachedHttpResponseGenerator {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() {
|
||||
public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() throws Exception {
|
||||
currentAge(CacheValidityPolicy.MAX_AGE + 1L);
|
||||
|
||||
final ClassicHttpResponse response = impl.generateResponse(request, entry);
|
||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||
|
||||
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
|
||||
|
||||
|
@ -152,17 +152,17 @@ public class TestCachedHttpResponseGenerator {
|
|||
|
||||
@Test
|
||||
public void testResponseContainsEntityToServeGETRequestIfEntryContainsResource() throws Exception {
|
||||
final ClassicHttpResponse response = impl.generateResponse(request, entry);
|
||||
final SimpleHttpResponse response = impl.generateResponse(request, entry);
|
||||
|
||||
Assert.assertNotNull(response.getEntity());
|
||||
Assert.assertNotNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponseDoesNotContainEntityToServeHEADRequestIfEntryContainsResource() throws Exception {
|
||||
final ClassicHttpRequest headRequest = HttpTestUtils.makeDefaultHEADRequest();
|
||||
final ClassicHttpResponse response = impl.generateResponse(headRequest, entry);
|
||||
final SimpleHttpResponse response = impl.generateResponse(headRequest, entry);
|
||||
|
||||
Assert.assertNull(response.getEntity());
|
||||
Assert.assertNull(response.getBody());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.classic.ExecChain;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||
|
@ -290,7 +291,7 @@ public class TestCachingExec extends TestCachingExecChain {
|
|||
eq(responseDate)))
|
||||
.andReturn(updatedEntry);
|
||||
expect(mockSuitabilityChecker.isConditional(request)).andReturn(false);
|
||||
responseIsGeneratedFromCache(HttpTestUtils.make200Response());
|
||||
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
||||
|
||||
replayMocks();
|
||||
impl.revalidateCacheEntry(host, request, scope, mockExecChain, entry);
|
||||
|
@ -396,7 +397,7 @@ public class TestCachingExec extends TestCachingExecChain {
|
|||
cacheEntrySuitable(true);
|
||||
cacheEntryValidatable(true);
|
||||
|
||||
responseIsGeneratedFromCache(HttpTestUtils.make200Response());
|
||||
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
||||
|
||||
replayMocks();
|
||||
impl.execute(request, scope, mockExecChain);
|
||||
|
|
|
@ -50,6 +50,7 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.hc.client5.http.HttpRoute;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.client5.http.cache.CacheResponseStatus;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheContext;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
|
@ -312,7 +313,7 @@ public abstract class TestCachingExecChain {
|
|||
requestPolicyAllowsCaching(true);
|
||||
getCacheEntryReturns(mockCacheEntry);
|
||||
cacheEntrySuitable(true);
|
||||
responseIsGeneratedFromCache(HttpTestUtils.make200Response());
|
||||
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
||||
requestIsFatallyNonCompliant(null);
|
||||
entryHasStaleness(0L);
|
||||
|
||||
|
@ -350,7 +351,7 @@ public abstract class TestCachingExecChain {
|
|||
requestPolicyAllowsCaching(true);
|
||||
cacheEntrySuitable(true);
|
||||
getCacheEntryReturns(mockCacheEntry);
|
||||
responseIsGeneratedFromCache(HttpTestUtils.make200Response());
|
||||
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
||||
entryHasStaleness(0L);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1351,7 +1352,7 @@ public abstract class TestCachingExecChain {
|
|||
originResponse.setHeader("ETag", "\"etag\"");
|
||||
|
||||
final HttpCacheEntry httpCacheEntry = HttpTestUtils.makeCacheEntry();
|
||||
final ClassicHttpResponse response = HttpTestUtils.make200Response();
|
||||
final SimpleHttpResponse response = SimpleHttpResponse.create(HttpStatus.SC_OK);
|
||||
|
||||
EasyMock.expect(mockCache.createCacheEntry(
|
||||
eq(host),
|
||||
|
@ -1410,7 +1411,7 @@ public abstract class TestCachingExecChain {
|
|||
requestPolicyAllowsCaching(true);
|
||||
getCacheEntryReturns(entry);
|
||||
cacheEntrySuitable(true);
|
||||
responseIsGeneratedFromCache(HttpTestUtils.make200Response());
|
||||
responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK));
|
||||
entryHasStaleness(0);
|
||||
|
||||
replayMocks();
|
||||
|
@ -1745,7 +1746,7 @@ public abstract class TestCachingExecChain {
|
|||
.andReturn(staleness);
|
||||
}
|
||||
|
||||
protected void responseIsGeneratedFromCache(final ClassicHttpResponse cachedResponse) throws IOException {
|
||||
protected void responseIsGeneratedFromCache(final SimpleHttpResponse cachedResponse) throws IOException {
|
||||
expect(
|
||||
mockResponseGenerator.generateResponse(
|
||||
(ClassicHttpRequest) anyObject(),
|
||||
|
|
|
@ -36,13 +36,14 @@ import java.io.File;
|
|||
import java.util.Date;
|
||||
|
||||
import org.apache.hc.client5.http.HttpRoute;
|
||||
import org.apache.hc.client5.http.cache.CacheResponseStatus;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheContext;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheStorage;
|
||||
import org.apache.hc.client5.http.cache.ResourceFactory;
|
||||
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.protocol.HttpClientContext;
|
||||
import org.apache.hc.client5.http.utils.DateUtils;
|
||||
import org.apache.hc.core5.http.ClassicHttpRequest;
|
||||
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||
|
@ -52,6 +53,7 @@ import org.junit.After;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public class TestHttpCacheJiraNumber1147 {
|
||||
|
||||
|
@ -97,7 +99,7 @@ public class TestHttpCacheJiraNumber1147 {
|
|||
final HttpHost target = new HttpHost("somehost", 80);
|
||||
final HttpRoute route = new HttpRoute(target);
|
||||
final ClassicHttpRequest get = new HttpGet("http://somehost/");
|
||||
final HttpClientContext context = HttpClientContext.create();
|
||||
final HttpCacheContext context = HttpCacheContext.create();
|
||||
|
||||
final Date now = new Date();
|
||||
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||
|
@ -132,9 +134,10 @@ public class TestHttpCacheJiraNumber1147 {
|
|||
Assert.assertEquals(200, response2.getCode());
|
||||
IOUtils.consume(response2.getEntity());
|
||||
|
||||
verify(mockExecChain).proceed(
|
||||
verify(mockExecChain, Mockito.times(2)).proceed(
|
||||
isA(ClassicHttpRequest.class),
|
||||
isA(ExecChain.Scope.class));
|
||||
Assert.assertEquals(CacheResponseStatus.FAILURE, context.getCacheResponseStatus());
|
||||
}
|
||||
|
||||
protected ExecChainHandler createCachingExecChain(final BasicHttpCache cache, final CacheConfig config) {
|
||||
|
|
Loading…
Reference in New Issue