Upgraded HttpCore to version 5.0-alpha2; Upgraded to the latest 5.0 APIs

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1776187 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2016-12-27 19:48:07 +00:00
parent b85a51b868
commit e48091da3d
381 changed files with 5952 additions and 10846 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ bin
target target
.idea .idea
*.iml *.iml
/httpclient5/src/test/resources/log4j2-debug.xml

View File

@ -26,13 +26,14 @@
*/ */
package org.apache.hc.client5.http.cache; package org.apache.hc.client5.http.cache;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Records static constants for various HTTP header names. * Records static constants for various HTTP header names.
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class HeaderConstants { public class HeaderConstants {
public static final String GET_METHOD = "GET"; public static final String GET_METHOD = "GET";

View File

@ -27,14 +27,12 @@
package org.apache.hc.client5.http.cache; package org.apache.hc.client5.http.cache;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.annotation.NotThreadSafe;
import org.apache.hc.core5.http.protocol.BasicHttpContext; import org.apache.hc.core5.http.protocol.BasicHttpContext;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
/** /**
* @since 4.3 * @since 4.3
*/ */
@NotThreadSafe
public class HttpCacheContext extends HttpClientContext { public class HttpCacheContext extends HttpClientContext {
/** /**

View File

@ -34,11 +34,13 @@ import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.StatusLine; import org.apache.hc.core5.http.MessageHeaders;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.message.HeaderGroup; import org.apache.hc.core5.http.message.HeaderGroup;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
@ -51,15 +53,15 @@ import org.apache.hc.core5.util.Args;
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class HttpCacheEntry implements Serializable { public class HttpCacheEntry implements MessageHeaders, Serializable {
private static final long serialVersionUID = -6300496422359477413L; private static final long serialVersionUID = -6300496422359477413L;
private static final String REQUEST_METHOD_HEADER_NAME = "Hc-Request-Method"; private static final String REQUEST_METHOD_HEADER_NAME = "Hc-Request-Method";
private final Date requestDate; private final Date requestDate;
private final Date responseDate; private final Date responseDate;
private final StatusLine statusLine; private final int status;
private final HeaderGroup responseHeaders; private final HeaderGroup responseHeaders;
private final Resource resource; private final Resource resource;
private final Map<String,String> variantMap; private final Map<String,String> variantMap;
@ -73,8 +75,8 @@ public class HttpCacheEntry implements Serializable {
* @param responseDate * @param responseDate
* Date/time that the response came back (Used for age * Date/time that the response came back (Used for age
* calculations) * calculations)
* @param statusLine * @param status
* HTTP status line from origin response * HTTP status from origin response
* @param responseHeaders * @param responseHeaders
* Header[] from original HTTP Response * Header[] from original HTTP Response
* @param resource representing origin response body * @param resource representing origin response body
@ -82,62 +84,29 @@ public class HttpCacheEntry implements Serializable {
* of this parent entry; this maps a "variant key" (derived * of this parent entry; this maps a "variant key" (derived
* from the varying request headers) to a "cache key" (where * from the varying request headers) to a "cache key" (where
* in the cache storage the particular variant is located) * in the cache storage the particular variant is located)
* @param requestMethod HTTP method used when the request was made
*/ */
public HttpCacheEntry( public HttpCacheEntry(
final Date requestDate, final Date requestDate,
final Date responseDate, final Date responseDate,
final StatusLine statusLine, final int status,
final Header[] responseHeaders, final Header[] responseHeaders,
final Resource resource, final Resource resource,
final Map<String,String> variantMap, final Map<String,String> variantMap) {
final String requestMethod) {
super(); super();
Args.notNull(requestDate, "Request date"); Args.notNull(requestDate, "Request date");
Args.notNull(responseDate, "Response date"); Args.notNull(responseDate, "Response date");
Args.notNull(statusLine, "Status line"); Args.check(status >= HttpStatus.SC_SUCCESS, "Status code");
Args.notNull(responseHeaders, "Response headers"); Args.notNull(responseHeaders, "Response headers");
this.requestDate = requestDate; this.requestDate = requestDate;
this.responseDate = responseDate; this.responseDate = responseDate;
this.statusLine = statusLine; this.status = status;
this.responseHeaders = new HeaderGroup(); this.responseHeaders = new HeaderGroup();
this.responseHeaders.setHeaders(responseHeaders); this.responseHeaders.setHeaders(responseHeaders);
this.resource = resource; this.resource = resource;
this.variantMap = variantMap != null this.variantMap = variantMap != null ? new HashMap<>(variantMap) : null;
? new HashMap<>(variantMap)
: null;
this.date = parseDate(); this.date = parseDate();
} }
/**
* Create a new {@link HttpCacheEntry} with variants.
* @param requestDate
* Date/time when the request was made (Used for age
* calculations)
* @param responseDate
* Date/time that the response came back (Used for age
* calculations)
* @param statusLine
* HTTP status line from origin response
* @param responseHeaders
* Header[] from original HTTP Response
* @param resource representing origin response body
* @param variantMap describing cache entries that are variants
* of this parent entry; this maps a "variant key" (derived
* from the varying request headers) to a "cache key" (where
* in the cache storage the particular variant is located)
*/
public HttpCacheEntry(
final Date requestDate,
final Date responseDate,
final StatusLine statusLine,
final Header[] responseHeaders,
final Resource resource,
final Map<String,String> variantMap) {
this(requestDate, responseDate, statusLine, responseHeaders, resource,
variantMap, null);
}
/** /**
* Create a new {@link HttpCacheEntry}. * Create a new {@link HttpCacheEntry}.
* *
@ -147,38 +116,15 @@ public class HttpCacheEntry implements Serializable {
* @param responseDate * @param responseDate
* Date/time that the response came back (Used for age * Date/time that the response came back (Used for age
* calculations) * calculations)
* @param statusLine * @param status
* HTTP status line from origin response * HTTP status from origin response
* @param responseHeaders * @param responseHeaders
* Header[] from original HTTP Response * Header[] from original HTTP Response
* @param resource representing origin response body * @param resource representing origin response body
*/ */
public HttpCacheEntry(final Date requestDate, final Date responseDate, final StatusLine statusLine, public HttpCacheEntry(final Date requestDate, final Date responseDate, final int status,
final Header[] responseHeaders, final Resource resource) { final Header[] responseHeaders, final Resource resource) {
this(requestDate, responseDate, statusLine, responseHeaders, resource, this(requestDate, responseDate, status, responseHeaders, resource, new HashMap<String,String>());
new HashMap<String,String>());
}
/**
* Create a new {@link HttpCacheEntry}.
*
* @param requestDate
* Date/time when the request was made (Used for age
* calculations)
* @param responseDate
* Date/time that the response came back (Used for age
* calculations)
* @param statusLine
* HTTP status line from origin response
* @param responseHeaders
* Header[] from original HTTP Response
* @param resource representing origin response body
* @param requestMethod HTTP method used when the request was made
*/
public HttpCacheEntry(final Date requestDate, final Date responseDate, final StatusLine statusLine,
final Header[] responseHeaders, final Resource resource, final String requestMethod) {
this(requestDate, responseDate, statusLine, responseHeaders, resource,
new HashMap<String,String>(),requestMethod);
} }
/** /**
@ -194,35 +140,10 @@ public class HttpCacheEntry implements Serializable {
} }
/** /**
* Returns the {@link StatusLine} from the origin * Returns the status from the origin {@link org.apache.hc.core5.http.HttpResponse}.
* {@link org.apache.hc.core5.http.HttpResponse}.
*/ */
public StatusLine getStatusLine() { public int getStatus() {
return this.statusLine; return this.status;
}
/**
* Returns the {@link ProtocolVersion} from the origin
* {@link org.apache.hc.core5.http.HttpResponse}.
*/
public ProtocolVersion getProtocolVersion() {
return this.statusLine.getProtocolVersion();
}
/**
* Gets the reason phrase from the origin
* {@link org.apache.hc.core5.http.HttpResponse}, for example, "Not Modified".
*/
public String getReasonPhrase() {
return this.statusLine.getReasonPhrase();
}
/**
* Returns the HTTP response code from the origin
* {@link org.apache.hc.core5.http.HttpResponse}.
*/
public int getStatusCode() {
return this.statusLine.getStatusCode();
} }
/** /**
@ -245,6 +166,7 @@ public class HttpCacheEntry implements Serializable {
/** /**
* Returns all the headers that were on the origin response. * Returns all the headers that were on the origin response.
*/ */
@Override
public Header[] getAllHeaders() { public Header[] getAllHeaders() {
final HeaderGroup filteredHeaders = new HeaderGroup(); final HeaderGroup filteredHeaders = new HeaderGroup();
for (final Iterator<Header> iterator = responseHeaders.headerIterator(); iterator.hasNext();) { for (final Iterator<Header> iterator = responseHeaders.headerIterator(); iterator.hasNext();) {
@ -260,6 +182,7 @@ public class HttpCacheEntry implements Serializable {
* Returns the first header from the origin response with the given * Returns the first header from the origin response with the given
* name. * name.
*/ */
@Override
public Header getFirstHeader(final String name) { public Header getFirstHeader(final String name) {
if (REQUEST_METHOD_HEADER_NAME.equalsIgnoreCase(name)) { if (REQUEST_METHOD_HEADER_NAME.equalsIgnoreCase(name)) {
return null; return null;
@ -267,10 +190,19 @@ public class HttpCacheEntry implements Serializable {
return responseHeaders.getFirstHeader(name); return responseHeaders.getFirstHeader(name);
} }
/**
* @since 5.0
*/
@Override
public Header getLastHeader(final String name) {
return responseHeaders.getLastHeader(name);
}
/** /**
* Gets all the headers with the given name that were on the origin * Gets all the headers with the given name that were on the origin
* response. * response.
*/ */
@Override
public Header[] getHeaders(final String name) { public Header[] getHeaders(final String name) {
if (REQUEST_METHOD_HEADER_NAME.equalsIgnoreCase(name)) { if (REQUEST_METHOD_HEADER_NAME.equalsIgnoreCase(name)) {
return new Header[0]; return new Header[0];
@ -278,6 +210,46 @@ public class HttpCacheEntry implements Serializable {
return responseHeaders.getHeaders(name); return responseHeaders.getHeaders(name);
} }
/**
* @since 5.0
*/
@Override
public boolean containsHeader(final String name) {
return responseHeaders.containsHeader(name);
}
/**
* @since 5.0
*/
@Override
public int containsHeaders(final String name) {
return responseHeaders.containsHeaders(name);
}
/**
* @since 5.0
*/
@Override
public Header getSingleHeader(final String name) throws ProtocolException {
return responseHeaders.getSingleHeader(name);
}
/**
* @since 5.0
*/
@Override
public Iterator<Header> headerIterator() {
return responseHeaders.headerIterator();
}
/**
* @since 5.0
*/
@Override
public Iterator<Header> headerIterator(final String name) {
return responseHeaders.headerIterator(name);
}
/** /**
* Gets the Date value of the "Date" header or null if the header is missing or cannot be * Gets the Date value of the "Date" header or null if the header is missing or cannot be
* parsed. * parsed.
@ -325,8 +297,7 @@ public class HttpCacheEntry implements Serializable {
* @since 4.4 * @since 4.4
*/ */
public String getRequestMethod() { public String getRequestMethod() {
final Header requestMethodHeader = responseHeaders final Header requestMethodHeader = responseHeaders.getFirstHeader(REQUEST_METHOD_HEADER_NAME);
.getFirstHeader(REQUEST_METHOD_HEADER_NAME);
if (requestMethodHeader != null) { if (requestMethodHeader != null) {
return requestMethodHeader.getValue(); return requestMethodHeader.getValue();
} }
@ -340,7 +311,7 @@ public class HttpCacheEntry implements Serializable {
@Override @Override
public String toString() { public String toString() {
return "[request date=" + this.requestDate + "; response date=" + this.responseDate return "[request date=" + this.requestDate + "; response date=" + this.responseDate
+ "; statusLine=" + this.statusLine + "]"; + "; status=" + this.status + "]";
} }
} }

View File

@ -26,15 +26,12 @@
*/ */
package org.apache.hc.client5.http.cache; package org.apache.hc.client5.http.cache;
import org.apache.hc.core5.annotation.NotThreadSafe;
/** /**
* Used to limiting the size of an incoming response body of * Used to limiting the size of an incoming response body of
* unknown size that is optimistically being read in anticipation * unknown size that is optimistically being read in anticipation
* of caching it. * of caching it.
* @since 4.1 * @since 4.1
*/ */
@NotThreadSafe // reached
public class InputLimit { public class InputLimit {
private final long value; private final long value;

View File

@ -30,13 +30,12 @@ import java.io.IOException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
@ -48,8 +47,7 @@ import org.apache.hc.core5.http.HttpResponse;
public class AsynchronousValidationRequest implements Runnable { public class AsynchronousValidationRequest implements Runnable {
private final AsynchronousValidator parent; private final AsynchronousValidator parent;
private final CachingExec cachingExec; private final CachingExec cachingExec;
private final HttpRoute route; private final RoutedHttpRequest request;
private final HttpRequestWrapper request;
private final HttpClientContext context; private final HttpClientContext context;
private final HttpExecutionAware execAware; private final HttpExecutionAware execAware;
private final HttpCacheEntry cacheEntry; private final HttpCacheEntry cacheEntry;
@ -70,8 +68,7 @@ public class AsynchronousValidationRequest implements Runnable {
AsynchronousValidationRequest( AsynchronousValidationRequest(
final AsynchronousValidator parent, final AsynchronousValidator parent,
final CachingExec cachingExec, final CachingExec cachingExec,
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware, final HttpExecutionAware execAware,
final HttpCacheEntry cacheEntry, final HttpCacheEntry cacheEntry,
@ -79,7 +76,6 @@ public class AsynchronousValidationRequest implements Runnable {
final int consecutiveFailedAttempts) { final int consecutiveFailedAttempts) {
this.parent = parent; this.parent = parent;
this.cachingExec = cachingExec; this.cachingExec = cachingExec;
this.route = route;
this.request = request; this.request = request;
this.context = context; this.context = context;
this.execAware = execAware; this.execAware = execAware;
@ -110,8 +106,8 @@ public class AsynchronousValidationRequest implements Runnable {
*/ */
private boolean revalidateCacheEntry() { private boolean revalidateCacheEntry() {
try { try {
try (CloseableHttpResponse httpResponse = cachingExec.revalidateCacheEntry(route, request, context, execAware, cacheEntry)) { try (ClassicHttpResponse httpResponse = cachingExec.revalidateCacheEntry(request, context, execAware, cacheEntry)) {
final int statusCode = httpResponse.getStatusLine().getStatusCode(); final int statusCode = httpResponse.getCode();
return isNotServerError(statusCode) && isNotStale(httpResponse); return isNotServerError(statusCode) && isNotStale(httpResponse);
} }
} catch (final IOException ioe) { } catch (final IOException ioe) {

View File

@ -35,10 +35,9 @@ import java.util.concurrent.RejectedExecutionException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
/** /**
@ -91,19 +90,18 @@ class AsynchronousValidator implements Closeable {
*/ */
public synchronized void revalidateCacheEntry( public synchronized void revalidateCacheEntry(
final CachingExec cachingExec, final CachingExec cachingExec,
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware, final HttpExecutionAware execAware,
final HttpCacheEntry entry) { final HttpCacheEntry entry) {
// getVariantURI will fall back on getURI if no variants exist // getVariantURI will fall back on getURI if no variants exist
final String uri = cacheKeyGenerator.getVariantURI(context.getTargetHost(), request, entry); final String uri = cacheKeyGenerator.generateVariantURI(request.getTargetHost(), request, entry);
if (!queued.contains(uri)) { if (!queued.contains(uri)) {
final int consecutiveFailedAttempts = failureCache.getErrorCount(uri); final int consecutiveFailedAttempts = failureCache.getErrorCount(uri);
final AsynchronousValidationRequest revalidationRequest = final AsynchronousValidationRequest revalidationRequest =
new AsynchronousValidationRequest( new AsynchronousValidationRequest(
this, cachingExec, route, request, context, execAware, entry, uri, consecutiveFailedAttempts); this, cachingExec, request, context, execAware, entry, uri, consecutiveFailedAttempts);
try { try {
schedulingStrategy.schedule(revalidationRequest); schedulingStrategy.schedule(revalidationRequest);

View File

@ -44,17 +44,15 @@ import org.apache.hc.client5.http.cache.HttpCacheUpdateCallback;
import org.apache.hc.client5.http.cache.HttpCacheUpdateException; import org.apache.hc.client5.http.cache.HttpCacheUpdateException;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.client5.http.cache.ResourceFactory; import org.apache.hc.client5.http.cache.ResourceFactory;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.client5.http.methods.HttpRequestWrapper;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.entity.ByteArrayEntity; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHttpResponse;
class BasicHttpCache implements HttpCache { class BasicHttpCache implements HttpCache {
private static final Set<String> safeRequestMethods = new HashSet<>( private static final Set<String> safeRequestMethods = new HashSet<>(
@ -114,15 +112,15 @@ class BasicHttpCache implements HttpCache {
@Override @Override
public void flushCacheEntriesFor(final HttpHost host, final HttpRequest request) public void flushCacheEntriesFor(final HttpHost host, final HttpRequest request)
throws IOException { throws IOException {
if (!safeRequestMethods.contains(request.getRequestLine().getMethod())) { if (!safeRequestMethods.contains(request.getMethod())) {
final String uri = uriExtractor.getURI(host, request); final String uri = uriExtractor.generateKey(host, request);
storage.removeEntry(uri); storage.removeEntry(uri);
} }
} }
@Override @Override
public void flushInvalidatedCacheEntriesFor(final HttpHost host, final HttpRequest request, final HttpResponse response) { public void flushInvalidatedCacheEntriesFor(final HttpHost host, final HttpRequest request, final HttpResponse response) {
if (!safeRequestMethods.contains(request.getRequestLine().getMethod())) { if (!safeRequestMethods.contains(request.getMethod())) {
cacheInvalidator.flushInvalidatedCacheEntries(host, request, response); cacheInvalidator.flushInvalidatedCacheEntries(host, request, response);
} }
} }
@ -138,7 +136,7 @@ class BasicHttpCache implements HttpCache {
void storeNonVariantEntry( void storeNonVariantEntry(
final HttpHost target, final HttpRequest req, final HttpCacheEntry entry) throws IOException { final HttpHost target, final HttpRequest req, final HttpCacheEntry entry) throws IOException {
final String uri = uriExtractor.getURI(target, req); final String uri = uriExtractor.generateKey(target, req);
storage.putEntry(uri, entry); storage.putEntry(uri, entry);
} }
@ -146,8 +144,8 @@ class BasicHttpCache implements HttpCache {
final HttpHost target, final HttpHost target,
final HttpRequest req, final HttpRequest req,
final HttpCacheEntry entry) throws IOException { final HttpCacheEntry entry) throws IOException {
final String parentURI = uriExtractor.getURI(target, req); final String parentURI = uriExtractor.generateKey(target, req);
final String variantURI = uriExtractor.getVariantURI(target, req, entry); final String variantURI = uriExtractor.generateVariantURI(target, req, entry);
storage.putEntry(variantURI, entry); storage.putEntry(variantURI, entry);
final HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() { final HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
@ -155,8 +153,8 @@ class BasicHttpCache implements HttpCache {
@Override @Override
public HttpCacheEntry update(final HttpCacheEntry existing) throws IOException { public HttpCacheEntry update(final HttpCacheEntry existing) throws IOException {
return doGetUpdatedParentEntry( return doGetUpdatedParentEntry(
req.getRequestLine().getUri(), existing, entry, req.getRequestUri(), existing, entry,
uriExtractor.getVariantKey(req, entry), uriExtractor.generateVariantKey(req, entry),
variantURI); variantURI);
} }
@ -172,16 +170,16 @@ class BasicHttpCache implements HttpCache {
@Override @Override
public void reuseVariantEntryFor(final HttpHost target, final HttpRequest req, public void reuseVariantEntryFor(final HttpHost target, final HttpRequest req,
final Variant variant) throws IOException { final Variant variant) throws IOException {
final String parentCacheKey = uriExtractor.getURI(target, req); final String parentCacheKey = uriExtractor.generateKey(target, req);
final HttpCacheEntry entry = variant.getEntry(); final HttpCacheEntry entry = variant.getEntry();
final String variantKey = uriExtractor.getVariantKey(req, entry); final String variantKey = uriExtractor.generateVariantKey(req, entry);
final String variantCacheKey = variant.getCacheKey(); final String variantCacheKey = variant.getCacheKey();
final HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() { final HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
@Override @Override
public HttpCacheEntry update(final HttpCacheEntry existing) public HttpCacheEntry update(final HttpCacheEntry existing)
throws IOException { throws IOException {
return doGetUpdatedParentEntry(req.getRequestLine().getUri(), return doGetUpdatedParentEntry(req.getRequestUri(),
existing, entry, variantKey, variantCacheKey); existing, entry, variantKey, variantCacheKey);
} }
}; };
@ -194,7 +192,7 @@ class BasicHttpCache implements HttpCache {
} }
boolean isIncompleteResponse(final HttpResponse resp, final Resource resource) { boolean isIncompleteResponse(final HttpResponse resp, final Resource resource) {
final int status = resp.getStatusLine().getStatusCode(); final int status = resp.getCode();
if (status != HttpStatus.SC_OK if (status != HttpStatus.SC_OK
&& status != HttpStatus.SC_PARTIAL_CONTENT) { && status != HttpStatus.SC_PARTIAL_CONTENT) {
return false; return false;
@ -215,11 +213,10 @@ class BasicHttpCache implements HttpCache {
return (resource.length() < contentLength); return (resource.length() < contentLength);
} }
CloseableHttpResponse generateIncompleteResponseError( ClassicHttpResponse generateIncompleteResponseError(
final HttpResponse response, final Resource resource) { final HttpResponse response, final Resource resource) {
final Integer contentLength = Integer.valueOf(response.getFirstHeader(HttpHeaders.CONTENT_LENGTH).getValue()); final Integer contentLength = Integer.valueOf(response.getFirstHeader(HttpHeaders.CONTENT_LENGTH).getValue());
final HttpResponse error = final ClassicHttpResponse error = new BasicClassicHttpResponse(HttpStatus.SC_BAD_GATEWAY, "Bad Gateway");
new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_GATEWAY, "Bad Gateway");
error.setHeader("Content-Type","text/plain;charset=UTF-8"); error.setHeader("Content-Type","text/plain;charset=UTF-8");
final String msg = String.format("Received incomplete response " + final String msg = String.format("Received incomplete response " +
"with Content-Length %d but actual body length %d", "with Content-Length %d but actual body length %d",
@ -227,7 +224,7 @@ class BasicHttpCache implements HttpCache {
final byte[] msgBytes = msg.getBytes(); final byte[] msgBytes = msg.getBytes();
error.setHeader("Content-Length", Integer.toString(msgBytes.length)); error.setHeader("Content-Length", Integer.toString(msgBytes.length));
error.setEntity(new ByteArrayEntity(msgBytes)); error.setEntity(new ByteArrayEntity(msgBytes));
return Proxies.enhanceResponse(error); return error;
} }
HttpCacheEntry doGetUpdatedParentEntry( HttpCacheEntry doGetUpdatedParentEntry(
@ -250,11 +247,10 @@ class BasicHttpCache implements HttpCache {
return new HttpCacheEntry( return new HttpCacheEntry(
src.getRequestDate(), src.getRequestDate(),
src.getResponseDate(), src.getResponseDate(),
src.getStatusLine(), src.getStatus(),
src.getAllHeaders(), src.getAllHeaders(),
resource, resource,
variantMap, variantMap);
src.getRequestMethod());
} }
@Override @Override
@ -262,7 +258,7 @@ class BasicHttpCache implements HttpCache {
final HttpCacheEntry stale, final HttpResponse originResponse, final HttpCacheEntry stale, final HttpResponse originResponse,
final Date requestSent, final Date responseReceived) throws IOException { final Date requestSent, final Date responseReceived) throws IOException {
final HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry( final HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(
request.getRequestLine().getUri(), request.getRequestUri(),
stale, stale,
requestSent, requestSent,
responseReceived, responseReceived,
@ -276,7 +272,7 @@ class BasicHttpCache implements HttpCache {
final HttpCacheEntry stale, final HttpResponse originResponse, final HttpCacheEntry stale, final HttpResponse originResponse,
final Date requestSent, final Date responseReceived, final String cacheKey) throws IOException { final Date requestSent, final Date responseReceived, final String cacheKey) throws IOException {
final HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry( final HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(
request.getRequestLine().getUri(), request.getRequestUri(),
stale, stale,
requestSent, requestSent,
responseReceived, responseReceived,
@ -286,19 +282,10 @@ class BasicHttpCache implements HttpCache {
} }
@Override @Override
public HttpResponse cacheAndReturnResponse(final HttpHost host, final HttpRequest request, public ClassicHttpResponse cacheAndReturnResponse(
final HttpResponse originResponse, final Date requestSent, final Date responseReceived)
throws IOException {
return cacheAndReturnResponse(host, request,
Proxies.enhanceResponse(originResponse), requestSent,
responseReceived);
}
@Override
public CloseableHttpResponse cacheAndReturnResponse(
final HttpHost host, final HttpHost host,
final HttpRequest request, final HttpRequest request,
final CloseableHttpResponse originResponse, final ClassicHttpResponse originResponse,
final Date requestSent, final Date requestSent,
final Date responseReceived) throws IOException { final Date responseReceived) throws IOException {
@ -320,12 +307,11 @@ class BasicHttpCache implements HttpCache {
final HttpCacheEntry entry = new HttpCacheEntry( final HttpCacheEntry entry = new HttpCacheEntry(
requestSent, requestSent,
responseReceived, responseReceived,
originResponse.getStatusLine(), originResponse.getCode(),
originResponse.getAllHeaders(), originResponse.getAllHeaders(),
resource, resource);
request.getRequestLine().getMethod());
storeInCache(host, request, entry); storeInCache(host, request, entry);
return responseGenerator.generateResponse(HttpRequestWrapper.wrap(request, host), entry); return responseGenerator.generateResponse(request, entry);
} finally { } finally {
if (closeOriginResponse) { if (closeOriginResponse) {
originResponse.close(); originResponse.close();
@ -334,21 +320,21 @@ class BasicHttpCache implements HttpCache {
} }
SizeLimitedResponseReader getResponseReader(final HttpRequest request, SizeLimitedResponseReader getResponseReader(final HttpRequest request,
final CloseableHttpResponse backEndResponse) { final ClassicHttpResponse backEndResponse) {
return new SizeLimitedResponseReader( return new SizeLimitedResponseReader(
resourceFactory, maxObjectSizeBytes, request, backEndResponse); resourceFactory, maxObjectSizeBytes, request, backEndResponse);
} }
@Override @Override
public HttpCacheEntry getCacheEntry(final HttpHost host, final HttpRequest request) throws IOException { public HttpCacheEntry getCacheEntry(final HttpHost host, final HttpRequest request) throws IOException {
final HttpCacheEntry root = storage.getEntry(uriExtractor.getURI(host, request)); final HttpCacheEntry root = storage.getEntry(uriExtractor.generateKey(host, request));
if (root == null) { if (root == null) {
return null; return null;
} }
if (!root.hasVariants()) { if (!root.hasVariants()) {
return root; return root;
} }
final String variantCacheKey = root.getVariantMap().get(uriExtractor.getVariantKey(request, root)); final String variantCacheKey = root.getVariantMap().get(uriExtractor.generateVariantKey(request, root));
if (variantCacheKey == null) { if (variantCacheKey == null) {
return null; return null;
} }
@ -365,7 +351,7 @@ class BasicHttpCache implements HttpCache {
public Map<String, Variant> getVariantCacheEntriesWithEtags(final HttpHost host, final HttpRequest request) public Map<String, Variant> getVariantCacheEntriesWithEtags(final HttpHost host, final HttpRequest request)
throws IOException { throws IOException {
final Map<String,Variant> variants = new HashMap<>(); final Map<String,Variant> variants = new HashMap<>();
final HttpCacheEntry root = storage.getEntry(uriExtractor.getURI(host, request)); final HttpCacheEntry root = storage.getEntry(uriExtractor.generateKey(host, request));
if (root == null || !root.hasVariants()) { if (root == null || !root.hasVariants()) {
return variants; return variants;
} }

View File

@ -31,7 +31,8 @@ import java.io.IOException;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheStorage; import org.apache.hc.client5.http.cache.HttpCacheStorage;
import org.apache.hc.client5.http.cache.HttpCacheUpdateCallback; import org.apache.hc.client5.http.cache.HttpCacheUpdateCallback;
import org.apache.hc.core5.annotation.ThreadSafe; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Basic {@link HttpCacheStorage} implementation backed by an instance of * Basic {@link HttpCacheStorage} implementation backed by an instance of
@ -43,7 +44,7 @@ import org.apache.hc.core5.annotation.ThreadSafe;
* *
* @since 4.1 * @since 4.1
*/ */
@ThreadSafe @Contract(threading = ThreadingBehavior.SAFE)
public class BasicHttpCacheStorage implements HttpCacheStorage { public class BasicHttpCacheStorage implements HttpCacheStorage {
private final CacheMap entries; private final CacheMap entries;

View File

@ -33,19 +33,18 @@ import java.security.SecureRandom;
import java.util.Formatter; import java.util.Formatter;
import java.util.Locale; import java.util.Locale;
import org.apache.hc.core5.annotation.GuardedBy; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadSafe; import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Should produce reasonably unique tokens. * Should produce reasonably unique tokens.
*/ */
@ThreadSafe @Contract(threading = ThreadingBehavior.SAFE)
class BasicIdGenerator { class BasicIdGenerator {
private final String hostname; private final String hostname;
private final SecureRandom rnd; private final SecureRandom rnd;
@GuardedBy("this")
private long count; private long count;
public BasicIdGenerator() { public BasicIdGenerator() {

View File

@ -30,17 +30,19 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.core5.annotation.Immutable; 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.Header;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.TrailerSupplier;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class CacheEntity implements HttpEntity, Serializable { class CacheEntity implements HttpEntity, Serializable {
private static final long serialVersionUID = -3467082284120936233L; private static final long serialVersionUID = -3467082284120936233L;
@ -98,7 +100,7 @@ class CacheEntity implements HttpEntity, Serializable {
} }
@Override @Override
public TrailerSupplier getTrailers() { public Supplier<List<? extends Header>> getTrailers() {
return null; return null;
} }
@ -107,4 +109,8 @@ class CacheEntity implements HttpEntity, Serializable {
return null; return null;
} }
@Override
public void close() throws IOException {
}
} }

View File

@ -38,7 +38,8 @@ import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.client5.http.cache.ResourceFactory; import org.apache.hc.client5.http.cache.ResourceFactory;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
@ -52,7 +53,7 @@ import org.apache.hc.core5.util.Args;
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class CacheEntryUpdater { class CacheEntryUpdater {
private final ResourceFactory resourceFactory; private final ResourceFactory resourceFactory;
@ -84,7 +85,7 @@ class CacheEntryUpdater {
final Date requestDate, final Date requestDate,
final Date responseDate, final Date responseDate,
final HttpResponse response) throws IOException { final HttpResponse response) throws IOException {
Args.check(response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED, Args.check(response.getCode() == HttpStatus.SC_NOT_MODIFIED,
"Response must have 304 status code"); "Response must have 304 status code");
final Header[] mergedHeaders = mergeHeaders(entry, response); final Header[] mergedHeaders = mergeHeaders(entry, response);
Resource resource = null; Resource resource = null;
@ -94,10 +95,9 @@ class CacheEntryUpdater {
return new HttpCacheEntry( return new HttpCacheEntry(
requestDate, requestDate,
responseDate, responseDate,
entry.getStatusLine(), entry.getStatus(),
mergedHeaders, mergedHeaders,
resource, resource);
entry.getRequestMethod());
} }
protected Header[] mergeHeaders(final HttpCacheEntry entry, final HttpResponse response) { protected Header[] mergeHeaders(final HttpCacheEntry entry, final HttpResponse response) {

View File

@ -38,7 +38,8 @@ import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheInvalidator; import org.apache.hc.client5.http.cache.HttpCacheInvalidator;
import org.apache.hc.client5.http.cache.HttpCacheStorage; import org.apache.hc.client5.http.cache.HttpCacheStorage;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
@ -51,7 +52,7 @@ import org.apache.hc.core5.http.HttpResponse;
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class CacheInvalidator implements HttpCacheInvalidator { class CacheInvalidator implements HttpCacheInvalidator {
private final HttpCacheStorage storage; private final HttpCacheStorage storage;
@ -82,7 +83,7 @@ class CacheInvalidator implements HttpCacheInvalidator {
*/ */
@Override @Override
public void flushInvalidatedCacheEntries(final HttpHost host, final HttpRequest req) { public void flushInvalidatedCacheEntries(final HttpHost host, final HttpRequest req) {
final String theUri = cacheKeyGenerator.getURI(host, req); final String theUri = cacheKeyGenerator.generateKey(host, req);
final HttpCacheEntry parent = getEntry(theUri); final HttpCacheEntry parent = getEntry(theUri);
if (requestShouldNotBeCached(req) || shouldInvalidateHeadCacheEntry(req, parent)) { if (requestShouldNotBeCached(req) || shouldInvalidateHeadCacheEntry(req, parent)) {
@ -117,7 +118,7 @@ class CacheInvalidator implements HttpCacheInvalidator {
} }
private boolean requestIsGet(final HttpRequest req) { private boolean requestIsGet(final HttpRequest req) {
return req.getRequestLine().getMethod().equals((HeaderConstants.GET_METHOD)); return req.getMethod().equals((HeaderConstants.GET_METHOD));
} }
private boolean isAHeadCacheEntry(final HttpCacheEntry parentCacheEntry) { private boolean isAHeadCacheEntry(final HttpCacheEntry parentCacheEntry) {
@ -142,7 +143,7 @@ class CacheInvalidator implements HttpCacheInvalidator {
} }
protected void flushUriIfSameHost(final URL requestURL, final URL targetURL) { protected void flushUriIfSameHost(final URL requestURL, final URL targetURL) {
final URL canonicalTarget = getAbsoluteURL(cacheKeyGenerator.canonicalizeUri(targetURL.toString())); final URL canonicalTarget = getAbsoluteURL(cacheKeyGenerator.generateKey(targetURL));
if (canonicalTarget == null) { if (canonicalTarget == null) {
return; return;
} }
@ -190,7 +191,7 @@ class CacheInvalidator implements HttpCacheInvalidator {
} }
protected boolean requestShouldNotBeCached(final HttpRequest req) { protected boolean requestShouldNotBeCached(final HttpRequest req) {
final String method = req.getRequestLine().getMethod(); final String method = req.getMethod();
return notGetOrHeadRequest(method); return notGetOrHeadRequest(method);
} }
@ -205,11 +206,11 @@ class CacheInvalidator implements HttpCacheInvalidator {
@Override @Override
public void flushInvalidatedCacheEntries(final HttpHost host, public void flushInvalidatedCacheEntries(final HttpHost host,
final HttpRequest request, final HttpResponse response) { final HttpRequest request, final HttpResponse response) {
final int status = response.getStatusLine().getStatusCode(); final int status = response.getCode();
if (status < 200 || status > 299) { if (status < 200 || status > 299) {
return; return;
} }
final URL reqURL = getAbsoluteURL(cacheKeyGenerator.getURI(host, request)); final URL reqURL = getAbsoluteURL(cacheKeyGenerator.generateKey(host, request));
if (reqURL == null) { if (reqURL == null) {
return; return;
} }
@ -225,7 +226,7 @@ class CacheInvalidator implements HttpCacheInvalidator {
private void flushLocationCacheEntry(final URL reqURL, private void flushLocationCacheEntry(final URL reqURL,
final HttpResponse response, final URL location) { final HttpResponse response, final URL location) {
final String cacheKey = cacheKeyGenerator.canonicalizeUri(location.toString()); final String cacheKey = cacheKeyGenerator.generateKey(location);
final HttpCacheEntry entry = getEntry(cacheKey); final HttpCacheEntry entry = getEntry(cacheKey);
if (entry == null) { if (entry == null) {
return; return;

View File

@ -27,32 +27,56 @@
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.utils.URIUtils; import org.apache.hc.client5.http.utils.URIUtils;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.net.URIBuilder;
/** /**
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class CacheKeyGenerator { class CacheKeyGenerator {
private static final URI BASE_URI = URI.create("http://example.com/"); private static final URI BASE_URI = URI.create("http://example.com/");
private URI normalize(final URI uri) throws URISyntaxException {
final URIBuilder builder = new URIBuilder(URIUtils.resolve(BASE_URI, uri)) ;
if (builder.getHost() != null) {
if (builder.getScheme() == null) {
builder.setScheme("http");
}
if (builder.getPort() == -1) {
if ("http".equalsIgnoreCase(builder.getScheme())) {
builder.setPort(80);
} else if ("https".equalsIgnoreCase(builder.getScheme())) {
builder.setPort(443);
}
}
}
if (builder.getPath() == null) {
builder.setPath("/");
}
return builder.build();
}
/** /**
* For a given {@link HttpHost} and {@link HttpRequest} get a URI from the * For a given {@link HttpHost} and {@link HttpRequest} get a URI from the
* pair that I can use as an identifier KEY into my HttpCache * pair that I can use as an identifier KEY into my HttpCache
@ -61,60 +85,40 @@ class CacheKeyGenerator {
* @param req the {@link HttpRequest} * @param req the {@link HttpRequest}
* @return String the extracted URI * @return String the extracted URI
*/ */
public String getURI(final HttpHost host, final HttpRequest req) { public String generateKey(final HttpHost host, final HttpRequest req) {
if (isRelativeRequest(req)) {
return canonicalizeUri(String.format("%s%s", host.toString(), req.getRequestLine().getUri()));
}
return canonicalizeUri(req.getRequestLine().getUri());
}
public String canonicalizeUri(final String uri) {
try { try {
final URI normalized = URIUtils.resolve(BASE_URI, uri); URI uri = req.getUri();
final URL u = new URL(normalized.toASCIIString()); if (!uri.isAbsolute()) {
final String protocol = u.getProtocol(); uri = URIUtils.rewriteURI(uri, host);
final String hostname = u.getHost(); }
final int port = canonicalizePort(u.getPort(), protocol); return normalize(uri).toASCIIString();
final String path = u.getPath(); } catch (URISyntaxException ex) {
final String query = u.getQuery(); return req.getRequestUri();
final String file = (query != null) ? (path + "?" + query) : path;
final URL out = new URL(protocol, hostname, port, file);
return out.toString();
} catch (final IllegalArgumentException e) {
return uri;
} catch (final MalformedURLException e) {
return uri;
} }
} }
private int canonicalizePort(final int port, final String protocol) { public String generateKey(final URL url) {
if (port == -1 && "http".equalsIgnoreCase(protocol)) { if (url == null) {
return 80; return null;
} else if (port == -1 && "https".equalsIgnoreCase(protocol)) { }
return 443; try {
return normalize(url.toURI()).toASCIIString();
} catch (URISyntaxException ex) {
return url.toString();
} }
return port;
}
private boolean isRelativeRequest(final HttpRequest req) {
final String requestUri = req.getRequestLine().getUri();
return ("*".equals(requestUri) || requestUri.startsWith("/"));
} }
protected String getFullHeaderValue(final Header[] headers) { protected String getFullHeaderValue(final Header[] headers) {
if (headers == null) { if (headers == null) {
return ""; return "";
} }
final StringBuilder buf = new StringBuilder(""); final StringBuilder buf = new StringBuilder("");
boolean first = true; for (int i = 0; i < headers.length; i++) {
for (final Header hdr : headers) { final Header hdr = headers[i];
if (!first) { if (i > 0) {
buf.append(", "); buf.append(", ");
} }
buf.append(hdr.getValue().trim()); buf.append(hdr.getValue().trim());
first = false;
} }
return buf.toString(); return buf.toString();
} }
@ -129,11 +133,11 @@ class CacheKeyGenerator {
* @param entry the parent entry used to track the variants * @param entry the parent entry used to track the variants
* @return String the extracted variant URI * @return String the extracted variant URI
*/ */
public String getVariantURI(final HttpHost host, final HttpRequest req, final HttpCacheEntry entry) { public String generateVariantURI(final HttpHost host, final HttpRequest req, final HttpCacheEntry entry) {
if (!entry.hasVariants()) { if (!entry.hasVariants()) {
return getURI(host, req); return generateKey(host, req);
} }
return getVariantKey(req, entry) + getURI(host, req); return generateVariantKey(req, entry) + generateKey(host, req);
} }
/** /**
@ -145,12 +149,12 @@ class CacheKeyGenerator {
* @param entry cache entry in question that has variants * @param entry cache entry in question that has variants
* @return a {@code String} variant key * @return a {@code String} variant key
*/ */
public String getVariantKey(final HttpRequest req, final HttpCacheEntry entry) { public String generateVariantKey(final HttpRequest req, final HttpCacheEntry entry) {
final List<String> variantHeaderNames = new ArrayList<>(); final List<String> variantHeaderNames = new ArrayList<>();
for (final Header varyHdr : entry.getHeaders(HeaderConstants.VARY)) { final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.VARY);
for (final HeaderElement elt : varyHdr.getElements()) { while (it.hasNext()) {
variantHeaderNames.add(elt.getName()); final HeaderElement elt = it.next();
} variantHeaderNames.add(elt.getName());
} }
Collections.sort(variantHeaderNames); Collections.sort(variantHeaderNames);

View File

@ -27,20 +27,24 @@
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import java.util.Date; import java.util.Date;
import java.util.Iterator;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.MessageHeaders;
/** /**
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class CacheValidityPolicy { class CacheValidityPolicy {
public static final long MAX_AGE = 2147483648L; public static final long MAX_AGE = 2147483648L;
@ -124,17 +128,17 @@ class CacheValidityPolicy {
} }
public boolean mayReturnStaleWhileRevalidating(final HttpCacheEntry entry, final Date now) { public boolean mayReturnStaleWhileRevalidating(final HttpCacheEntry entry, final Date now) {
for (final Header h : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) { final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) { final HeaderElement elt = it.next();
try { if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) {
final int allowedStalenessLifetime = Integer.parseInt(elt.getValue()); try {
if (getStalenessSecs(entry, now) <= allowedStalenessLifetime) { final int allowedStalenessLifetime = Integer.parseInt(elt.getValue());
return true; if (getStalenessSecs(entry, now) <= allowedStalenessLifetime) {
} return true;
} catch (final NumberFormatException nfe) {
// skip malformed directive
} }
} catch (final NumberFormatException nfe) {
// skip malformed directive
} }
} }
} }
@ -142,29 +146,26 @@ class CacheValidityPolicy {
return false; return false;
} }
public boolean mayReturnStaleIfError(final HttpRequest request, public boolean mayReturnStaleIfError(final HttpRequest request, final HttpCacheEntry entry, final Date now) {
final HttpCacheEntry entry, final Date now) {
final long stalenessSecs = getStalenessSecs(entry, now); final long stalenessSecs = getStalenessSecs(entry, now);
return mayReturnStaleIfError(request.getHeaders(HeaderConstants.CACHE_CONTROL), return mayReturnStaleIfError(request, HeaderConstants.CACHE_CONTROL, stalenessSecs)
stalenessSecs) || mayReturnStaleIfError(entry, HeaderConstants.CACHE_CONTROL, stalenessSecs);
|| mayReturnStaleIfError(entry.getHeaders(HeaderConstants.CACHE_CONTROL),
stalenessSecs);
} }
private boolean mayReturnStaleIfError(final Header[] headers, final long stalenessSecs) { private boolean mayReturnStaleIfError(final MessageHeaders headers, final String name, final long stalenessSecs) {
boolean result = false; boolean result = false;
for(final Header h : headers) { final Iterator<HeaderElement> it = MessageSupport.iterate(headers, name);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) { final HeaderElement elt = it.next();
try { if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) {
final int staleIfErrorSecs = Integer.parseInt(elt.getValue()); try {
if (stalenessSecs <= staleIfErrorSecs) { final int staleIfErrorSecs = Integer.parseInt(elt.getValue());
result = true; if (stalenessSecs <= staleIfErrorSecs) {
break; result = true;
} break;
} catch (final NumberFormatException nfe) {
// skip malformed directive
} }
} catch (final NumberFormatException nfe) {
// skip malformed directive
} }
} }
} }
@ -259,19 +260,18 @@ class CacheValidityPolicy {
protected long getMaxAge(final HttpCacheEntry entry) { protected long getMaxAge(final HttpCacheEntry entry) {
long maxage = -1; long maxage = -1;
for (final Header hdr : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) { final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
for (final HeaderElement elt : hdr.getElements()) { while (it.hasNext()) {
if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName()) final HeaderElement elt = it.next();
|| "s-maxage".equals(elt.getName())) { if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName()) || "s-maxage".equals(elt.getName())) {
try { try {
final long currMaxAge = Long.parseLong(elt.getValue()); final long currMaxAge = Long.parseLong(elt.getValue());
if (maxage == -1 || currMaxAge < maxage) { if (maxage == -1 || currMaxAge < maxage) {
maxage = currMaxAge; maxage = currMaxAge;
}
} catch (final NumberFormatException nfe) {
// be conservative if can't parse
maxage = 0;
} }
} catch (final NumberFormatException nfe) {
// be conservative if can't parse
maxage = 0;
} }
} }
} }
@ -286,13 +286,12 @@ class CacheValidityPolicy {
return DateUtils.parseDate(expiresHeader.getValue()); return DateUtils.parseDate(expiresHeader.getValue());
} }
public boolean hasCacheControlDirective(final HttpCacheEntry entry, public boolean hasCacheControlDirective(final HttpCacheEntry entry, final String directive) {
final String directive) { final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
for (final Header h : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) { while (it.hasNext()) {
for(final HeaderElement elt : h.getElements()) { final HeaderElement elt = it.next();
if (directive.equalsIgnoreCase(elt.getName())) { if (directive.equalsIgnoreCase(elt.getName())) {
return true; return true;
}
} }
} }
return false; return false;

View File

@ -26,11 +26,14 @@
*/ */
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import java.util.Iterator;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
@ -41,7 +44,7 @@ import org.apache.hc.core5.http.ProtocolVersion;
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class CacheableRequestPolicy { class CacheableRequestPolicy {
private final Log log = LogFactory.getLog(getClass()); private final Log log = LogFactory.getLog(getClass());
@ -54,9 +57,9 @@ class CacheableRequestPolicy {
* @return boolean Is it possible to serve this request from cache * @return boolean Is it possible to serve this request from cache
*/ */
public boolean isServableFromCache(final HttpRequest request) { public boolean isServableFromCache(final HttpRequest request) {
final String method = request.getRequestLine().getMethod(); final String method = request.getMethod();
final ProtocolVersion pv = request.getRequestLine().getProtocolVersion(); final ProtocolVersion pv = request.getVersion() != null ? request.getVersion() : HttpVersion.DEFAULT;
if (HttpVersion.HTTP_1_1.compareToVersion(pv) != 0) { if (HttpVersion.HTTP_1_1.compareToVersion(pv) != 0) {
log.trace("non-HTTP/1.1 request was not serveable from cache"); log.trace("non-HTTP/1.1 request was not serveable from cache");
return false; return false;
@ -73,20 +76,18 @@ class CacheableRequestPolicy {
return false; return false;
} }
final Header[] cacheControlHeaders = request.getHeaders(HeaderConstants.CACHE_CONTROL); final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
for (final Header cacheControl : cacheControlHeaders) { while (it.hasNext()) {
for (final HeaderElement cacheControlElement : cacheControl.getElements()) { final HeaderElement cacheControlElement = it.next();
if (HeaderConstants.CACHE_CONTROL_NO_STORE.equalsIgnoreCase(cacheControlElement if (HeaderConstants.CACHE_CONTROL_NO_STORE.equalsIgnoreCase(cacheControlElement
.getName())) { .getName())) {
log.trace("Request with no-store was not serveable from cache"); log.trace("Request with no-store was not serveable from cache");
return false; return false;
} }
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(cacheControlElement
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(cacheControlElement .getName())) {
.getName())) { log.trace("Request with no-cache was not serveable from cache");
log.trace("Request with no-cache was not serveable from cache"); return false;
return false;
}
} }
} }

View File

@ -30,25 +30,26 @@ import java.util.Date;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpRequestWrapper;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.annotation.Immutable; 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.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders; 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.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpResponse;
/** /**
* Rebuilds an {@link HttpResponse} from a {@link net.sf.ehcache.CacheEntry} * Rebuilds an {@link HttpResponse} from a {@link net.sf.ehcache.CacheEntry}
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class CachedHttpResponseGenerator { class CachedHttpResponseGenerator {
private final CacheValidityPolicy validityStrategy; private final CacheValidityPolicy validityStrategy;
@ -63,16 +64,16 @@ class CachedHttpResponseGenerator {
} }
/** /**
* If I was able to use a {@link CacheEntity} to response to the {@link org.apache.hc.core5.http.HttpRequest} then * 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. * generate an {@link HttpResponse} based on the cache entry.
* @param request {@link HttpRequestWrapper} to generate the response for * @param request {@link HttpRequest} to generate the response for
* @param entry {@link CacheEntity} to transform into an {@link HttpResponse} * @param entry {@link CacheEntity} to transform into an {@link HttpResponse}
* @return {@link HttpResponse} that was constructed * @return {@link HttpResponse} that was constructed
*/ */
CloseableHttpResponse generateResponse(final HttpRequestWrapper request, final HttpCacheEntry entry) { ClassicHttpResponse generateResponse(final HttpRequest request, final HttpCacheEntry entry) {
final Date now = new Date(); final Date now = new Date();
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, entry final ClassicHttpResponse response = new BasicClassicHttpResponse(entry.getStatus());
.getStatusCode(), entry.getReasonPhrase()); response.setVersion(HttpVersion.DEFAULT);
response.setHeaders(entry.getAllHeaders()); response.setHeaders(entry.getAllHeaders());
@ -91,17 +92,16 @@ class CachedHttpResponseGenerator {
} }
} }
return Proxies.enhanceResponse(response); return response;
} }
/** /**
* Generate a 304 - Not Modified response from a {@link CacheEntity}. This should be * Generate a 304 - Not Modified response from a {@link CacheEntity}. This should be
* used to respond to conditional requests, when the entry exists or has been re-validated. * used to respond to conditional requests, when the entry exists or has been re-validated.
*/ */
CloseableHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) { ClassicHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) {
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified");
HttpStatus.SC_NOT_MODIFIED, "Not Modified");
// The response MUST include the following headers // The response MUST include the following headers
// (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) // (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
@ -143,7 +143,7 @@ class CachedHttpResponseGenerator {
response.addHeader(varyHeader); response.addHeader(varyHeader);
} }
return Proxies.enhanceResponse(response); return response;
} }
private void addMissingContentLengthHeader(final HttpResponse response, final HttpEntity entity) { private void addMissingContentLengthHeader(final HttpResponse response, final HttpEntity entity) {
@ -164,9 +164,8 @@ class CachedHttpResponseGenerator {
return hdr != null; return hdr != null;
} }
private boolean responseShouldContainEntity(final HttpRequestWrapper request, final HttpCacheEntry cacheEntry) { private boolean responseShouldContainEntity(final HttpRequest request, final HttpCacheEntry cacheEntry) {
return request.getRequestLine().getMethod().equals(HeaderConstants.GET_METHOD) && return request.getMethod().equals(HeaderConstants.GET_METHOD) && cacheEntry.getResource() != null;
cacheEntry.getResource() != null;
} }
} }

View File

@ -27,13 +27,16 @@
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import java.util.Date; import java.util.Date;
import java.util.Iterator;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
@ -46,7 +49,7 @@ import org.apache.hc.core5.http.HttpStatus;
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class CachedResponseSuitabilityChecker { class CachedResponseSuitabilityChecker {
private final Log log = LogFactory.getLog(getClass()); private final Log log = LogFactory.getLog(getClass());
@ -102,25 +105,24 @@ class CachedResponseSuitabilityChecker {
private long getMaxStale(final HttpRequest request) { private long getMaxStale(final HttpRequest request) {
long maxstale = -1; long maxstale = -1;
for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) { final HeaderElement elt = it.next();
if ((elt.getValue() == null || "".equals(elt.getValue().trim())) if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
&& maxstale == -1) { if ((elt.getValue() == null || "".equals(elt.getValue().trim())) && maxstale == -1) {
maxstale = Long.MAX_VALUE; maxstale = Long.MAX_VALUE;
} else { } else {
try { try {
long val = Long.parseLong(elt.getValue()); long val = Long.parseLong(elt.getValue());
if (val < 0) { if (val < 0) {
val = 0; val = 0;
}
if (maxstale == -1 || val < maxstale) {
maxstale = val;
}
} catch (final NumberFormatException nfe) {
// err on the side of preserving semantic transparency
maxstale = 0;
} }
if (maxstale == -1 || val < maxstale) {
maxstale = val;
}
} catch (final NumberFormatException nfe) {
// err on the side of preserving semantic transparency
maxstale = 0;
} }
} }
} }
@ -158,7 +160,7 @@ class CachedResponseSuitabilityChecker {
return false; return false;
} }
if (!isConditional(request) && entry.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { if (!isConditional(request) && entry.getStatus() == HttpStatus.SC_NOT_MODIFIED) {
return false; return false;
} }
@ -171,65 +173,64 @@ class CachedResponseSuitabilityChecker {
"request method, entity or a 204 response"); "request method, entity or a 204 response");
return false; return false;
} }
final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
while (it.hasNext()) {
final HeaderElement elt = it.next();
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) {
log.trace("Response contained NO CACHE directive, cache was not suitable");
return false;
}
for (final Header ccHdr : request.getHeaders(HeaderConstants.CACHE_CONTROL)) { if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elt.getName())) {
for (final HeaderElement elt : ccHdr.getElements()) { log.trace("Response contained NO STORE directive, cache was not suitable");
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) { return false;
log.trace("Response contained NO CACHE directive, cache was not suitable"); }
if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
try {
final int maxage = Integer.parseInt(elt.getValue());
if (validityStrategy.getCurrentAgeSecs(entry, now) > maxage) {
log.trace("Response from cache was NOT suitable due to max age");
return false;
}
} catch (final NumberFormatException ex) {
// err conservatively
log.debug("Response from cache was malformed" + ex.getMessage());
return false; return false;
} }
}
if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elt.getName())) { if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
log.trace("Response contained NO STORE directive, cache was not suitable"); try {
final int maxstale = Integer.parseInt(elt.getValue());
if (validityStrategy.getFreshnessLifetimeSecs(entry) > maxstale) {
log.trace("Response from cache was not suitable due to Max stale freshness");
return false;
}
} catch (final NumberFormatException ex) {
// err conservatively
log.debug("Response from cache was malformed: " + ex.getMessage());
return false; return false;
} }
}
if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) { if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
try { try {
final int maxage = Integer.parseInt(elt.getValue()); final long minfresh = Long.parseLong(elt.getValue());
if (validityStrategy.getCurrentAgeSecs(entry, now) > maxage) { if (minfresh < 0L) {
log.trace("Response from cache was NOT suitable due to max age");
return false;
}
} catch (final NumberFormatException ex) {
// err conservatively
log.debug("Response from cache was malformed" + ex.getMessage());
return false; return false;
} }
} final long age = validityStrategy.getCurrentAgeSecs(entry, now);
final long freshness = validityStrategy.getFreshnessLifetimeSecs(entry);
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) { if (freshness - age < minfresh) {
try { log.trace("Response from cache was not suitable due to min fresh " +
final int maxstale = Integer.parseInt(elt.getValue()); "freshness requirement");
if (validityStrategy.getFreshnessLifetimeSecs(entry) > maxstale) {
log.trace("Response from cache was not suitable due to Max stale freshness");
return false;
}
} catch (final NumberFormatException ex) {
// err conservatively
log.debug("Response from cache was malformed: " + ex.getMessage());
return false;
}
}
if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
try {
final long minfresh = Long.parseLong(elt.getValue());
if (minfresh < 0L) {
return false;
}
final long age = validityStrategy.getCurrentAgeSecs(entry, now);
final long freshness = validityStrategy.getFreshnessLifetimeSecs(entry);
if (freshness - age < minfresh) {
log.trace("Response from cache was not suitable due to min fresh " +
"freshness requirement");
return false;
}
} catch (final NumberFormatException ex) {
// err conservatively
log.debug("Response from cache was malformed: " + ex.getMessage());
return false; return false;
} }
} catch (final NumberFormatException ex) {
// err conservatively
log.debug("Response from cache was malformed: " + ex.getMessage());
return false;
} }
} }
} }
@ -239,11 +240,11 @@ class CachedResponseSuitabilityChecker {
} }
private boolean isGet(final HttpRequest request) { private boolean isGet(final HttpRequest request) {
return request.getRequestLine().getMethod().equals(HeaderConstants.GET_METHOD); return request.getMethod().equals(HeaderConstants.GET_METHOD);
} }
private boolean entryIsNotA204Response(final HttpCacheEntry entry) { private boolean entryIsNotA204Response(final HttpCacheEntry entry) {
return entry.getStatusCode() != HttpStatus.SC_NO_CONTENT; return entry.getStatus() != HttpStatus.SC_NO_CONTENT;
} }
private boolean cacheEntryDoesNotContainMethodAndEntity(final HttpCacheEntry entry) { private boolean cacheEntryDoesNotContainMethodAndEntity(final HttpCacheEntry entry) {
@ -313,16 +314,12 @@ class CachedResponseSuitabilityChecker {
private boolean etagValidatorMatches(final HttpRequest request, final HttpCacheEntry entry) { private boolean etagValidatorMatches(final HttpRequest request, final HttpCacheEntry entry) {
final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG); final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
final String etag = (etagHeader != null) ? etagHeader.getValue() : null; final String etag = (etagHeader != null) ? etagHeader.getValue() : null;
final Header[] ifNoneMatch = request.getHeaders(HeaderConstants.IF_NONE_MATCH); final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.IF_NONE_MATCH);
if (ifNoneMatch != null) { while (it.hasNext()) {
for (final Header h : ifNoneMatch) { final HeaderElement elt = it.next();
for (final HeaderElement elt : h.getElements()) { final String reqEtag = elt.toString();
final String reqEtag = elt.toString(); if (("*".equals(reqEtag) && etag != null) || reqEtag.equals(etag)) {
if (("*".equals(reqEtag) && etag != null) return true;
|| reqEtag.equals(etag)) {
return true;
}
}
} }
} }
return false; return false;

View File

@ -27,10 +27,9 @@
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@ -45,13 +44,13 @@ import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheStorage; import org.apache.hc.client5.http.cache.HttpCacheStorage;
import org.apache.hc.client5.http.cache.ResourceFactory; import org.apache.hc.client5.http.cache.ResourceFactory;
import org.apache.hc.client5.http.impl.sync.ClientExecChain; import org.apache.hc.client5.http.impl.sync.ClientExecChain;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.client5.http.utils.URIUtils; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadSafe; import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpException;
@ -62,10 +61,9 @@ import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.RequestLine; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHttpResponse; import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpCoreContext; import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
@ -99,7 +97,7 @@ import org.apache.hc.core5.util.VersionInfo;
* *
* @since 4.3 * @since 4.3
*/ */
@ThreadSafe // So long as the responseCache implementation is threadsafe @Contract(threading = ThreadingBehavior.SAFE) // So long as the responseCache implementation is threadsafe
public class CachingExec implements ClientExecChain { public class CachingExec implements ClientExecChain {
private final static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false; private final static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false;
@ -223,27 +221,23 @@ public class CachingExec implements ClientExecChain {
return cacheUpdates.get(); return cacheUpdates.get();
} }
public CloseableHttpResponse execute( public ClassicHttpResponse execute(final RoutedHttpRequest request) throws IOException, HttpException {
final HttpRoute route, return execute(request, HttpClientContext.create(), null);
final HttpRequestWrapper request) throws IOException, HttpException {
return execute(route, request, HttpClientContext.create(), null);
} }
public CloseableHttpResponse execute( public ClassicHttpResponse execute(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context) throws IOException, HttpException { final HttpClientContext context) throws IOException, HttpException {
return execute(route, request, context, null); return execute(request, context, null);
} }
@Override @Override
public CloseableHttpResponse execute( public ClassicHttpResponse execute(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware) throws IOException, HttpException { final HttpExecutionAware execAware) throws IOException, HttpException {
final HttpHost target = context.getTargetHost(); final HttpHost target = request.getTargetHost();
final String via = generateViaHeader(request.getOriginal()); final String via = generateViaHeader(request.getOriginal());
// default response context // default response context
@ -251,42 +245,41 @@ public class CachingExec implements ClientExecChain {
if (clientRequestsOurOptions(request)) { if (clientRequestsOurOptions(request)) {
setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE); setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
return Proxies.enhanceResponse(new OptionsHttp11Response()); return new OptionsHttp11Response();
} }
final HttpResponse fatalErrorResponse = getFatallyNoncompliantResponse(request, context); final ClassicHttpResponse fatalErrorResponse = getFatallyNoncompliantResponse(request, context);
if (fatalErrorResponse != null) { if (fatalErrorResponse != null) {
return Proxies.enhanceResponse(fatalErrorResponse); return fatalErrorResponse;
} }
requestCompliance.makeRequestCompliant(request); requestCompliance.makeRequestCompliant(request);
request.addHeader("Via",via); request.addHeader("Via",via);
flushEntriesInvalidatedByRequest(context.getTargetHost(), request); flushEntriesInvalidatedByRequest(target, request);
if (!cacheableRequestPolicy.isServableFromCache(request)) { if (!cacheableRequestPolicy.isServableFromCache(request)) {
log.debug("Request is not servable from cache"); log.debug("Request is not servable from cache");
return callBackend(route, request, context, execAware); return callBackend(request, context, execAware);
} }
final HttpCacheEntry entry = satisfyFromCache(target, request); final HttpCacheEntry entry = satisfyFromCache(target, request);
if (entry == null) { if (entry == null) {
log.debug("Cache miss"); log.debug("Cache miss");
return handleCacheMiss(route, request, context, execAware); return handleCacheMiss(request, context, execAware);
} else { } else {
return handleCacheHit(route, request, context, execAware, entry); return handleCacheHit(request, context, execAware, entry);
} }
} }
private CloseableHttpResponse handleCacheHit( private ClassicHttpResponse handleCacheHit(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware, final HttpExecutionAware execAware,
final HttpCacheEntry entry) throws IOException, HttpException { final HttpCacheEntry entry) throws IOException, HttpException {
final HttpHost target = context.getTargetHost(); final HttpHost target = request.getTargetHost();
recordCacheHit(target, request); recordCacheHit(target, request);
CloseableHttpResponse out = null; ClassicHttpResponse out;
final Date now = getCurrentDate(); final Date now = getCurrentDate();
if (suitabilityChecker.canCachedResponseBeUsed(target, request, entry, now)) { if (suitabilityChecker.canCachedResponseBeUsed(target, request, entry, now)) {
log.debug("Cache hit"); log.debug("Cache hit");
@ -294,24 +287,23 @@ public class CachingExec implements ClientExecChain {
} else if (!mayCallBackend(request)) { } else if (!mayCallBackend(request)) {
log.debug("Cache entry not suitable but only-if-cached requested"); log.debug("Cache entry not suitable but only-if-cached requested");
out = generateGatewayTimeout(context); out = generateGatewayTimeout(context);
} else if (!(entry.getStatusCode() == HttpStatus.SC_NOT_MODIFIED } else if (!(entry.getStatus() == HttpStatus.SC_NOT_MODIFIED
&& !suitabilityChecker.isConditional(request))) { && !suitabilityChecker.isConditional(request))) {
log.debug("Revalidating cache entry"); log.debug("Revalidating cache entry");
return revalidateCacheEntry(route, request, context, execAware, entry, now); return revalidateCacheEntry(request, context, execAware, entry, now);
} else { } else {
log.debug("Cache entry not usable; calling backend"); log.debug("Cache entry not usable; calling backend");
return callBackend(route, request, context, execAware); return callBackend(request, context, execAware);
} }
final HttpRoute route = request.getRoute();
context.setAttribute(HttpClientContext.HTTP_ROUTE, route); context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target);
context.setAttribute(HttpCoreContext.HTTP_REQUEST, request); context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
context.setAttribute(HttpCoreContext.HTTP_RESPONSE, out); context.setAttribute(HttpCoreContext.HTTP_RESPONSE, out);
return out; return out;
} }
private CloseableHttpResponse revalidateCacheEntry( private ClassicHttpResponse revalidateCacheEntry(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware, final HttpExecutionAware execAware,
final HttpCacheEntry entry, final HttpCacheEntry entry,
@ -322,41 +314,37 @@ public class CachingExec implements ClientExecChain {
&& !staleResponseNotAllowed(request, entry, now) && !staleResponseNotAllowed(request, entry, now)
&& validityPolicy.mayReturnStaleWhileRevalidating(entry, now)) { && validityPolicy.mayReturnStaleWhileRevalidating(entry, now)) {
log.trace("Serving stale with asynchronous revalidation"); log.trace("Serving stale with asynchronous revalidation");
final CloseableHttpResponse resp = generateCachedResponse(request, context, entry, now); final ClassicHttpResponse resp = generateCachedResponse(request, context, entry, now);
asynchRevalidator.revalidateCacheEntry(this, route, request, context, execAware, entry); asynchRevalidator.revalidateCacheEntry(this, request, context, execAware, entry);
return resp; return resp;
} }
return revalidateCacheEntry(route, request, context, execAware, entry); return revalidateCacheEntry(request, context, execAware, entry);
} catch (final IOException ioex) { } catch (final IOException ioex) {
return handleRevalidationFailure(request, context, entry, now); return handleRevalidationFailure(request, context, entry, now);
} }
} }
private CloseableHttpResponse handleCacheMiss( private ClassicHttpResponse handleCacheMiss(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware) throws IOException, HttpException { final HttpExecutionAware execAware) throws IOException, HttpException {
final HttpHost target = context.getTargetHost(); final HttpHost target = request.getTargetHost();
recordCacheMiss(target, request); recordCacheMiss(target, request);
if (!mayCallBackend(request)) { if (!mayCallBackend(request)) {
return Proxies.enhanceResponse( return new BasicClassicHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
new BasicHttpResponse(
HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"));
} }
final Map<String, Variant> variants = getExistingCacheVariants(target, request); final Map<String, Variant> variants = getExistingCacheVariants(target, request);
if (variants != null && !variants.isEmpty()) { if (variants != null && !variants.isEmpty()) {
return negotiateResponseFromVariants(route, request, context, return negotiateResponseFromVariants(request, context, execAware, variants);
execAware, variants);
} }
return callBackend(route, request, context, execAware); return callBackend(request, context, execAware);
} }
private HttpCacheEntry satisfyFromCache( private HttpCacheEntry satisfyFromCache(
final HttpHost target, final HttpRequestWrapper request) { final HttpHost target, final RoutedHttpRequest request) {
HttpCacheEntry entry = null; HttpCacheEntry entry = null;
try { try {
entry = responseCache.getCacheEntry(target, request); entry = responseCache.getCacheEntry(target, request);
@ -366,10 +354,10 @@ public class CachingExec implements ClientExecChain {
return entry; return entry;
} }
private HttpResponse getFatallyNoncompliantResponse( private ClassicHttpResponse getFatallyNoncompliantResponse(
final HttpRequestWrapper request, final RoutedHttpRequest request,
final HttpContext context) { final HttpContext context) {
HttpResponse fatalErrorResponse = null; ClassicHttpResponse fatalErrorResponse = null;
final List<RequestProtocolError> fatalError = requestCompliance.requestIsFatallyNonCompliant(request); final List<RequestProtocolError> fatalError = requestCompliance.requestIsFatallyNonCompliant(request);
for (final RequestProtocolError error : fatalError) { for (final RequestProtocolError error : fatalError) {
@ -381,7 +369,7 @@ public class CachingExec implements ClientExecChain {
private Map<String, Variant> getExistingCacheVariants( private Map<String, Variant> getExistingCacheVariants(
final HttpHost target, final HttpHost target,
final HttpRequestWrapper request) { final RoutedHttpRequest request) {
Map<String,Variant> variants = null; Map<String,Variant> variants = null;
try { try {
variants = responseCache.getVariantCacheEntriesWithEtags(target, request); variants = responseCache.getVariantCacheEntriesWithEtags(target, request);
@ -391,19 +379,17 @@ public class CachingExec implements ClientExecChain {
return variants; return variants;
} }
private void recordCacheMiss(final HttpHost target, final HttpRequestWrapper request) { private void recordCacheMiss(final HttpHost target, final RoutedHttpRequest request) {
cacheMisses.getAndIncrement(); cacheMisses.getAndIncrement();
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
final RequestLine rl = request.getRequestLine(); log.trace("Cache miss [host: " + target + "; uri: " + request.getRequestUri() + "]");
log.trace("Cache miss [host: " + target + "; uri: " + rl.getUri() + "]");
} }
} }
private void recordCacheHit(final HttpHost target, final HttpRequestWrapper request) { private void recordCacheHit(final HttpHost target, final RoutedHttpRequest request) {
cacheHits.getAndIncrement(); cacheHits.getAndIncrement();
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
final RequestLine rl = request.getRequestLine(); log.trace("Cache hit [host: " + target + "; uri: " + request.getRequestUri() + "]");
log.trace("Cache hit [host: " + target + "; uri: " + rl.getUri() + "]");
} }
} }
@ -414,7 +400,7 @@ public class CachingExec implements ClientExecChain {
private void flushEntriesInvalidatedByRequest( private void flushEntriesInvalidatedByRequest(
final HttpHost target, final HttpHost target,
final HttpRequestWrapper request) { final RoutedHttpRequest request) {
try { try {
responseCache.flushInvalidatedCacheEntriesFor(target, request); responseCache.flushInvalidatedCacheEntriesFor(target, request);
} catch (final IOException ioe) { } catch (final IOException ioe) {
@ -422,9 +408,9 @@ public class CachingExec implements ClientExecChain {
} }
} }
private CloseableHttpResponse generateCachedResponse(final HttpRequestWrapper request, private ClassicHttpResponse generateCachedResponse(final RoutedHttpRequest request,
final HttpContext context, final HttpCacheEntry entry, final Date now) { final HttpContext context, final HttpCacheEntry entry, final Date now) {
final CloseableHttpResponse cachedResponse; final ClassicHttpResponse cachedResponse;
if (request.containsHeader(HeaderConstants.IF_NONE_MATCH) if (request.containsHeader(HeaderConstants.IF_NONE_MATCH)
|| request.containsHeader(HeaderConstants.IF_MODIFIED_SINCE)) { || request.containsHeader(HeaderConstants.IF_MODIFIED_SINCE)) {
cachedResponse = responseGenerator.generateNotModifiedResponse(entry); cachedResponse = responseGenerator.generateNotModifiedResponse(entry);
@ -438,8 +424,8 @@ public class CachingExec implements ClientExecChain {
return cachedResponse; return cachedResponse;
} }
private CloseableHttpResponse handleRevalidationFailure( private ClassicHttpResponse handleRevalidationFailure(
final HttpRequestWrapper request, final RoutedHttpRequest request,
final HttpContext context, final HttpContext context,
final HttpCacheEntry entry, final HttpCacheEntry entry,
final Date now) { final Date now) {
@ -450,26 +436,24 @@ public class CachingExec implements ClientExecChain {
} }
} }
private CloseableHttpResponse generateGatewayTimeout( private ClassicHttpResponse generateGatewayTimeout(
final HttpContext context) { final HttpContext context) {
setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE); setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
return Proxies.enhanceResponse(new BasicHttpResponse( return new BasicClassicHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT,
"Gateway Timeout"));
} }
private CloseableHttpResponse unvalidatedCacheHit( private ClassicHttpResponse unvalidatedCacheHit(
final HttpRequestWrapper request, final RoutedHttpRequest request,
final HttpContext context, final HttpContext context,
final HttpCacheEntry entry) { final HttpCacheEntry entry) {
final CloseableHttpResponse cachedResponse = responseGenerator.generateResponse(request, entry); final ClassicHttpResponse cachedResponse = responseGenerator.generateResponse(request, entry);
setResponseStatus(context, CacheResponseStatus.CACHE_HIT); setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
cachedResponse.addHeader(HeaderConstants.WARNING, "111 localhost \"Revalidation failed\""); cachedResponse.addHeader(HeaderConstants.WARNING, "111 localhost \"Revalidation failed\"");
return cachedResponse; return cachedResponse;
} }
private boolean staleResponseNotAllowed( private boolean staleResponseNotAllowed(
final HttpRequestWrapper request, final RoutedHttpRequest request,
final HttpCacheEntry entry, final HttpCacheEntry entry,
final Date now) { final Date now) {
return validityPolicy.mustRevalidate(entry) return validityPolicy.mustRevalidate(entry)
@ -477,39 +461,39 @@ public class CachingExec implements ClientExecChain {
|| explicitFreshnessRequest(request, entry, now); || explicitFreshnessRequest(request, entry, now);
} }
private boolean mayCallBackend(final HttpRequestWrapper request) { private boolean mayCallBackend(final RoutedHttpRequest request) {
for (final Header h: request.getHeaders(HeaderConstants.CACHE_CONTROL)) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
for (final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if ("only-if-cached".equals(elt.getName())) { final HeaderElement elt = it.next();
log.trace("Request marked only-if-cached"); if ("only-if-cached".equals(elt.getName())) {
return false; log.trace("Request marked only-if-cached");
} return false;
} }
} }
return true; return true;
} }
private boolean explicitFreshnessRequest( private boolean explicitFreshnessRequest(
final HttpRequestWrapper request, final RoutedHttpRequest request,
final HttpCacheEntry entry, final HttpCacheEntry entry,
final Date now) { final Date now) {
for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) { final HeaderElement elt = it.next();
try { if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
final int maxstale = Integer.parseInt(elt.getValue()); try {
final long age = validityPolicy.getCurrentAgeSecs(entry, now); final int maxstale = Integer.parseInt(elt.getValue());
final long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry); final long age = validityPolicy.getCurrentAgeSecs(entry, now);
if (age - lifetime > maxstale) { final long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry);
return true; if (age - lifetime > maxstale) {
}
} catch (final NumberFormatException nfe) {
return true; return true;
} }
} else if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName()) } catch (final NumberFormatException nfe) {
|| HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
return true; return true;
} }
} else if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())
|| HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
return true;
} }
} }
return false; return false;
@ -517,7 +501,7 @@ public class CachingExec implements ClientExecChain {
private String generateViaHeader(final HttpMessage msg) { private String generateViaHeader(final HttpMessage msg) {
final ProtocolVersion pv = msg.getProtocolVersion(); final ProtocolVersion pv = msg.getVersion() != null ? msg.getVersion() : HttpVersion.DEFAULT;
final String existingEntry = viaHeaders.get(pv); final String existingEntry = viaHeaders.get(pv);
if (existingEntry != null) { if (existingEntry != null) {
return existingEntry; return existingEntry;
@ -562,13 +546,11 @@ public class CachingExec implements ClientExecChain {
} }
boolean clientRequestsOurOptions(final HttpRequest request) { boolean clientRequestsOurOptions(final HttpRequest request) {
final RequestLine line = request.getRequestLine(); if (!HeaderConstants.OPTIONS_METHOD.equals(request.getMethod())) {
if (!HeaderConstants.OPTIONS_METHOD.equals(line.getMethod())) {
return false; return false;
} }
if (!"*".equals(line.getUri())) { if (!"*".equals(request.getRequestUri())) {
return false; return false;
} }
@ -579,16 +561,15 @@ public class CachingExec implements ClientExecChain {
return true; return true;
} }
CloseableHttpResponse callBackend( ClassicHttpResponse callBackend(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware) throws IOException, HttpException { final HttpExecutionAware execAware) throws IOException, HttpException {
final Date requestDate = getCurrentDate(); final Date requestDate = getCurrentDate();
log.trace("Calling the backend"); log.trace("Calling the backend");
final CloseableHttpResponse backendResponse = backend.execute(route, request, context, execAware); final ClassicHttpResponse backendResponse = backend.execute(request, context, execAware);
try { try {
backendResponse.addHeader("Via", generateViaHeader(backendResponse)); backendResponse.addHeader("Via", generateViaHeader(backendResponse));
return handleBackendResponse(request, context, requestDate, getCurrentDate(), return handleBackendResponse(request, context, requestDate, getCurrentDate(),
@ -620,24 +601,22 @@ public class CachingExec implements ClientExecChain {
return false; return false;
} }
CloseableHttpResponse negotiateResponseFromVariants( ClassicHttpResponse negotiateResponseFromVariants(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware, final HttpExecutionAware execAware,
final Map<String, Variant> variants) throws IOException, HttpException { final Map<String, Variant> variants) throws IOException, HttpException {
final HttpRequestWrapper conditionalRequest = conditionalRequestBuilder final RoutedHttpRequest conditionalRequest = conditionalRequestBuilder
.buildConditionalRequestFromVariants(request, variants); .buildConditionalRequestFromVariants(request, variants);
final Date requestDate = getCurrentDate(); final Date requestDate = getCurrentDate();
final CloseableHttpResponse backendResponse = backend.execute( final ClassicHttpResponse backendResponse = backend.execute(conditionalRequest, context, execAware);
route, conditionalRequest, context, execAware);
try { try {
final Date responseDate = getCurrentDate(); final Date responseDate = getCurrentDate();
backendResponse.addHeader("Via", generateViaHeader(backendResponse)); backendResponse.addHeader("Via", generateViaHeader(backendResponse));
if (backendResponse.getStatusLine().getStatusCode() != HttpStatus.SC_NOT_MODIFIED) { if (backendResponse.getCode() != HttpStatus.SC_NOT_MODIFIED) {
return handleBackendResponse(request, context, requestDate, responseDate, return handleBackendResponse(request, context, requestDate, responseDate,
backendResponse); backendResponse);
} }
@ -647,7 +626,7 @@ public class CachingExec implements ClientExecChain {
log.warn("304 response did not contain ETag"); log.warn("304 response did not contain ETag");
IOUtils.consume(backendResponse.getEntity()); IOUtils.consume(backendResponse.getEntity());
backendResponse.close(); backendResponse.close();
return callBackend(route, request, context, execAware); return callBackend(request, context, execAware);
} }
final String resultEtag = resultEtagHeader.getValue(); final String resultEtag = resultEtagHeader.getValue();
@ -656,7 +635,7 @@ public class CachingExec implements ClientExecChain {
log.debug("304 response did not contain ETag matching one sent in If-None-Match"); log.debug("304 response did not contain ETag matching one sent in If-None-Match");
IOUtils.consume(backendResponse.getEntity()); IOUtils.consume(backendResponse.getEntity());
backendResponse.close(); backendResponse.close();
return callBackend(route, request, context, execAware); return callBackend(request, context, execAware);
} }
final HttpCacheEntry matchedEntry = matchingVariant.getEntry(); final HttpCacheEntry matchedEntry = matchingVariant.getEntry();
@ -664,18 +643,18 @@ public class CachingExec implements ClientExecChain {
if (revalidationResponseIsTooOld(backendResponse, matchedEntry)) { if (revalidationResponseIsTooOld(backendResponse, matchedEntry)) {
IOUtils.consume(backendResponse.getEntity()); IOUtils.consume(backendResponse.getEntity());
backendResponse.close(); backendResponse.close();
return retryRequestUnconditionally(route, request, context, execAware, matchedEntry); return retryRequestUnconditionally(request, context, execAware);
} }
recordCacheUpdate(context); recordCacheUpdate(context);
final HttpCacheEntry responseEntry = getUpdatedVariantEntry( final HttpCacheEntry responseEntry = getUpdatedVariantEntry(
context.getTargetHost(), conditionalRequest, requestDate, responseDate, request.getTargetHost(), conditionalRequest, requestDate, responseDate,
backendResponse, matchingVariant, matchedEntry); backendResponse, matchingVariant, matchedEntry);
backendResponse.close(); backendResponse.close();
final CloseableHttpResponse resp = responseGenerator.generateResponse(request, responseEntry); final ClassicHttpResponse resp = responseGenerator.generateResponse(request, responseEntry);
tryToUpdateVariantMap(context.getTargetHost(), request, matchingVariant); tryToUpdateVariantMap(request.getTargetHost(), request, matchingVariant);
if (shouldSendNotModifiedResponse(request, responseEntry)) { if (shouldSendNotModifiedResponse(request, responseEntry)) {
return responseGenerator.generateNotModifiedResponse(responseEntry); return responseGenerator.generateNotModifiedResponse(responseEntry);
@ -687,23 +666,20 @@ public class CachingExec implements ClientExecChain {
} }
} }
private CloseableHttpResponse retryRequestUnconditionally( private ClassicHttpResponse retryRequestUnconditionally(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware, final HttpExecutionAware execAware) throws IOException, HttpException {
final HttpCacheEntry matchedEntry) throws IOException, HttpException { final RoutedHttpRequest unconditional = conditionalRequestBuilder.buildUnconditionalRequest(request);
final HttpRequestWrapper unconditional = conditionalRequestBuilder return callBackend(unconditional, context, execAware);
.buildUnconditionalRequest(request, matchedEntry);
return callBackend(route, unconditional, context, execAware);
} }
private HttpCacheEntry getUpdatedVariantEntry( private HttpCacheEntry getUpdatedVariantEntry(
final HttpHost target, final HttpHost target,
final HttpRequestWrapper conditionalRequest, final RoutedHttpRequest conditionalRequest,
final Date requestDate, final Date requestDate,
final Date responseDate, final Date responseDate,
final CloseableHttpResponse backendResponse, final ClassicHttpResponse backendResponse,
final Variant matchingVariant, final Variant matchingVariant,
final HttpCacheEntry matchedEntry) throws IOException { final HttpCacheEntry matchedEntry) throws IOException {
HttpCacheEntry responseEntry = matchedEntry; HttpCacheEntry responseEntry = matchedEntry;
@ -720,7 +696,7 @@ public class CachingExec implements ClientExecChain {
private void tryToUpdateVariantMap( private void tryToUpdateVariantMap(
final HttpHost target, final HttpHost target,
final HttpRequestWrapper request, final RoutedHttpRequest request,
final Variant matchingVariant) { final Variant matchingVariant) {
try { try {
responseCache.reuseVariantEntryFor(target, request, matchingVariant); responseCache.reuseVariantEntryFor(target, request, matchingVariant);
@ -730,53 +706,42 @@ public class CachingExec implements ClientExecChain {
} }
private boolean shouldSendNotModifiedResponse( private boolean shouldSendNotModifiedResponse(
final HttpRequestWrapper request, final RoutedHttpRequest request,
final HttpCacheEntry responseEntry) { final HttpCacheEntry responseEntry) {
return (suitabilityChecker.isConditional(request) return (suitabilityChecker.isConditional(request)
&& suitabilityChecker.allConditionalsMatch(request, responseEntry, new Date())); && suitabilityChecker.allConditionalsMatch(request, responseEntry, new Date()));
} }
CloseableHttpResponse revalidateCacheEntry( ClassicHttpResponse revalidateCacheEntry(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext context, final HttpClientContext context,
final HttpExecutionAware execAware, final HttpExecutionAware execAware,
final HttpCacheEntry cacheEntry) throws IOException, HttpException { final HttpCacheEntry cacheEntry) throws IOException, HttpException {
final HttpRequestWrapper conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry); final RoutedHttpRequest conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
final URI uri = conditionalRequest.getURI();
if (uri != null) {
try {
conditionalRequest.setURI(URIUtils.rewriteURIForRoute(uri, route));
} catch (final URISyntaxException ex) {
throw new ProtocolException("Invalid URI: " + uri, ex);
}
}
Date requestDate = getCurrentDate(); Date requestDate = getCurrentDate();
CloseableHttpResponse backendResponse = backend.execute( ClassicHttpResponse backendResponse = backend.execute(conditionalRequest, context, execAware);
route, conditionalRequest, context, execAware);
Date responseDate = getCurrentDate(); Date responseDate = getCurrentDate();
if (revalidationResponseIsTooOld(backendResponse, cacheEntry)) { if (revalidationResponseIsTooOld(backendResponse, cacheEntry)) {
backendResponse.close(); backendResponse.close();
final HttpRequestWrapper unconditional = conditionalRequestBuilder final RoutedHttpRequest unconditional = conditionalRequestBuilder.buildUnconditionalRequest(request);
.buildUnconditionalRequest(request, cacheEntry);
requestDate = getCurrentDate(); requestDate = getCurrentDate();
backendResponse = backend.execute(route, unconditional, context, execAware); backendResponse = backend.execute(unconditional, context, execAware);
responseDate = getCurrentDate(); responseDate = getCurrentDate();
} }
backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse)); backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse));
final int statusCode = backendResponse.getStatusLine().getStatusCode(); final int statusCode = backendResponse.getCode();
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) { if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
recordCacheUpdate(context); recordCacheUpdate(context);
} }
if (statusCode == HttpStatus.SC_NOT_MODIFIED) { if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
final HttpCacheEntry updatedEntry = responseCache.updateCacheEntry( final HttpCacheEntry updatedEntry = responseCache.updateCacheEntry(
context.getTargetHost(), request, cacheEntry, request.getTargetHost(), request, cacheEntry,
backendResponse, requestDate, responseDate); backendResponse, requestDate, responseDate);
if (suitabilityChecker.isConditional(request) if (suitabilityChecker.isConditional(request)
&& suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) { && suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) {
@ -790,7 +755,7 @@ public class CachingExec implements ClientExecChain {
&& !staleResponseNotAllowed(request, cacheEntry, getCurrentDate()) && !staleResponseNotAllowed(request, cacheEntry, getCurrentDate())
&& validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) { && validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
try { try {
final CloseableHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry); final ClassicHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry);
cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\""); cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
return cachedResponse; return cachedResponse;
} finally { } finally {
@ -808,23 +773,22 @@ public class CachingExec implements ClientExecChain {
|| statusCode == HttpStatus.SC_GATEWAY_TIMEOUT; || statusCode == HttpStatus.SC_GATEWAY_TIMEOUT;
} }
CloseableHttpResponse handleBackendResponse( ClassicHttpResponse handleBackendResponse(
final HttpRequestWrapper request, final RoutedHttpRequest request,
final HttpClientContext context, final HttpClientContext context,
final Date requestDate, final Date requestDate,
final Date responseDate, final Date responseDate,
final CloseableHttpResponse backendResponse) throws IOException { final ClassicHttpResponse backendResponse) throws IOException {
log.trace("Handling Backend response"); log.trace("Handling Backend response");
responseCompliance.ensureProtocolCompliance(request, backendResponse); responseCompliance.ensureProtocolCompliance(request, backendResponse);
final HttpHost target = context.getTargetHost(); final HttpHost target = request.getTargetHost();
final boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse); final boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse);
responseCache.flushInvalidatedCacheEntriesFor(target, request, backendResponse); responseCache.flushInvalidatedCacheEntriesFor(target, request, backendResponse);
if (cacheable && !alreadyHaveNewerCacheEntry(target, request, backendResponse)) { if (cacheable && !alreadyHaveNewerCacheEntry(target, request, backendResponse)) {
storeRequestIfModifiedSinceFor304Response(request, backendResponse); storeRequestIfModifiedSinceFor304Response(request, backendResponse);
return responseCache.cacheAndReturnResponse(target, request, return responseCache.cacheAndReturnResponse(target, request, backendResponse, requestDate, responseDate);
backendResponse, requestDate, responseDate);
} }
if (!cacheable) { if (!cacheable) {
try { try {
@ -846,7 +810,7 @@ public class CachingExec implements ClientExecChain {
*/ */
private void storeRequestIfModifiedSinceFor304Response( private void storeRequestIfModifiedSinceFor304Response(
final HttpRequest request, final HttpResponse backendResponse) { final HttpRequest request, final HttpResponse backendResponse) {
if (backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { if (backendResponse.getCode() == HttpStatus.SC_NOT_MODIFIED) {
final Header h = request.getFirstHeader("If-Modified-Since"); final Header h = request.getFirstHeader("If-Modified-Since");
if (h != null) { if (h != null) {
backendResponse.addHeader("Last-Modified", h.getValue()); backendResponse.addHeader("Last-Modified", h.getValue());
@ -854,7 +818,7 @@ public class CachingExec implements ClientExecChain {
} }
} }
private boolean alreadyHaveNewerCacheEntry(final HttpHost target, final HttpRequestWrapper request, private boolean alreadyHaveNewerCacheEntry(final HttpHost target, final RoutedHttpRequest request,
final HttpResponse backendResponse) { final HttpResponse backendResponse) {
HttpCacheEntry existing = null; HttpCacheEntry existing = null;
try { try {

View File

@ -30,7 +30,8 @@ package org.apache.hc.client5.http.impl.cache;
import java.io.File; import java.io.File;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient; import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Factory methods for {@link CloseableHttpClient} instances * Factory methods for {@link CloseableHttpClient} instances
@ -38,7 +39,7 @@ import org.apache.hc.core5.annotation.Immutable;
* *
* @since 4.3 * @since 4.3
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class CachingHttpClients { public class CachingHttpClients {
private CachingHttpClients() { private CachingHttpClients() {

View File

@ -33,11 +33,9 @@ import java.io.OutputStream;
import java.io.SequenceInputStream; import java.io.SequenceInputStream;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.core5.annotation.NotThreadSafe; import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.entity.AbstractHttpEntity;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
@NotThreadSafe
class CombinedEntity extends AbstractHttpEntity { class CombinedEntity extends AbstractHttpEntity {
private final Resource resource; private final Resource resource;
@ -82,6 +80,11 @@ class CombinedEntity extends AbstractHttpEntity {
} }
} }
@Override
public void close() throws IOException {
dispose();
}
private void dispose() { private void dispose() {
this.resource.dispose(); this.resource.dispose();
} }

View File

@ -26,12 +26,15 @@
*/ */
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.ProtocolException; import org.apache.hc.core5.http.ProtocolException;
@ -39,7 +42,7 @@ import org.apache.hc.core5.http.ProtocolException;
/** /**
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class ConditionalRequestBuilder { class ConditionalRequestBuilder {
/** /**
@ -53,9 +56,9 @@ class ConditionalRequestBuilder {
* @return the wrapped request * @return the wrapped request
* @throws ProtocolException when I am unable to build a new origin request. * @throws ProtocolException when I am unable to build a new origin request.
*/ */
public HttpRequestWrapper buildConditionalRequest(final HttpRequestWrapper request, final HttpCacheEntry cacheEntry) public RoutedHttpRequest buildConditionalRequest(final RoutedHttpRequest request, final HttpCacheEntry cacheEntry)
throws ProtocolException { throws ProtocolException {
final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal(), request.getTarget()); final RoutedHttpRequest newRequest = RoutedHttpRequest.adapt(request.getOriginal(), request.getRoute());
newRequest.setHeaders(request.getAllHeaders()); newRequest.setHeaders(request.getAllHeaders());
final Header eTag = cacheEntry.getFirstHeader(HeaderConstants.ETAG); final Header eTag = cacheEntry.getFirstHeader(HeaderConstants.ETAG);
if (eTag != null) { if (eTag != null) {
@ -66,13 +69,13 @@ class ConditionalRequestBuilder {
newRequest.setHeader(HeaderConstants.IF_MODIFIED_SINCE, lastModified.getValue()); newRequest.setHeader(HeaderConstants.IF_MODIFIED_SINCE, lastModified.getValue());
} }
boolean mustRevalidate = false; boolean mustRevalidate = false;
for(final Header h : cacheEntry.getHeaders(HeaderConstants.CACHE_CONTROL)) { final Iterator<HeaderElement> it = MessageSupport.iterate(cacheEntry, HeaderConstants.CACHE_CONTROL);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if (HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE.equalsIgnoreCase(elt.getName()) final HeaderElement elt = it.next();
if (HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE.equalsIgnoreCase(elt.getName())
|| HeaderConstants.CACHE_CONTROL_PROXY_REVALIDATE.equalsIgnoreCase(elt.getName())) { || HeaderConstants.CACHE_CONTROL_PROXY_REVALIDATE.equalsIgnoreCase(elt.getName())) {
mustRevalidate = true; mustRevalidate = true;
break; break;
}
} }
} }
if (mustRevalidate) { if (mustRevalidate) {
@ -93,9 +96,9 @@ class ConditionalRequestBuilder {
* @param variants * @param variants
* @return the wrapped request * @return the wrapped request
*/ */
public HttpRequestWrapper buildConditionalRequestFromVariants(final HttpRequestWrapper request, public RoutedHttpRequest buildConditionalRequestFromVariants(final RoutedHttpRequest request,
final Map<String, Variant> variants) { final Map<String, Variant> variants) {
final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal(), request.getTarget()); final RoutedHttpRequest newRequest = RoutedHttpRequest.adapt(request.getOriginal(), request.getRoute());
newRequest.setHeaders(request.getAllHeaders()); newRequest.setHeaders(request.getAllHeaders());
// we do not support partial content so all etags are used // we do not support partial content so all etags are used
@ -121,11 +124,10 @@ class ConditionalRequestBuilder {
* our current cache entry. In this case, the protocol recommendation * our current cache entry. In this case, the protocol recommendation
* is to retry the validation and force syncup with the origin. * is to retry the validation and force syncup with the origin.
* @param request client request we are trying to satisfy * @param request client request we are trying to satisfy
* @param entry existing cache entry we are trying to validate
* @return an unconditional validation request * @return an unconditional validation request
*/ */
public HttpRequestWrapper buildUnconditionalRequest(final HttpRequestWrapper request, final HttpCacheEntry entry) { public RoutedHttpRequest buildUnconditionalRequest(final RoutedHttpRequest request) {
final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal(), request.getTarget()); final RoutedHttpRequest newRequest = RoutedHttpRequest.adapt(request.getOriginal(), request.getRoute());
newRequest.setHeaders(request.getAllHeaders()); newRequest.setHeaders(request.getAllHeaders());
newRequest.addHeader(HeaderConstants.CACHE_CONTROL,HeaderConstants.CACHE_CONTROL_NO_CACHE); newRequest.addHeader(HeaderConstants.CACHE_CONTROL,HeaderConstants.CACHE_CONTROL_NO_CACHE);
newRequest.addHeader(HeaderConstants.PRAGMA,HeaderConstants.CACHE_CONTROL_NO_CACHE); newRequest.addHeader(HeaderConstants.PRAGMA,HeaderConstants.CACHE_CONTROL_NO_CACHE);

View File

@ -30,7 +30,8 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import org.apache.hc.core5.annotation.ThreadSafe; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Implements a bounded failure cache. The oldest entries are discarded when * Implements a bounded failure cache. The oldest entries are discarded when
@ -38,7 +39,7 @@ import org.apache.hc.core5.annotation.ThreadSafe;
* *
* @since 4.3 * @since 4.3
*/ */
@ThreadSafe @Contract(threading = ThreadingBehavior.SAFE)
public class DefaultFailureCache implements FailureCache { public class DefaultFailureCache implements FailureCache {
static final int DEFAULT_MAX_SIZE = 1000; static final int DEFAULT_MAX_SIZE = 1000;

View File

@ -35,7 +35,8 @@ import java.io.OutputStream;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheEntrySerializationException; import org.apache.hc.client5.http.cache.HttpCacheEntrySerializationException;
import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer; import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* {@link HttpCacheEntrySerializer} implementation that uses the default (native) * {@link HttpCacheEntrySerializer} implementation that uses the default (native)
@ -45,7 +46,7 @@ import org.apache.hc.core5.annotation.Immutable;
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class DefaultHttpCacheEntrySerializer implements HttpCacheEntrySerializer { public class DefaultHttpCacheEntrySerializer implements HttpCacheEntrySerializer {
@Override @Override

View File

@ -30,7 +30,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.hc.core5.annotation.ThreadSafe; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
/** /**
@ -56,7 +57,7 @@ import org.apache.hc.core5.util.Args;
* *
* @since 4.3 * @since 4.3
*/ */
@ThreadSafe @Contract(threading = ThreadingBehavior.SAFE)
public class ExponentialBackOffSchedulingStrategy implements SchedulingStrategy { public class ExponentialBackOffSchedulingStrategy implements SchedulingStrategy {
public static final long DEFAULT_BACK_OFF_RATE = 10; public static final long DEFAULT_BACK_OFF_RATE = 10;

View File

@ -26,14 +26,15 @@
*/ */
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* The error count with a creation timestamp and its associated key. * The error count with a creation timestamp and its associated key.
* *
* @since 4.3 * @since 4.3
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class FailureCacheValue { public class FailureCacheValue {
private final long creationTimeInNanos; private final long creationTimeInNanos;

View File

@ -32,14 +32,15 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.core5.annotation.ThreadSafe; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Cache resource backed by a file. * Cache resource backed by a file.
* *
* @since 4.1 * @since 4.1
*/ */
@ThreadSafe @Contract(threading = ThreadingBehavior.SAFE)
public class FileResource implements Resource { public class FileResource implements Resource {
private static final long serialVersionUID = 4132244415919043397L; private static final long serialVersionUID = 4132244415919043397L;

View File

@ -34,14 +34,15 @@ import java.io.InputStream;
import org.apache.hc.client5.http.cache.InputLimit; import org.apache.hc.client5.http.cache.InputLimit;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.client5.http.cache.ResourceFactory; import org.apache.hc.client5.http.cache.ResourceFactory;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Generates {@link Resource} instances whose body is stored in a temporary file. * Generates {@link Resource} instances whose body is stored in a temporary file.
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class FileResourceFactory implements ResourceFactory { public class FileResourceFactory implements ResourceFactory {
private final File cacheDir; private final File cacheDir;

View File

@ -30,14 +30,15 @@ import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Cache resource backed by a byte array on the heap. * Cache resource backed by a byte array on the heap.
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class HeapResource implements Resource { public class HeapResource implements Resource {
private static final long serialVersionUID = -2078599905620463394L; private static final long serialVersionUID = -2078599905620463394L;

View File

@ -33,14 +33,15 @@ import java.io.InputStream;
import org.apache.hc.client5.http.cache.InputLimit; import org.apache.hc.client5.http.cache.InputLimit;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.client5.http.cache.ResourceFactory; import org.apache.hc.client5.http.cache.ResourceFactory;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
/** /**
* Generates {@link Resource} instances stored entirely in heap. * Generates {@link Resource} instances stored entirely in heap.
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class HeapResourceFactory implements ResourceFactory { public class HeapResourceFactory implements ResourceFactory {
@Override @Override

View File

@ -31,7 +31,7 @@ import java.util.Date;
import java.util.Map; import java.util.Map;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
@ -99,24 +99,9 @@ interface HttpCache {
* @return the {@link HttpResponse} * @return the {@link HttpResponse}
* @throws IOException * @throws IOException
*/ */
HttpResponse cacheAndReturnResponse( ClassicHttpResponse cacheAndReturnResponse(HttpHost host,
HttpHost host, HttpRequest request, HttpResponse originResponse, HttpRequest request, ClassicHttpResponse originResponse,
Date requestSent, Date responseReceived) Date requestSent, Date responseReceived)
throws IOException;
/**
* Store a {@link HttpResponse} in the cache if possible, and return
* @param host
* @param request
* @param originResponse
* @param requestSent
* @param responseReceived
* @return the {@link HttpResponse}
* @throws IOException
*/
CloseableHttpResponse cacheAndReturnResponse(HttpHost host,
HttpRequest request, CloseableHttpResponse originResponse,
Date requestSent, Date responseReceived)
throws IOException; throws IOException;
/** /**

View File

@ -34,10 +34,11 @@ import java.io.OutputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class IOUtils { class IOUtils {
static void consume(final HttpEntity entity) throws IOException { static void consume(final HttpEntity entity) throws IOException {

View File

@ -31,7 +31,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.hc.core5.annotation.ThreadSafe; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
/** /**
@ -40,7 +41,7 @@ import org.apache.hc.core5.util.Args;
* *
* @since 4.3 * @since 4.3
*/ */
@ThreadSafe @Contract(threading = ThreadingBehavior.SAFE)
public class ImmediateSchedulingStrategy implements SchedulingStrategy { public class ImmediateSchedulingStrategy implements SchedulingStrategy {
private final ExecutorService executor; private final ExecutorService executor;

View File

@ -37,7 +37,8 @@ import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheStorage; import org.apache.hc.client5.http.cache.HttpCacheStorage;
import org.apache.hc.client5.http.cache.HttpCacheUpdateCallback; import org.apache.hc.client5.http.cache.HttpCacheUpdateCallback;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.core5.annotation.ThreadSafe; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
/** /**
@ -70,7 +71,7 @@ import org.apache.hc.core5.util.Args;
* *
* @since 4.1 * @since 4.1
*/ */
@ThreadSafe @Contract(threading = ThreadingBehavior.SAFE)
public class ManagedHttpCacheStorage implements HttpCacheStorage, Closeable { public class ManagedHttpCacheStorage implements HttpCacheStorage, Closeable {
private final CacheMap entries; private final CacheMap entries;

View File

@ -26,73 +26,60 @@
*/ */
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale; import java.util.Locale;
import org.apache.hc.core5.annotation.Immutable; 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.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.StatusLine;
import org.apache.hc.core5.http.message.AbstractHttpMessage;
import org.apache.hc.core5.http.message.BasicStatusLine;
/** /**
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
final class OptionsHttp11Response extends AbstractHttpMessage implements HttpResponse { final class OptionsHttp11Response implements ClassicHttpResponse, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1,
HttpStatus.SC_NOT_IMPLEMENTED, "");
private final ProtocolVersion version = HttpVersion.HTTP_1_1;
@Override
public StatusLine getStatusLine() {
return statusLine;
}
@Override @Override
public int getCode() { public int getCode() {
return statusLine.getStatusCode(); return HttpStatus.SC_NOT_IMPLEMENTED;
} }
@Override @Override
public void setStatusLine(final StatusLine statusline) { public void setCode(final int code) {
// No-op on purpose, this class is not going to be doing any work.
} }
@Override @Override
public void setStatusLine(final ProtocolVersion ver, final int code) { public String getReasonPhrase() {
// No-op on purpose, this class is not going to be doing any work.
}
@Override
public void setStatusLine(final ProtocolVersion ver, final int code, final String reason) {
// No-op on purpose, this class is not going to be doing any work.
}
@Override
public void setStatusCode(final int code) throws IllegalStateException {
// No-op on purpose, this class is not going to be doing any work.
}
@Override
public void setReasonPhrase(final String reason) throws IllegalStateException {
// No-op on purpose, this class is not going to be doing any work.
}
@Override
public HttpEntity getEntity() {
return null; return null;
} }
@Override @Override
public void setEntity(final HttpEntity entity) { public void setVersion(final ProtocolVersion version) {
}
@Override
public int containsHeaders(final String name) {
return 0;
}
@Override
public Header getSingleHeader(final String name) throws ProtocolException {
return null;
}
@Override
public void setReasonPhrase(final String reason) throws IllegalStateException {
// No-op on purpose, this class is not going to be doing any work. // No-op on purpose, this class is not going to be doing any work.
} }
@ -107,33 +94,33 @@ final class OptionsHttp11Response extends AbstractHttpMessage implements HttpRes
} }
@Override @Override
public ProtocolVersion getProtocolVersion() { public ProtocolVersion getVersion() {
return version; return HttpVersion.HTTP_1_1;
} }
@Override @Override
public boolean containsHeader(final String name) { public boolean containsHeader(final String name) {
return super.containsHeader(name); return false;
} }
@Override @Override
public Header[] getHeaders(final String name) { public Header[] getHeaders(final String name) {
return super.getHeaders(name); return null;
} }
@Override @Override
public Header getFirstHeader(final String name) { public Header getFirstHeader(final String name) {
return super.getFirstHeader(name); return null;
} }
@Override @Override
public Header getLastHeader(final String name) { public Header getLastHeader(final String name) {
return super.getLastHeader(name); return null;
} }
@Override @Override
public Header[] getAllHeaders() { public Header[] getAllHeaders() {
return super.getAllHeaders(); return null;
} }
@Override @Override
@ -173,13 +160,25 @@ final class OptionsHttp11Response extends AbstractHttpMessage implements HttpRes
@Override @Override
public Iterator<Header> headerIterator() { public Iterator<Header> headerIterator() {
return super.headerIterator(); return Collections.emptyIterator();
} }
@Override @Override
public Iterator<Header> headerIterator(final String name) { public Iterator<Header> headerIterator(final String name) {
return super.headerIterator(name); return Collections.emptyIterator();
} }
@Override
public HttpEntity getEntity() {
return null;
}
@Override
public void setEntity(final HttpEntity entity) {
}
@Override
public void close() throws IOException {
}
} }

View File

@ -1,56 +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.lang.reflect.Proxy;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.core5.annotation.NotThreadSafe;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.util.Args;
/**
* Proxies for HTTP message objects.
*
* @since 4.3
*/
@NotThreadSafe
class Proxies {
public static CloseableHttpResponse enhanceResponse(final HttpResponse original) {
Args.notNull(original, "HTTP response");
if (original instanceof CloseableHttpResponse) {
return (CloseableHttpResponse) original;
} else {
return (CloseableHttpResponse) Proxy.newProxyInstance(
ResponseProxyHandler.class.getClassLoader(),
new Class<?>[] { CloseableHttpResponse.class },
new ResponseProxyHandler(original));
}
}
}

View File

@ -28,32 +28,34 @@ package org.apache.hc.client5.http.impl.cache;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.ClientProtocolException; import org.apache.hc.client5.http.protocol.ClientProtocolException;
import org.apache.hc.core5.annotation.Immutable; 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.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HeaderElements; import org.apache.hc.core5.http.HeaderElements;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpRequest; 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.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.entity.AbstractHttpEntity; import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpResponse; import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.http.message.BasicStatusLine;
/** /**
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class RequestProtocolCompliance { class RequestProtocolCompliance {
private final boolean weakETagOnPutDeleteAllowed; private final boolean weakETagOnPutDeleteAllowed;
@ -107,7 +109,7 @@ class RequestProtocolCompliance {
* @param request the request to check for compliance * @param request the request to check for compliance
* @throws ClientProtocolException when we have trouble making the request compliant * @throws ClientProtocolException when we have trouble making the request compliant
*/ */
public void makeRequestCompliant(final HttpRequestWrapper request) public void makeRequestCompliant(final RoutedHttpRequest request)
throws ClientProtocolException { throws ClientProtocolException {
if (requestMustNotHaveEntity(request)) { if (requestMustNotHaveEntity(request)) {
@ -119,23 +121,22 @@ class RequestProtocolCompliance {
decrementOPTIONSMaxForwardsIfGreaterThen0(request); decrementOPTIONSMaxForwardsIfGreaterThen0(request);
stripOtherFreshnessDirectivesWithNoCache(request); stripOtherFreshnessDirectivesWithNoCache(request);
if (requestVersionIsTooLow(request) if (requestVersionIsTooLow(request) || requestMinorVersionIsTooHighMajorVersionsMatch(request)) {
|| requestMinorVersionIsTooHighMajorVersionsMatch(request)) { request.setVersion(HttpVersion.HTTP_1_1);
request.setProtocolVersion(HttpVersion.HTTP_1_1);
} }
} }
private void stripOtherFreshnessDirectivesWithNoCache(final HttpRequest request) { private void stripOtherFreshnessDirectivesWithNoCache(final HttpRequest request) {
final List<HeaderElement> outElts = new ArrayList<>(); final List<HeaderElement> outElts = new ArrayList<>();
boolean shouldStrip = false; boolean shouldStrip = false;
for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if (!disallowedWithNoCache.contains(elt.getName())) { final HeaderElement elt = it.next();
outElts.add(elt); if (!disallowedWithNoCache.contains(elt.getName())) {
} outElts.add(elt);
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) { }
shouldStrip = true; if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) {
} shouldStrip = true;
} }
} }
if (!shouldStrip) { if (!shouldStrip) {
@ -160,11 +161,11 @@ class RequestProtocolCompliance {
} }
private boolean requestMustNotHaveEntity(final HttpRequest request) { private boolean requestMustNotHaveEntity(final HttpRequest request) {
return HeaderConstants.TRACE_METHOD.equals(request.getRequestLine().getMethod()); return HeaderConstants.TRACE_METHOD.equals(request.getMethod());
} }
private void decrementOPTIONSMaxForwardsIfGreaterThen0(final HttpRequest request) { private void decrementOPTIONSMaxForwardsIfGreaterThen0(final HttpRequest request) {
if (!HeaderConstants.OPTIONS_METHOD.equals(request.getRequestLine().getMethod())) { if (!HeaderConstants.OPTIONS_METHOD.equals(request.getMethod())) {
return; return;
} }
@ -179,22 +180,22 @@ class RequestProtocolCompliance {
request.setHeader(HeaderConstants.MAX_FORWARDS, Integer.toString(currentMaxForwards - 1)); request.setHeader(HeaderConstants.MAX_FORWARDS, Integer.toString(currentMaxForwards - 1));
} }
private void verifyOPTIONSRequestWithBodyHasContentType(final HttpRequest request) { private void verifyOPTIONSRequestWithBodyHasContentType(final RoutedHttpRequest request) {
if (!HeaderConstants.OPTIONS_METHOD.equals(request.getRequestLine().getMethod())) { if (!HeaderConstants.OPTIONS_METHOD.equals(request.getMethod())) {
return; return;
} }
addContentTypeHeaderIfMissing(request); addContentTypeHeaderIfMissing(request);
} }
private void addContentTypeHeaderIfMissing(final HttpRequest request) { private void addContentTypeHeaderIfMissing(final RoutedHttpRequest request) {
final HttpEntity entity = request.getEntity(); final HttpEntity entity = request.getEntity();
if (entity != null && entity.getContentType() == null) { if (entity != null && entity.getContentType() == null) {
((AbstractHttpEntity) entity).setContentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType()); ((AbstractHttpEntity) entity).setContentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType());
} }
} }
private void verifyRequestWithExpectContinueFlagHas100continueHeader(final HttpRequest request) { private void verifyRequestWithExpectContinueFlagHas100continueHeader(final RoutedHttpRequest request) {
if (request.containsHeader(HttpHeaders.EXPECT) && request.getEntity() != null) { if (request.containsHeader(HttpHeaders.EXPECT) && request.getEntity() != null) {
add100ContinueHeaderIfMissing(request); add100ContinueHeaderIfMissing(request);
} else { } else {
@ -209,7 +210,7 @@ class RequestProtocolCompliance {
List<HeaderElement> expectElementsThatAreNot100Continue = new ArrayList<>(); List<HeaderElement> expectElementsThatAreNot100Continue = new ArrayList<>();
for (final Header h : expectHeaders) { for (final Header h : expectHeaders) {
for (final HeaderElement elt : h.getElements()) { for (final HeaderElement elt : MessageSupport.parse(h)) {
if (!(HeaderElements.CONTINUE.equalsIgnoreCase(elt.getName()))) { if (!(HeaderElements.CONTINUE.equalsIgnoreCase(elt.getName()))) {
expectElementsThatAreNot100Continue.add(elt); expectElementsThatAreNot100Continue.add(elt);
} else { } else {
@ -233,11 +234,11 @@ class RequestProtocolCompliance {
private void add100ContinueHeaderIfMissing(final HttpRequest request) { private void add100ContinueHeaderIfMissing(final HttpRequest request) {
boolean hasHeader = false; boolean hasHeader = false;
for (final Header h : request.getHeaders(HttpHeaders.EXPECT)) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HttpHeaders.EXPECT);
for (final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if (HeaderElements.CONTINUE.equalsIgnoreCase(elt.getName())) { final HeaderElement elt = it.next();
hasHeader = true; if (HeaderElements.CONTINUE.equalsIgnoreCase(elt.getName())) {
} hasHeader = true;
} }
} }
@ -247,7 +248,7 @@ class RequestProtocolCompliance {
} }
protected boolean requestMinorVersionIsTooHighMajorVersionsMatch(final HttpRequest request) { protected boolean requestMinorVersionIsTooHighMajorVersionsMatch(final HttpRequest request) {
final ProtocolVersion requestProtocol = request.getProtocolVersion(); final ProtocolVersion requestProtocol = request.getVersion();
if (requestProtocol.getMajor() != HttpVersion.HTTP_1_1.getMajor()) { if (requestProtocol.getMajor() != HttpVersion.HTTP_1_1.getMajor()) {
return false; return false;
} }
@ -260,7 +261,7 @@ class RequestProtocolCompliance {
} }
protected boolean requestVersionIsTooLow(final HttpRequest request) { protected boolean requestVersionIsTooLow(final HttpRequest request) {
return request.getProtocolVersion().compareToVersion(HttpVersion.HTTP_1_1) < 0; return request.getVersion().compareToVersion(HttpVersion.HTTP_1_1) < 0;
} }
/** /**
@ -268,27 +269,24 @@ class RequestProtocolCompliance {
* that a problem occured. * that a problem occured.
* *
* @param errorCheck What type of error should I get * @param errorCheck What type of error should I get
* @return The {@link HttpResponse} that is the error generated * @return The {@link ClassicHttpResponse} that is the error generated
*/ */
public HttpResponse getErrorForRequest(final RequestProtocolError errorCheck) { public ClassicHttpResponse getErrorForRequest(final RequestProtocolError errorCheck) {
switch (errorCheck) { switch (errorCheck) {
case BODY_BUT_NO_LENGTH_ERROR: case BODY_BUT_NO_LENGTH_ERROR:
return new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, return new BasicClassicHttpResponse(HttpStatus.SC_LENGTH_REQUIRED, "");
HttpStatus.SC_LENGTH_REQUIRED, ""));
case WEAK_ETAG_AND_RANGE_ERROR: case WEAK_ETAG_AND_RANGE_ERROR:
return new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, return new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST,
HttpStatus.SC_BAD_REQUEST, "Weak eTag not compatible with byte range")); "Weak eTag not compatible with byte range");
case WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR: case WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR:
return new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, return new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST,
HttpStatus.SC_BAD_REQUEST, "Weak eTag not compatible with PUT or DELETE requests");
"Weak eTag not compatible with PUT or DELETE requests"));
case NO_CACHE_DIRECTIVE_WITH_FIELD_NAME: case NO_CACHE_DIRECTIVE_WITH_FIELD_NAME:
return new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, return new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST,
HttpStatus.SC_BAD_REQUEST, "No-Cache directive MUST NOT include a field name");
"No-Cache directive MUST NOT include a field name"));
default: default:
throw new IllegalStateException( throw new IllegalStateException(
@ -299,7 +297,7 @@ class RequestProtocolCompliance {
private RequestProtocolError requestHasWeakETagAndRange(final HttpRequest request) { private RequestProtocolError requestHasWeakETagAndRange(final HttpRequest request) {
// TODO: Should these be looking at all the headers marked as Range? // TODO: Should these be looking at all the headers marked as Range?
final String method = request.getRequestLine().getMethod(); final String method = request.getMethod();
if (!(HeaderConstants.GET_METHOD.equals(method))) { if (!(HeaderConstants.GET_METHOD.equals(method))) {
return null; return null;
} }
@ -325,9 +323,8 @@ class RequestProtocolCompliance {
private RequestProtocolError requestHasWeekETagForPUTOrDELETEIfMatch(final HttpRequest request) { private RequestProtocolError requestHasWeekETagForPUTOrDELETEIfMatch(final HttpRequest request) {
// TODO: Should these be looking at all the headers marked as If-Match/If-None-Match? // TODO: Should these be looking at all the headers marked as If-Match/If-None-Match?
final String method = request.getRequestLine().getMethod(); final String method = request.getMethod();
if (!(HeaderConstants.PUT_METHOD.equals(method) || HeaderConstants.DELETE_METHOD if (!(HeaderConstants.PUT_METHOD.equals(method) || HeaderConstants.DELETE_METHOD.equals(method))) {
.equals(method))) {
return null; return null;
} }
@ -353,12 +350,11 @@ class RequestProtocolCompliance {
} }
private RequestProtocolError requestContainsNoCacheDirectiveWithFieldName(final HttpRequest request) { private RequestProtocolError requestContainsNoCacheDirectiveWithFieldName(final HttpRequest request) {
for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(elt.getName()) final HeaderElement elt = it.next();
&& elt.getValue() != null) { if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(elt.getName()) && elt.getValue() != null) {
return RequestProtocolError.NO_CACHE_DIRECTIVE_WITH_FIELD_NAME; return RequestProtocolError.NO_CACHE_DIRECTIVE_WITH_FIELD_NAME;
}
} }
} }
return null; return null;

View File

@ -31,10 +31,11 @@ import java.lang.ref.ReferenceQueue;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class ResourceReference extends PhantomReference<HttpCacheEntry> { class ResourceReference extends PhantomReference<HttpCacheEntry> {
private final Resource resource; private final Resource resource;

View File

@ -29,13 +29,15 @@ package org.apache.hc.client5.http.impl.cache;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
@ -44,13 +46,15 @@ import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.message.MessageSupport;
/** /**
* Determines if an HttpResponse can be cached. * Determines if an HttpResponse can be cached.
* *
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class ResponseCachingPolicy { class ResponseCachingPolicy {
private static final String[] AUTH_CACHEABLE_PARAMS = { private static final String[] AUTH_CACHEABLE_PARAMS = {
@ -111,7 +115,7 @@ class ResponseCachingPolicy {
return false; return false;
} }
final int status = response.getStatusLine().getStatusCode(); final int status = response.getCode();
if (cacheableStatuses.contains(status)) { if (cacheableStatuses.contains(status)) {
// these response codes MAY be cached // these response codes MAY be cached
cacheable = true; cacheable = true;
@ -154,11 +158,11 @@ class ResponseCachingPolicy {
return false; return false;
} }
for (final Header varyHdr : response.getHeaders(HeaderConstants.VARY)) { final Iterator<HeaderElement> it = MessageSupport.iterate(response, HeaderConstants.VARY);
for (final HeaderElement elem : varyHdr.getElements()) { while (it.hasNext()) {
if ("*".equals(elem.getName())) { final HeaderElement elem = it.next();
return false; if ("*".equals(elem.getName())) {
} return false;
} }
} }
@ -189,27 +193,25 @@ class ResponseCachingPolicy {
} }
protected boolean isExplicitlyNonCacheable(final HttpResponse response) { protected boolean isExplicitlyNonCacheable(final HttpResponse response) {
final Header[] cacheControlHeaders = response.getHeaders(HeaderConstants.CACHE_CONTROL); final Iterator<HeaderElement> it = MessageSupport.iterate(response, HeaderConstants.CACHE_CONTROL);
for (final Header header : cacheControlHeaders) { while (it.hasNext()) {
for (final HeaderElement elem : header.getElements()) { final HeaderElement elem = it.next();
if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elem.getName()) if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elem.getName())
|| HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elem.getName()) || HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elem.getName())
|| (sharedCache && HeaderConstants.PRIVATE.equals(elem.getName()))) { || (sharedCache && HeaderConstants.PRIVATE.equals(elem.getName()))) {
return true; return true;
}
} }
} }
return false; return false;
} }
protected boolean hasCacheControlParameterFrom(final HttpMessage msg, final String[] params) { protected boolean hasCacheControlParameterFrom(final HttpMessage msg, final String[] params) {
final Header[] cacheControlHeaders = msg.getHeaders(HeaderConstants.CACHE_CONTROL); final Iterator<HeaderElement> it = MessageSupport.iterate(msg, HeaderConstants.CACHE_CONTROL);
for (final Header header : cacheControlHeaders) { while (it.hasNext()) {
for (final HeaderElement elem : header.getElements()) { final HeaderElement elem = it.next();
for (final String param : params) { for (final String param : params) {
if (param.equalsIgnoreCase(elem.getName())) { if (param.equalsIgnoreCase(elem.getName())) {
return true; return true;
}
} }
} }
} }
@ -247,7 +249,7 @@ class ResponseCachingPolicy {
return false; return false;
} }
if (request.getRequestLine().getUri().contains("?")) { if (request.getRequestUri().contains("?")) {
if (neverCache1_0ResponsesWithQueryString && from1_0Origin(response)) { if (neverCache1_0ResponsesWithQueryString && from1_0Origin(response)) {
log.debug("Response was not cacheable as it had a query string."); log.debug("Response was not cacheable as it had a query string.");
return false; return false;
@ -269,7 +271,7 @@ class ResponseCachingPolicy {
} }
} }
final String method = request.getRequestLine().getMethod(); final String method = request.getMethod();
return isResponseCacheable(method, response); return isResponseCacheable(method, response);
} }
@ -292,22 +294,23 @@ class ResponseCachingPolicy {
} }
private boolean from1_0Origin(final HttpResponse response) { private boolean from1_0Origin(final HttpResponse response) {
final Header via = response.getFirstHeader(HeaderConstants.VIA); final Iterator<HeaderElement> it = MessageSupport.iterate(response, HeaderConstants.VIA);
if (via != null) { while (it.hasNext()) {
for(final HeaderElement elt : via.getElements()) { final HeaderElement elt = it.next();
final String proto = elt.toString().split("\\s")[0]; final String proto = elt.toString().split("\\s")[0];
if (proto.contains("/")) { if (proto.contains("/")) {
return proto.equals("HTTP/1.0"); return proto.equals("HTTP/1.0");
} else { } else {
return proto.equals("1.0"); return proto.equals("1.0");
}
} }
} }
return HttpVersion.HTTP_1_0.equals(response.getProtocolVersion()); final ProtocolVersion version = response.getVersion() != null ? response.getVersion() : HttpVersion.DEFAULT;
return HttpVersion.HTTP_1_0.equals(version);
} }
private boolean requestProtocolGreaterThanAccepted(final HttpRequest req) { private boolean requestProtocolGreaterThanAccepted(final HttpRequest req) {
return req.getProtocolVersion().compareToVersion(HttpVersion.HTTP_1_1) > 0; final ProtocolVersion version = req.getVersion() != null ? req.getVersion() : HttpVersion.DEFAULT;
return version.compareToVersion(HttpVersion.HTTP_1_1) > 0;
} }
} }

View File

@ -32,10 +32,12 @@ import java.util.Date;
import java.util.List; import java.util.List;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.ClientProtocolException; import org.apache.hc.client5.http.protocol.ClientProtocolException;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.annotation.Immutable; 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.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HeaderElements; import org.apache.hc.core5.http.HeaderElements;
@ -45,12 +47,14 @@ import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.MessageSupport;
/** /**
* @since 4.1 * @since 4.1
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
class ResponseProtocolCompliance { class ResponseProtocolCompliance {
private static final String UNEXPECTED_100_CONTINUE = "The incoming request did not contain a " private static final String UNEXPECTED_100_CONTINUE = "The incoming request did not contain a "
@ -66,7 +70,7 @@ class ResponseProtocolCompliance {
* @param response The {@link HttpResponse} from the origin server * @param response The {@link HttpResponse} from the origin server
* @throws IOException Bad things happened * @throws IOException Bad things happened
*/ */
public void ensureProtocolCompliance(final HttpRequestWrapper request, final HttpResponse response) public void ensureProtocolCompliance(final RoutedHttpRequest request, final ClassicHttpResponse response)
throws IOException { throws IOException {
if (backendResponseMustNotHaveBody(request, response)) { if (backendResponseMustNotHaveBody(request, response)) {
consumeBody(response); consumeBody(response);
@ -90,7 +94,7 @@ class ResponseProtocolCompliance {
warningsWithNonMatchingWarnDatesAreRemoved(response); warningsWithNonMatchingWarnDatesAreRemoved(response);
} }
private void consumeBody(final HttpResponse response) throws IOException { private void consumeBody(final ClassicHttpResponse response) throws IOException {
final HttpEntity body = response.getEntity(); final HttpEntity body = response.getEntity();
if (body != null) { if (body != null) {
IOUtils.consume(body); IOUtils.consume(body);
@ -140,7 +144,7 @@ class ResponseProtocolCompliance {
for (final Header h : hdrs) { for (final Header h : hdrs) {
final StringBuilder buf = new StringBuilder(); final StringBuilder buf = new StringBuilder();
boolean first = true; boolean first = true;
for (final HeaderElement elt : h.getElements()) { for (final HeaderElement elt : MessageSupport.parse(h)) {
if ("identity".equalsIgnoreCase(elt.getName())) { if ("identity".equalsIgnoreCase(elt.getName())) {
modified = true; modified = true;
} else { } else {
@ -173,9 +177,9 @@ class ResponseProtocolCompliance {
} }
private void ensurePartialContentIsNotSentToAClientThatDidNotRequestIt(final HttpRequest request, private void ensurePartialContentIsNotSentToAClientThatDidNotRequestIt(final HttpRequest request,
final HttpResponse response) throws IOException { final ClassicHttpResponse response) throws IOException {
if (request.getFirstHeader(HeaderConstants.RANGE) != null if (request.getFirstHeader(HeaderConstants.RANGE) != null
|| response.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT) { || response.getCode() != HttpStatus.SC_PARTIAL_CONTENT) {
return; return;
} }
@ -185,11 +189,11 @@ class ResponseProtocolCompliance {
private void ensure200ForOPTIONSRequestWithNoBodyHasContentLengthZero(final HttpRequest request, private void ensure200ForOPTIONSRequestWithNoBodyHasContentLengthZero(final HttpRequest request,
final HttpResponse response) { final HttpResponse response) {
if (!request.getRequestLine().getMethod().equalsIgnoreCase(HeaderConstants.OPTIONS_METHOD)) { if (!request.getMethod().equalsIgnoreCase(HeaderConstants.OPTIONS_METHOD)) {
return; return;
} }
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { if (response.getCode() != HttpStatus.SC_OK) {
return; return;
} }
@ -203,7 +207,7 @@ class ResponseProtocolCompliance {
"Content-Language", HttpHeaders.CONTENT_LENGTH, "Content-MD5", "Content-Language", HttpHeaders.CONTENT_LENGTH, "Content-MD5",
"Content-Range", HttpHeaders.CONTENT_TYPE, HeaderConstants.LAST_MODIFIED "Content-Range", HttpHeaders.CONTENT_TYPE, HeaderConstants.LAST_MODIFIED
}; };
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { if (response.getCode() == HttpStatus.SC_NOT_MODIFIED) {
for(final String hdr : disallowedEntityHeaders) { for(final String hdr : disallowedEntityHeaders) {
response.removeHeaders(hdr); response.removeHeaders(hdr);
} }
@ -211,15 +215,15 @@ class ResponseProtocolCompliance {
} }
private boolean backendResponseMustNotHaveBody(final HttpRequest request, final HttpResponse backendResponse) { private boolean backendResponseMustNotHaveBody(final HttpRequest request, final HttpResponse backendResponse) {
return HeaderConstants.HEAD_METHOD.equals(request.getRequestLine().getMethod()) return HeaderConstants.HEAD_METHOD.equals(request.getMethod())
|| backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NO_CONTENT || backendResponse.getCode() == HttpStatus.SC_NO_CONTENT
|| backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_RESET_CONTENT || backendResponse.getCode() == HttpStatus.SC_RESET_CONTENT
|| backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED; || backendResponse.getCode() == HttpStatus.SC_NOT_MODIFIED;
} }
private void requestDidNotExpect100ContinueButResponseIsOne(final HttpRequestWrapper request, private void requestDidNotExpect100ContinueButResponseIsOne(final RoutedHttpRequest request,
final HttpResponse response) throws IOException { final ClassicHttpResponse response) throws IOException {
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_CONTINUE) { if (response.getCode() != HttpStatus.SC_CONTINUE) {
return; return;
} }
@ -232,10 +236,11 @@ class ResponseProtocolCompliance {
throw new ClientProtocolException(UNEXPECTED_100_CONTINUE); throw new ClientProtocolException(UNEXPECTED_100_CONTINUE);
} }
private void transferEncodingIsNotReturnedTo1_0Client(final HttpRequestWrapper request, private void transferEncodingIsNotReturnedTo1_0Client(final RoutedHttpRequest request,
final HttpResponse response) { final HttpResponse response) {
final HttpRequest originalRequest = request.getOriginal(); final HttpRequest originalRequest = request.getOriginal();
if (originalRequest.getProtocolVersion().compareToVersion(HttpVersion.HTTP_1_1) >= 0) { final ProtocolVersion version = originalRequest.getVersion() != null ? originalRequest.getVersion() : HttpVersion.DEFAULT;
if (version.compareToVersion(HttpVersion.HTTP_1_1) >= 0) {
return; return;
} }

View File

@ -1,89 +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.Closeable;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.hc.core5.annotation.NotThreadSafe;
import org.apache.hc.core5.http.HttpResponse;
/**
* A proxy class that can enhance an arbitrary {@link HttpResponse} with
* {@link Closeable#close()} method.
*
* @since 4.3
*/
@NotThreadSafe
class ResponseProxyHandler implements InvocationHandler {
private static final Method CLOSE_METHOD;
static {
try {
CLOSE_METHOD = Closeable.class.getMethod("close");
} catch (final NoSuchMethodException ex) {
throw new Error(ex);
}
}
private final HttpResponse original;
ResponseProxyHandler(final HttpResponse original) {
super();
this.original = original;
}
public void close() throws IOException {
IOUtils.consume(original.getEntity());
}
@Override
public Object invoke(
final Object proxy, final Method method, final Object[] args) throws Throwable {
if (method.equals(CLOSE_METHOD)) {
close();
return null;
} else {
try {
return method.invoke(this.original, args);
} catch (final InvocationTargetException ex) {
final Throwable cause = ex.getCause();
if (cause != null) {
throw cause;
} else {
throw ex;
}
}
}
}
}

View File

@ -28,28 +28,24 @@ package org.apache.hc.client5.http.impl.cache;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Proxy;
import org.apache.hc.client5.http.cache.InputLimit; import org.apache.hc.client5.http.cache.InputLimit;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.client5.http.cache.ResourceFactory; import org.apache.hc.client5.http.cache.ResourceFactory;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.annotation.NotThreadSafe;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHttpResponse;
/** /**
* @since 4.1 * @since 4.1
*/ */
@NotThreadSafe
class SizeLimitedResponseReader { class SizeLimitedResponseReader {
private final ResourceFactory resourceFactory; private final ResourceFactory resourceFactory;
private final long maxResponseSizeBytes; private final long maxResponseSizeBytes;
private final HttpRequest request; private final HttpRequest request;
private final CloseableHttpResponse response; private final ClassicHttpResponse response;
private InputStream instream; private InputStream instream;
private InputLimit limit; private InputLimit limit;
@ -57,14 +53,14 @@ class SizeLimitedResponseReader {
private boolean consumed; private boolean consumed;
/** /**
* Create an {@link HttpResponse} that is limited in size, this allows for checking * Create an {@link ClassicHttpResponse} that is limited in size, this allows for checking
* the size of objects that will be stored in the cache. * the size of objects that will be stored in the cache.
*/ */
public SizeLimitedResponseReader( public SizeLimitedResponseReader(
final ResourceFactory resourceFactory, final ResourceFactory resourceFactory,
final long maxResponseSizeBytes, final long maxResponseSizeBytes,
final HttpRequest request, final HttpRequest request,
final CloseableHttpResponse response) { final ClassicHttpResponse response) {
super(); super();
this.resourceFactory = resourceFactory; this.resourceFactory = resourceFactory;
this.maxResponseSizeBytes = maxResponseSizeBytes; this.maxResponseSizeBytes = maxResponseSizeBytes;
@ -100,7 +96,7 @@ class SizeLimitedResponseReader {
if (entity == null) { if (entity == null) {
return; return;
} }
final String uri = request.getRequestLine().getUri(); final String uri = request.getRequestUri();
instream = entity.getContent(); instream = entity.getContent();
try { try {
resource = resourceFactory.generate(uri, instream, limit); resource = resourceFactory.generate(uri, instream, limit);
@ -121,9 +117,19 @@ class SizeLimitedResponseReader {
return resource; return resource;
} }
CloseableHttpResponse getReconstructedResponse() throws IOException { ClassicHttpResponse getReconstructedResponse() throws IOException {
ensureConsumed(); ensureConsumed();
final HttpResponse reconstructed = new BasicHttpResponse(response.getStatusLine()); final ClassicHttpResponse reconstructed = new BasicClassicHttpResponse(response.getCode()) {
@Override
public void close() throws IOException {
try {
super.close();
} finally {
response.close();
}
}
};
reconstructed.setHeaders(response.getAllHeaders()); reconstructed.setHeaders(response.getAllHeaders());
final CombinedEntity combinedEntity = new CombinedEntity(resource, instream); final CombinedEntity combinedEntity = new CombinedEntity(resource, instream);
@ -134,17 +140,7 @@ class SizeLimitedResponseReader {
combinedEntity.setChunked(entity.isChunked()); combinedEntity.setChunked(entity.isChunked());
} }
reconstructed.setEntity(combinedEntity); reconstructed.setEntity(combinedEntity);
return (CloseableHttpResponse) Proxy.newProxyInstance( return reconstructed;
ResponseProxyHandler.class.getClassLoader(),
new Class<?>[] { CloseableHttpResponse.class },
new ResponseProxyHandler(reconstructed) {
@Override
public void close() throws IOException {
response.close();
}
});
} }
} }

View File

@ -42,10 +42,7 @@ import java.util.Map;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.StatusLine;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicStatusLine;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -55,7 +52,6 @@ public class TestHttpCacheEntry {
private Date elevenSecondsAgo; private Date elevenSecondsAgo;
private Date nineSecondsAgo; private Date nineSecondsAgo;
private Resource mockResource; private Resource mockResource;
private StatusLine statusLine;
private HttpCacheEntry entry; private HttpCacheEntry entry;
@Before @Before
@ -63,14 +59,11 @@ public class TestHttpCacheEntry {
now = new Date(); now = new Date();
elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L); elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L);
nineSecondsAgo = new Date(now.getTime() - 9 * 1000L); nineSecondsAgo = new Date(now.getTime() - 9 * 1000L);
statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1,
HttpStatus.SC_OK, "OK");
mockResource = mock(Resource.class); mockResource = mock(Resource.class);
} }
private HttpCacheEntry makeEntry(final Header[] headers) { private HttpCacheEntry makeEntry(final Header[] headers) {
return new HttpCacheEntry(elevenSecondsAgo, nineSecondsAgo, return new HttpCacheEntry(elevenSecondsAgo, nineSecondsAgo, HttpStatus.SC_OK, headers, mockResource);
statusLine, headers, mockResource, HeaderConstants.GET_METHOD);
} }
@Test @Test
@ -147,8 +140,7 @@ public class TestHttpCacheEntry {
@Test @Test
public void mustProvideRequestDate() { public void mustProvideRequestDate() {
try { try {
new HttpCacheEntry(null, new Date(), statusLine, new HttpCacheEntry(null, new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
fail("Should have thrown exception"); fail("Should have thrown exception");
} catch (final IllegalArgumentException expected) { } catch (final IllegalArgumentException expected) {
} }
@ -158,19 +150,7 @@ public class TestHttpCacheEntry {
@Test @Test
public void mustProvideResponseDate() { public void mustProvideResponseDate() {
try { try {
new HttpCacheEntry(new Date(), null, statusLine, new HttpCacheEntry(new Date(), null, HttpStatus.SC_OK, new Header[]{}, mockResource);
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
fail("Should have thrown exception");
} catch (final IllegalArgumentException expected) {
}
}
@SuppressWarnings("unused")
@Test
public void mustProvideStatusLine() {
try {
new HttpCacheEntry(new Date(), new Date(), null,
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
fail("Should have thrown exception"); fail("Should have thrown exception");
} catch (final IllegalArgumentException expected) { } catch (final IllegalArgumentException expected) {
} }
@ -180,62 +160,35 @@ public class TestHttpCacheEntry {
@Test @Test
public void mustProvideResponseHeaders() { public void mustProvideResponseHeaders() {
try { try {
new HttpCacheEntry(new Date(), new Date(), statusLine, new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, null, mockResource);
null, mockResource, HeaderConstants.GET_METHOD);
fail("Should have thrown exception"); fail("Should have thrown exception");
} catch (final IllegalArgumentException expected) { } catch (final IllegalArgumentException expected) {
} }
} }
@Test
public void canRetrieveOriginalStatusLine() {
entry = new HttpCacheEntry(new Date(), new Date(), statusLine,
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
assertSame(statusLine, entry.getStatusLine());
}
@Test
public void protocolVersionComesFromOriginalStatusLine() {
entry = new HttpCacheEntry(new Date(), new Date(), statusLine,
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
assertSame(statusLine.getProtocolVersion(),
entry.getProtocolVersion());
}
@Test
public void reasonPhraseComesFromOriginalStatusLine() {
entry = new HttpCacheEntry(new Date(), new Date(), statusLine,
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
assertSame(statusLine.getReasonPhrase(), entry.getReasonPhrase());
}
@Test @Test
public void statusCodeComesFromOriginalStatusLine() { public void statusCodeComesFromOriginalStatusLine() {
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
new Header[]{}, mockResource, HeaderConstants.GET_METHOD); assertEquals(HttpStatus.SC_OK, entry.getStatus());
assertEquals(statusLine.getStatusCode(), entry.getStatusCode());
} }
@Test @Test
public void canGetOriginalRequestDate() { public void canGetOriginalRequestDate() {
final Date requestDate = new Date(); final Date requestDate = new Date();
entry = new HttpCacheEntry(requestDate, new Date(), statusLine, entry = new HttpCacheEntry(requestDate, new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
assertSame(requestDate, entry.getRequestDate()); assertSame(requestDate, entry.getRequestDate());
} }
@Test @Test
public void canGetOriginalResponseDate() { public void canGetOriginalResponseDate() {
final Date responseDate = new Date(); final Date responseDate = new Date();
entry = new HttpCacheEntry(new Date(), responseDate, statusLine, entry = new HttpCacheEntry(new Date(), responseDate, HttpStatus.SC_OK, new Header[]{}, mockResource);
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
assertSame(responseDate, entry.getResponseDate()); assertSame(responseDate, entry.getResponseDate());
} }
@Test @Test
public void canGetOriginalResource() { public void canGetOriginalResource() {
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
assertSame(mockResource, entry.getResource()); assertSame(mockResource, entry.getResource());
} }
@ -245,8 +198,7 @@ public class TestHttpCacheEntry {
new BasicHeader("Server", "MockServer/1.0"), new BasicHeader("Server", "MockServer/1.0"),
new BasicHeader("Date", DateUtils.formatDate(now)) new BasicHeader("Date", DateUtils.formatDate(now))
}; };
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, headers, mockResource);
headers, mockResource, HeaderConstants.GET_METHOD);
final Header[] result = entry.getAllHeaders(); final Header[] result = entry.getAllHeaders();
assertEquals(headers.length, result.length); assertEquals(headers.length, result.length);
for(int i=0; i<headers.length; i++) { for(int i=0; i<headers.length; i++) {
@ -257,16 +209,15 @@ public class TestHttpCacheEntry {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Test @Test
public void canConstructWithoutVariants() { public void canConstructWithoutVariants() {
new HttpCacheEntry(new Date(), new Date(), statusLine, new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
new Header[]{}, mockResource, HeaderConstants.GET_METHOD);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Test @Test
public void canProvideVariantMap() { public void canProvideVariantMap() {
new HttpCacheEntry(new Date(), new Date(), statusLine, new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
new Header[]{}, mockResource, new Header[]{}, mockResource,
new HashMap<String,String>(), HeaderConstants.GET_METHOD); new HashMap<String,String>());
} }
@Test @Test
@ -274,9 +225,9 @@ public class TestHttpCacheEntry {
final Map<String,String> variantMap = new HashMap<>(); final Map<String,String> variantMap = new HashMap<>();
variantMap.put("A","B"); variantMap.put("A","B");
variantMap.put("C","D"); variantMap.put("C","D");
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
new Header[]{}, mockResource, new Header[]{}, mockResource,
variantMap, HeaderConstants.GET_METHOD); variantMap);
final Map<String,String> result = entry.getVariantMap(); final Map<String,String> result = entry.getVariantMap();
assertEquals(2, result.size()); assertEquals(2, result.size());
assertEquals("B", result.get("A")); assertEquals("B", result.get("A"));
@ -288,9 +239,9 @@ public class TestHttpCacheEntry {
final Map<String,String> variantMap = new HashMap<>(); final Map<String,String> variantMap = new HashMap<>();
variantMap.put("A","B"); variantMap.put("A","B");
variantMap.put("C","D"); variantMap.put("C","D");
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
new Header[]{}, mockResource, new Header[]{}, mockResource,
variantMap, HeaderConstants.GET_METHOD); variantMap);
final Map<String,String> result = entry.getVariantMap(); final Map<String,String> result = entry.getVariantMap();
try { try {
result.remove("A"); result.remove("A");
@ -306,8 +257,8 @@ public class TestHttpCacheEntry {
@Test @Test
public void canConvertToString() { public void canConvertToString() {
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
new Header[]{}, mockResource, HeaderConstants.GET_METHOD); new Header[]{}, mockResource);
assertNotNull(entry.toString()); assertNotNull(entry.toString());
assertFalse("".equals(entry.toString())); assertFalse("".equals(entry.toString()));
} }
@ -315,16 +266,16 @@ public class TestHttpCacheEntry {
@Test @Test
public void testMissingDateHeaderIsIgnored() { public void testMissingDateHeaderIsIgnored() {
final Header[] headers = new Header[] {}; final Header[] headers = new Header[] {};
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
headers, mockResource, HeaderConstants.GET_METHOD); headers, mockResource);
assertNull(entry.getDate()); assertNull(entry.getDate());
} }
@Test @Test
public void testMalformedDateHeaderIsIgnored() { public void testMalformedDateHeaderIsIgnored() {
final Header[] headers = new Header[] { new BasicHeader("Date", "asdf") }; final Header[] headers = new Header[] { new BasicHeader("Date", "asdf") };
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
headers, mockResource, HeaderConstants.GET_METHOD); headers, mockResource);
assertNull(entry.getDate()); assertNull(entry.getDate());
} }
@ -334,8 +285,8 @@ public class TestHttpCacheEntry {
// round down to nearest second to make comparison easier // round down to nearest second to make comparison easier
final Date date = new Date(nowMs - (nowMs % 1000L)); final Date date = new Date(nowMs - (nowMs % 1000L));
final Header[] headers = new Header[] { new BasicHeader("Date", DateUtils.formatDate(date)) }; final Header[] headers = new Header[] { new BasicHeader("Date", DateUtils.formatDate(date)) };
entry = new HttpCacheEntry(new Date(), new Date(), statusLine, entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
headers, mockResource, HeaderConstants.GET_METHOD); headers, mockResource);
final Date dateHeaderValue = entry.getDate(); final Date dateHeaderValue = entry.getDate();
assertNotNull(dateHeaderValue); assertNotNull(dateHeaderValue);
assertEquals(date.getTime(), dateHeaderValue.getTime()); assertEquals(date.getTime(), dateHeaderValue.getTime());

View File

@ -31,16 +31,15 @@ import java.util.HashMap;
import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HttpCacheContext; import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.impl.sync.ClientExecChain; import org.apache.hc.client5.http.impl.sync.ClientExecChain;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.easymock.EasyMock; import org.easymock.EasyMock;
import org.easymock.IExpectationSetters; import org.easymock.IExpectationSetters;
import org.junit.Before; import org.junit.Before;
@ -55,14 +54,14 @@ public abstract class AbstractProtocolTest {
protected HttpEntity body; protected HttpEntity body;
protected ClientExecChain mockBackend; protected ClientExecChain mockBackend;
protected HttpCache mockCache; protected HttpCache mockCache;
protected HttpRequestWrapper request; protected RoutedHttpRequest request;
protected HttpCacheContext context; protected HttpCacheContext context;
protected CloseableHttpResponse originResponse; protected ClassicHttpResponse originResponse;
protected CacheConfig config; protected CacheConfig config;
protected ClientExecChain impl; protected ClientExecChain impl;
protected HttpCache cache; protected HttpCache cache;
public static HttpRequestWrapper eqRequest(final HttpRequestWrapper in) { public static RoutedHttpRequest eqRequest(final RoutedHttpRequest in) {
EasyMock.reportMatcher(new RequestEquivalent(in)); EasyMock.reportMatcher(new RequestEquivalent(in));
return null; return null;
} }
@ -72,7 +71,7 @@ public abstract class AbstractProtocolTest {
return null; return null;
} }
public static CloseableHttpResponse eqCloseableResponse(final CloseableHttpResponse in) { public static ClassicHttpResponse eqCloseableResponse(final ClassicHttpResponse in) {
EasyMock.reportMatcher(new ResponseEquivalent(in)); EasyMock.reportMatcher(new ResponseEquivalent(in));
return null; return null;
} }
@ -85,12 +84,11 @@ public abstract class AbstractProtocolTest {
body = HttpTestUtils.makeBody(entityLength); body = HttpTestUtils.makeBody(entityLength);
request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1), host); request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("GET", "/foo"), route);
context = HttpCacheContext.create(); context = HttpCacheContext.create();
context.setTargetHost(host);
originResponse = Proxies.enhanceResponse(HttpTestUtils.make200Response()); originResponse = HttpTestUtils.make200Response();
config = CacheConfig.custom() config = CacheConfig.custom()
.setMaxCacheEntries(MAX_ENTRIES) .setMaxCacheEntries(MAX_ENTRIES)
@ -122,23 +120,21 @@ public abstract class AbstractProtocolTest {
EasyMock.verify(mockCache); EasyMock.verify(mockCache);
} }
protected IExpectationSetters<CloseableHttpResponse> backendExpectsAnyRequest() throws Exception { protected IExpectationSetters<ClassicHttpResponse> backendExpectsAnyRequest() throws Exception {
final CloseableHttpResponse resp = mockBackend.execute( final ClassicHttpResponse resp = mockBackend.execute(
EasyMock.isA(HttpRoute.class), EasyMock.isA(RoutedHttpRequest.class),
EasyMock.isA(HttpRequestWrapper.class),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull()); EasyMock.<HttpExecutionAware>isNull());
return EasyMock.expect(resp); return EasyMock.expect(resp);
} }
protected IExpectationSetters<CloseableHttpResponse> backendExpectsAnyRequestAndReturn( protected IExpectationSetters<ClassicHttpResponse> backendExpectsAnyRequestAndReturn(
final HttpResponse reponse) throws Exception { final ClassicHttpResponse response) throws Exception {
final CloseableHttpResponse resp = mockBackend.execute( final ClassicHttpResponse resp = mockBackend.execute(
EasyMock.isA(HttpRoute.class), EasyMock.isA(RoutedHttpRequest.class),
EasyMock.isA(HttpRequestWrapper.class),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull()); EasyMock.<HttpExecutionAware>isNull());
return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(reponse)); return EasyMock.expect(resp).andReturn(response);
} }
protected void emptyMockCacheExpectsNoPuts() throws Exception { protected void emptyMockCacheExpectsNoPuts() throws Exception {

View File

@ -28,26 +28,24 @@ package org.apache.hc.client5.http.impl.cache;
import java.io.IOException; import java.io.IOException;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.impl.sync.ClientExecChain; import org.apache.hc.client5.http.impl.sync.ClientExecChain;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpRequest; 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.HttpStatus;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHttpResponse;
public class DummyBackend implements ClientExecChain { public class DummyBackend implements ClientExecChain {
private HttpRequest request; private ClassicHttpRequest request;
private HttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP",1,1), HttpStatus.SC_OK, "OK"); private ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
private int executions = 0; private int executions = 0;
public void setResponse(final HttpResponse resp) { public void setResponse(final ClassicHttpResponse resp) {
response = resp; response = resp;
} }
@ -56,14 +54,13 @@ public class DummyBackend implements ClientExecChain {
} }
@Override @Override
public CloseableHttpResponse execute( public ClassicHttpResponse execute(
final HttpRoute route, final RoutedHttpRequest request,
final HttpRequestWrapper request,
final HttpClientContext clientContext, final HttpClientContext clientContext,
final HttpExecutionAware execAware) throws IOException, HttpException { final HttpExecutionAware execAware) throws IOException, HttpException {
this.request = request; this.request = request;
executions++; executions++;
return Proxies.enhanceResponse(response); return response;
} }
public int getExecutions() { public int getExecutions() {

View File

@ -29,27 +29,30 @@ package org.apache.hc.client5.http.impl.cache;
import java.io.InputStream; import java.io.InputStream;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
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.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpMessage; import org.apache.hc.core5.http.HttpMessage;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.RequestLine; import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.StatusLine; import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.entity.ByteArrayEntity; 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.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.http.message.BasicHttpResponse; import org.apache.hc.core5.util.LangUtils;
import org.apache.hc.core5.http.message.BasicStatusLine;
import org.junit.Assert; import org.junit.Assert;
public class HttpTestUtils { public class HttpTestUtils {
@ -72,7 +75,7 @@ public class HttpTestUtils {
private static final String[] MULTI_HEADERS = { "Accept", "Accept-Charset", "Accept-Encoding", private static final String[] MULTI_HEADERS = { "Accept", "Accept-Charset", "Accept-Encoding",
"Accept-Language", "Allow", "Cache-Control", "Connection", "Content-Encoding", "Accept-Language", "Allow", "Cache-Control", "Connection", "Content-Encoding",
"Content-Language", "Expect", "Pragma", "Proxy-Authenticate", "TE", "Trailer", "Content-Language", "Expect", "Pragma", "Proxy-Authenticate", "TE", "Trailer",
"Transfer-Encoding", "Upgrade", "Via", "Warning", "WWW-Authenticate" }; "Transfer-Encoding", "Upgrade", "Via", HttpHeaders.WARNING, "WWW-Authenticate" };
private static final String[] SINGLE_HEADERS = { "Accept-Ranges", "Age", "Authorization", private static final String[] SINGLE_HEADERS = { "Accept-Ranges", "Age", "Authorization",
"Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type", "Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type",
"Date", "ETag", "Expires", "From", "Host", "If-Match", "If-Modified-Since", "Date", "ETag", "Expires", "From", "Host", "If-Match", "If-Modified-Since",
@ -150,32 +153,6 @@ public class HttpTestUtils {
return (-1 == i2.read()); return (-1 == i2.read());
} }
/*
* Assert.asserts that the components of two status lines match in a way
* that differs only by hop-by-hop information. "2.1 Proxy Behavior ...We
* remind the reader that HTTP version numbers are hop-by-hop components of
* HTTP meesages, and are not end-to-end."
*
* @see http://www.ietf.org/rfc/rfc2145.txt
*/
public static boolean semanticallyTransparent(final StatusLine l1, final StatusLine l2) {
return (l1.getReasonPhrase().equals(l2.getReasonPhrase()) && l1.getStatusCode() == l2
.getStatusCode());
}
/* Assert.asserts that the components of two status lines match. */
public static boolean equivalent(final StatusLine l1, final StatusLine l2) {
return (l1.getProtocolVersion().equals(l2.getProtocolVersion()) && semanticallyTransparent(
l1, l2));
}
/* Assert.asserts that the components of two request lines match. */
public static boolean equivalent(final RequestLine l1, final RequestLine l2) {
return (l1.getMethod().equals(l2.getMethod())
&& l1.getProtocolVersion().equals(l2.getProtocolVersion()) && l1.getUri().equals(
l2.getUri()));
}
/* /*
* Retrieves the full header value by combining multiple headers and * Retrieves the full header value by combining multiple headers and
* separating with commas, canonicalizing whitespace along the way. * separating with commas, canonicalizing whitespace along the way.
@ -225,31 +202,39 @@ public class HttpTestUtils {
* *
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html#sec1.3 * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html#sec1.3
*/ */
public static boolean semanticallyTransparent(final HttpResponse r1, final HttpResponse r2) public static boolean semanticallyTransparent(
throws Exception { final ClassicHttpResponse r1, final ClassicHttpResponse r2) throws Exception {
final boolean entitiesEquivalent = equivalent(r1.getEntity(), r2.getEntity()); final boolean entitiesEquivalent = equivalent(r1.getEntity(), r2.getEntity());
if (!entitiesEquivalent) { if (!entitiesEquivalent) {
return false; return false;
} }
final boolean statusLinesEquivalent = semanticallyTransparent(r1.getStatusLine(), r2.getStatusLine()); final boolean statusLinesEquivalent = LangUtils.equals(r1.getReasonPhrase(), r2.getReasonPhrase())
&& r1.getCode() == r2.getCode();
if (!statusLinesEquivalent) { if (!statusLinesEquivalent) {
return false; return false;
} }
final boolean e2eHeadersEquivalentSubset = isEndToEndHeaderSubset( return isEndToEndHeaderSubset(r1, r2);
r1, r2); }
return e2eHeadersEquivalentSubset;
/* Assert.asserts that protocol versions equivalent. */
public static boolean equivalent(final ProtocolVersion v1, final ProtocolVersion v2) {
return LangUtils.equals(v1 != null ? v1 : HttpVersion.DEFAULT, v2 != null ? v2 : HttpVersion.DEFAULT );
} }
/* Assert.asserts that two requests are morally equivalent. */ /* Assert.asserts that two requests are morally equivalent. */
public static boolean equivalent(final HttpRequest r1, final HttpRequest r2) { public static boolean equivalent(final HttpRequest r1, final HttpRequest r2) {
return (equivalent(r1.getRequestLine(), r2.getRequestLine()) && isEndToEndHeaderSubset(r1, return equivalent(r1.getVersion(), r2.getVersion()) &&
r2)); LangUtils.equals(r1.getMethod(), r2.getMethod()) &&
LangUtils.equals(r1.getRequestUri(), r2.getRequestUri()) &&
isEndToEndHeaderSubset(r1, r2);
} }
/* Assert.asserts that two requests are morally equivalent. */ /* Assert.asserts that two requests are morally equivalent. */
public static boolean equivalent(final HttpResponse r1, final HttpResponse r2) { public static boolean equivalent(final HttpResponse r1, final HttpResponse r2) {
return (equivalent(r1.getStatusLine(), r2.getStatusLine()) && isEndToEndHeaderSubset(r1, return equivalent(r1.getVersion(), r2.getVersion()) &&
r2)); r1.getCode() == r2.getCode() &&
LangUtils.equals(r1.getReasonPhrase(), r2.getReasonPhrase()) &&
isEndToEndHeaderSubset(r1, r2);
} }
public static byte[] getRandomBytes(final int nbytes) { public static byte[] getRandomBytes(final int nbytes) {
@ -301,7 +286,7 @@ public class HttpTestUtils {
public static HttpCacheEntry makeCacheEntry(final Date requestDate, public static HttpCacheEntry makeCacheEntry(final Date requestDate,
final Date responseDate, final Header[] headers, final byte[] bytes, final Date responseDate, final Header[] headers, final byte[] bytes,
final Map<String,String> variantMap) { final Map<String,String> variantMap) {
return new HttpCacheEntry(requestDate, responseDate, makeStatusLine(), headers, new HeapResource(bytes), variantMap, HeaderConstants.GET_METHOD); return new HttpCacheEntry(requestDate, responseDate, HttpStatus.SC_OK, headers, new HeapResource(bytes), variantMap);
} }
public static HttpCacheEntry makeCacheEntry(final Header[] headers, final byte[] bytes) { public static HttpCacheEntry makeCacheEntry(final Header[] headers, final byte[] bytes) {
@ -324,39 +309,31 @@ public class HttpTestUtils {
public static HttpCacheEntry makeCacheEntryWithNoRequestMethodOrEntity(final Header[] headers) { public static HttpCacheEntry makeCacheEntryWithNoRequestMethodOrEntity(final Header[] headers) {
final Date now = new Date(); final Date now = new Date();
return new HttpCacheEntry(now, now, makeStatusLine(), headers, null, null, null); return new HttpCacheEntry(now, now, HttpStatus.SC_OK, headers, null, null);
} }
public static HttpCacheEntry makeCacheEntryWithNoRequestMethod(final Header[] headers) { public static HttpCacheEntry makeCacheEntryWithNoRequestMethod(final Header[] headers) {
final Date now = new Date(); final Date now = new Date();
return new HttpCacheEntry(now, now, makeStatusLine(), headers, new HeapResource(getRandomBytes(128)), null, null); return new HttpCacheEntry(now, now, HttpStatus.SC_OK, headers, new HeapResource(getRandomBytes(128)), null);
} }
public static HttpCacheEntry make204CacheEntryWithNoRequestMethod(final Header[] headers) { public static HttpCacheEntry make204CacheEntryWithNoRequestMethod(final Header[] headers) {
final Date now = new Date(); final Date now = new Date();
return new HttpCacheEntry(now, now, make204StatusLine(), headers, null, null, HeaderConstants.HEAD_METHOD); return new HttpCacheEntry(now, now, HttpStatus.SC_NO_CONTENT, headers, null, null);
} }
public static HttpCacheEntry makeHeadCacheEntry(final Header[] headers) { public static HttpCacheEntry makeHeadCacheEntry(final Header[] headers) {
final Date now = new Date(); final Date now = new Date();
return new HttpCacheEntry(now, now, makeStatusLine(), headers, null, null, HeaderConstants.HEAD_METHOD); return new HttpCacheEntry(now, now, HttpStatus.SC_OK, headers, null, null);
} }
public static HttpCacheEntry makeHeadCacheEntryWithNoRequestMethod(final Header[] headers) { public static HttpCacheEntry makeHeadCacheEntryWithNoRequestMethod(final Header[] headers) {
final Date now = new Date(); final Date now = new Date();
return new HttpCacheEntry(now, now, makeStatusLine(), headers, null, null, null); return new HttpCacheEntry(now, now, HttpStatus.SC_OK, headers, null, null);
} }
public static StatusLine makeStatusLine() { public static ClassicHttpResponse make200Response() {
return new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse out = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
}
public static StatusLine make204StatusLine() {
return new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "OK");
}
public static HttpResponse make200Response() {
final HttpResponse out = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
out.setHeader("Date", DateUtils.formatDate(new Date())); out.setHeader("Date", DateUtils.formatDate(new Date()));
out.setHeader("Server", "MockOrigin/1.0"); out.setHeader("Server", "MockOrigin/1.0");
out.setHeader("Content-Length", "128"); out.setHeader("Content-Length", "128");
@ -364,39 +341,42 @@ public class HttpTestUtils {
return out; return out;
} }
public static final HttpResponse make200Response(final Date date, final String cacheControl) { public static final ClassicHttpResponse make200Response(final Date date, final String cacheControl) {
final HttpResponse response = HttpTestUtils.make200Response(); final ClassicHttpResponse response = HttpTestUtils.make200Response();
response.setHeader("Date", DateUtils.formatDate(date)); response.setHeader("Date", DateUtils.formatDate(date));
response.setHeader("Cache-Control",cacheControl); response.setHeader("Cache-Control",cacheControl);
response.setHeader("Etag","\"etag\""); response.setHeader("Etag","\"etag\"");
return response; return response;
} }
public static ClassicHttpResponse make304Response() {
return new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not modified");
}
public static final void assert110WarningFound(final HttpResponse response) { public static final void assert110WarningFound(final HttpResponse response) {
boolean found110Warning = false; boolean found110Warning = false;
for(final Header h : response.getHeaders("Warning")) { final Iterator<HeaderElement> it = MessageSupport.iterate(response, HttpHeaders.WARNING);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
final String[] parts = elt.getName().split("\\s"); final HeaderElement elt = it.next();
if ("110".equals(parts[0])) { final String[] parts = elt.getName().split("\\s");
found110Warning = true; if ("110".equals(parts[0])) {
break; found110Warning = true;
} break;
} }
} }
Assert.assertTrue(found110Warning); Assert.assertTrue(found110Warning);
} }
public static HttpRequest makeDefaultRequest() { public static ClassicHttpRequest makeDefaultRequest() {
return new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); return new BasicClassicHttpRequest("GET", "/");
} }
public static HttpRequest makeDefaultHEADRequest() { public static ClassicHttpRequest makeDefaultHEADRequest() {
return new BasicHttpRequest("HEAD","/",HttpVersion.HTTP_1_1); return new BasicClassicHttpRequest("HEAD", "/");
} }
public static HttpResponse make500Response() { public static ClassicHttpResponse make500Response() {
return new BasicHttpResponse(HttpVersion.HTTP_1_1, return new BasicClassicHttpResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
} }
public static Map<String, String> makeDefaultVariantMap(final String key, final String value) { public static Map<String, String> makeDefaultVariantMap(final String key, final String value) {

View File

@ -1,41 +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 org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.message.BasicStatusLine;
public class OKStatus extends BasicStatusLine {
private static final long serialVersionUID = -1639872615816850272L;
public OKStatus() {
super(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
}
}

View File

@ -35,15 +35,14 @@ import java.io.IOException;
import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.ProtocolException; import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.StatusLine;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -55,12 +54,11 @@ public class TestAsynchronousValidationRequest {
private CachingExec mockClient; private CachingExec mockClient;
private HttpHost host; private HttpHost host;
private HttpRoute route; private HttpRoute route;
private HttpRequestWrapper request; private RoutedHttpRequest request;
private HttpClientContext context; private HttpClientContext context;
private HttpExecutionAware mockExecAware; private HttpExecutionAware mockExecAware;
private HttpCacheEntry mockCacheEntry; private HttpCacheEntry mockCacheEntry;
private CloseableHttpResponse mockResponse; private ClassicHttpResponse mockResponse;
private StatusLine mockStatusLine;
@Before @Before
public void setUp() { public void setUp() {
@ -68,12 +66,11 @@ public class TestAsynchronousValidationRequest {
mockClient = mock(CachingExec.class); mockClient = mock(CachingExec.class);
host = new HttpHost("foo.example.com", 80); host = new HttpHost("foo.example.com", 80);
route = new HttpRoute(host); route = new HttpRoute(host);
request = HttpRequestWrapper.wrap(new HttpGet("/"), host); request = RoutedHttpRequest.adapt(new HttpGet("/"), route);
context = HttpClientContext.create(); context = HttpClientContext.create();
mockExecAware = mock(HttpExecutionAware.class); mockExecAware = mock(HttpExecutionAware.class);
mockCacheEntry = mock(HttpCacheEntry.class); mockCacheEntry = mock(HttpCacheEntry.class);
mockResponse = mock(CloseableHttpResponse.class); mockResponse = mock(ClassicHttpResponse.class);
mockStatusLine = mock(StatusLine.class);
} }
@Test @Test
@ -81,20 +78,18 @@ public class TestAsynchronousValidationRequest {
final String identifier = "foo"; final String identifier = "foo";
final AsynchronousValidationRequest impl = new AsynchronousValidationRequest( final AsynchronousValidationRequest impl = new AsynchronousValidationRequest(
mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, mockParent, mockClient, request, context, mockExecAware, mockCacheEntry,
identifier, 0); identifier, 0);
when( when(
mockClient.revalidateCacheEntry( mockClient.revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry)).thenReturn(mockResponse); request, context, mockExecAware, mockCacheEntry)).thenReturn(mockResponse);
when(mockResponse.getStatusLine()).thenReturn(mockStatusLine); when(mockResponse.getCode()).thenReturn(200);
when(mockStatusLine.getStatusCode()).thenReturn(200);
impl.run(); impl.run();
verify(mockClient).revalidateCacheEntry( verify(mockClient).revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry); request, context, mockExecAware, mockCacheEntry);
verify(mockResponse).getStatusLine();
verify(mockParent).markComplete(identifier); verify(mockParent).markComplete(identifier);
verify(mockParent).jobSuccessful(identifier); verify(mockParent).jobSuccessful(identifier);
} }
@ -104,21 +99,18 @@ public class TestAsynchronousValidationRequest {
final String identifier = "foo"; final String identifier = "foo";
final AsynchronousValidationRequest impl = new AsynchronousValidationRequest( final AsynchronousValidationRequest impl = new AsynchronousValidationRequest(
mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, mockParent, mockClient, request, context, mockExecAware, mockCacheEntry,
identifier, 0); identifier, 0);
when( when(
mockClient.revalidateCacheEntry( mockClient.revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry)).thenReturn(mockResponse); request, context, mockExecAware, mockCacheEntry)).thenReturn(mockResponse);
when(mockResponse.getStatusLine()).thenReturn(mockStatusLine); when(mockResponse.getCode()).thenReturn(200);
when(mockStatusLine.getStatusCode()).thenReturn(200);
impl.run(); impl.run();
verify(mockClient).revalidateCacheEntry( verify(mockClient).revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry); request, context, mockExecAware, mockCacheEntry);
verify(mockResponse).getStatusLine();
verify(mockStatusLine).getStatusCode();
verify(mockParent).markComplete(identifier); verify(mockParent).markComplete(identifier);
verify(mockParent).jobSuccessful(identifier); verify(mockParent).jobSuccessful(identifier);
} }
@ -129,22 +121,19 @@ public class TestAsynchronousValidationRequest {
final Header[] warning = new Header[] {new BasicHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"")}; final Header[] warning = new Header[] {new BasicHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"")};
final AsynchronousValidationRequest impl = new AsynchronousValidationRequest( final AsynchronousValidationRequest impl = new AsynchronousValidationRequest(
mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, mockParent, mockClient, request, context, mockExecAware, mockCacheEntry,
identifier, 0); identifier, 0);
when( when(
mockClient.revalidateCacheEntry( mockClient.revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry)).thenReturn(mockResponse); request, context, mockExecAware, mockCacheEntry)).thenReturn(mockResponse);
when(mockResponse.getStatusLine()).thenReturn(mockStatusLine); when(mockResponse.getCode()).thenReturn(200);
when(mockStatusLine.getStatusCode()).thenReturn(200);
when(mockResponse.getHeaders(HeaderConstants.WARNING)).thenReturn(warning); when(mockResponse.getHeaders(HeaderConstants.WARNING)).thenReturn(warning);
impl.run(); impl.run();
verify(mockClient).revalidateCacheEntry( verify(mockClient).revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry); request, context, mockExecAware, mockCacheEntry);
verify(mockResponse).getStatusLine();
verify(mockStatusLine).getStatusCode();
verify(mockResponse).getHeaders(HeaderConstants.WARNING); verify(mockResponse).getHeaders(HeaderConstants.WARNING);
verify(mockParent).markComplete(identifier); verify(mockParent).markComplete(identifier);
verify(mockParent).jobFailed(identifier); verify(mockParent).jobFailed(identifier);
@ -155,18 +144,18 @@ public class TestAsynchronousValidationRequest {
final String identifier = "foo"; final String identifier = "foo";
final AsynchronousValidationRequest impl = new AsynchronousValidationRequest( final AsynchronousValidationRequest impl = new AsynchronousValidationRequest(
mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, mockParent, mockClient, request, context, mockExecAware, mockCacheEntry,
identifier, 0); identifier, 0);
when( when(
mockClient.revalidateCacheEntry( mockClient.revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry)).thenThrow( request, context, mockExecAware, mockCacheEntry)).thenThrow(
new ProtocolException()); new ProtocolException());
impl.run(); impl.run();
verify(mockClient).revalidateCacheEntry( verify(mockClient).revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry); request, context, mockExecAware, mockCacheEntry);
verify(mockParent).markComplete(identifier); verify(mockParent).markComplete(identifier);
verify(mockParent).jobFailed(identifier); verify(mockParent).jobFailed(identifier);
} }
@ -176,18 +165,18 @@ public class TestAsynchronousValidationRequest {
final String identifier = "foo"; final String identifier = "foo";
final AsynchronousValidationRequest impl = new AsynchronousValidationRequest( final AsynchronousValidationRequest impl = new AsynchronousValidationRequest(
mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, mockParent, mockClient, request, context, mockExecAware, mockCacheEntry,
identifier, 0); identifier, 0);
when( when(
mockClient.revalidateCacheEntry( mockClient.revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry)).thenThrow( request, context, mockExecAware, mockCacheEntry)).thenThrow(
new IOException()); new IOException());
impl.run(); impl.run();
verify(mockClient).revalidateCacheEntry( verify(mockClient).revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry); request, context, mockExecAware, mockCacheEntry);
verify(mockParent).markComplete(identifier); verify(mockParent).markComplete(identifier);
verify(mockParent).jobFailed(identifier); verify(mockParent).jobFailed(identifier);
} }
@ -197,18 +186,18 @@ public class TestAsynchronousValidationRequest {
final String identifier = "foo"; final String identifier = "foo";
final AsynchronousValidationRequest impl = new AsynchronousValidationRequest( final AsynchronousValidationRequest impl = new AsynchronousValidationRequest(
mockParent, mockClient, route, request, context, mockExecAware, mockCacheEntry, mockParent, mockClient, request, context, mockExecAware, mockCacheEntry,
identifier, 0); identifier, 0);
when( when(
mockClient.revalidateCacheEntry( mockClient.revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry)).thenThrow( request, context, mockExecAware, mockCacheEntry)).thenThrow(
new RuntimeException()); new RuntimeException());
impl.run(); impl.run();
verify(mockClient).revalidateCacheEntry( verify(mockClient).revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry); request, context, mockExecAware, mockCacheEntry);
verify(mockParent).markComplete(identifier); verify(mockParent).markComplete(identifier);
verify(mockParent).jobFailed(identifier); verify(mockParent).jobFailed(identifier);
} }

View File

@ -42,12 +42,13 @@ import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicHeaderIterator;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -61,7 +62,7 @@ public class TestAsynchronousValidator {
private CachingExec mockClient; private CachingExec mockClient;
private HttpHost host; private HttpHost host;
private HttpRoute route; private HttpRoute route;
private HttpRequestWrapper request; private RoutedHttpRequest request;
private HttpClientContext context; private HttpClientContext context;
private HttpExecutionAware mockExecAware; private HttpExecutionAware mockExecAware;
private HttpCacheEntry mockCacheEntry; private HttpCacheEntry mockCacheEntry;
@ -73,9 +74,8 @@ public class TestAsynchronousValidator {
mockClient = mock(CachingExec.class); mockClient = mock(CachingExec.class);
host = new HttpHost("foo.example.com", 80); host = new HttpHost("foo.example.com", 80);
route = new HttpRoute(host); route = new HttpRoute(host);
request = HttpRequestWrapper.wrap(new HttpGet("/"), host); request = RoutedHttpRequest.adapt(new HttpGet("/"), route);
context = HttpClientContext.create(); context = HttpClientContext.create();
context.setTargetHost(new HttpHost("foo.example.com"));
mockExecAware = mock(HttpExecutionAware.class); mockExecAware = mock(HttpExecutionAware.class);
mockCacheEntry = mock(HttpCacheEntry.class); mockCacheEntry = mock(HttpCacheEntry.class);
mockSchedulingStrategy = mock(SchedulingStrategy.class); mockSchedulingStrategy = mock(SchedulingStrategy.class);
@ -87,7 +87,7 @@ public class TestAsynchronousValidator {
when(mockCacheEntry.hasVariants()).thenReturn(false); when(mockCacheEntry.hasVariants()).thenReturn(false);
impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry); impl.revalidateCacheEntry(mockClient, request, context, mockExecAware, mockCacheEntry);
verify(mockCacheEntry).hasVariants(); verify(mockCacheEntry).hasVariants();
verify(mockSchedulingStrategy).schedule(isA(AsynchronousValidationRequest.class)); verify(mockSchedulingStrategy).schedule(isA(AsynchronousValidationRequest.class));
@ -101,7 +101,7 @@ public class TestAsynchronousValidator {
when(mockCacheEntry.hasVariants()).thenReturn(false); when(mockCacheEntry.hasVariants()).thenReturn(false);
impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry); impl.revalidateCacheEntry(mockClient, request, context, mockExecAware, mockCacheEntry);
final ArgumentCaptor<AsynchronousValidationRequest> cap = ArgumentCaptor.forClass(AsynchronousValidationRequest.class); final ArgumentCaptor<AsynchronousValidationRequest> cap = ArgumentCaptor.forClass(AsynchronousValidationRequest.class);
verify(mockCacheEntry).hasVariants(); verify(mockCacheEntry).hasVariants();
@ -121,7 +121,7 @@ public class TestAsynchronousValidator {
when(mockCacheEntry.hasVariants()).thenReturn(false); when(mockCacheEntry.hasVariants()).thenReturn(false);
doThrow(new RejectedExecutionException()).when(mockSchedulingStrategy).schedule(isA(AsynchronousValidationRequest.class)); doThrow(new RejectedExecutionException()).when(mockSchedulingStrategy).schedule(isA(AsynchronousValidationRequest.class));
impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry); impl.revalidateCacheEntry(mockClient, request, context, mockExecAware, mockCacheEntry);
verify(mockCacheEntry).hasVariants(); verify(mockCacheEntry).hasVariants();
@ -135,8 +135,8 @@ public class TestAsynchronousValidator {
when(mockCacheEntry.hasVariants()).thenReturn(false); when(mockCacheEntry.hasVariants()).thenReturn(false);
impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry); impl.revalidateCacheEntry(mockClient, request, context, mockExecAware, mockCacheEntry);
impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry); impl.revalidateCacheEntry(mockClient, request, context, mockExecAware, mockCacheEntry);
verify(mockCacheEntry, times(2)).hasVariants(); verify(mockCacheEntry, times(2)).hasVariants();
verify(mockSchedulingStrategy).schedule(isA(AsynchronousValidationRequest.class)); verify(mockSchedulingStrategy).schedule(isA(AsynchronousValidationRequest.class));
@ -148,10 +148,10 @@ public class TestAsynchronousValidator {
public void testVariantsBothRevalidated() { public void testVariantsBothRevalidated() {
impl = new AsynchronousValidator(mockSchedulingStrategy); impl = new AsynchronousValidator(mockSchedulingStrategy);
final HttpRequest req1 = new HttpGet("/"); final ClassicHttpRequest req1 = new HttpGet("/");
req1.addHeader(new BasicHeader("Accept-Encoding", "identity")); req1.addHeader(new BasicHeader("Accept-Encoding", "identity"));
final HttpRequest req2 = new HttpGet("/"); final ClassicHttpRequest req2 = new HttpGet("/");
req2.addHeader(new BasicHeader("Accept-Encoding", "gzip")); req2.addHeader(new BasicHeader("Accept-Encoding", "gzip"));
final Header[] variantHeaders = new Header[] { final Header[] variantHeaders = new Header[] {
@ -159,14 +159,15 @@ public class TestAsynchronousValidator {
}; };
when(mockCacheEntry.hasVariants()).thenReturn(true); when(mockCacheEntry.hasVariants()).thenReturn(true);
when(mockCacheEntry.getHeaders(HeaderConstants.VARY)).thenReturn(variantHeaders); when(mockCacheEntry.headerIterator(HeaderConstants.VARY)).thenReturn(
new BasicHeaderIterator(variantHeaders, HeaderConstants.VARY));
mockSchedulingStrategy.schedule(isA(AsynchronousValidationRequest.class)); mockSchedulingStrategy.schedule(isA(AsynchronousValidationRequest.class));
impl.revalidateCacheEntry(mockClient, route, HttpRequestWrapper.wrap(req1, host), context, mockExecAware, mockCacheEntry); impl.revalidateCacheEntry(mockClient, RoutedHttpRequest.adapt(req1, route), context, mockExecAware, mockCacheEntry);
impl.revalidateCacheEntry(mockClient, route, HttpRequestWrapper.wrap(req2, host), context, mockExecAware, mockCacheEntry); impl.revalidateCacheEntry(mockClient, RoutedHttpRequest.adapt(req2, route), context, mockExecAware, mockCacheEntry);
verify(mockCacheEntry, times(2)).hasVariants(); verify(mockCacheEntry, times(2)).hasVariants();
verify(mockCacheEntry, times(2)).getHeaders(HeaderConstants.VARY); verify(mockCacheEntry, times(2)).headerIterator(HeaderConstants.VARY);
verify(mockSchedulingStrategy, times(2)).schedule(isA(AsynchronousValidationRequest.class)); verify(mockSchedulingStrategy, times(2)).schedule(isA(AsynchronousValidationRequest.class));
Assert.assertEquals(2, impl.getScheduledIdentifiers().size()); Assert.assertEquals(2, impl.getScheduledIdentifiers().size());
@ -183,9 +184,9 @@ public class TestAsynchronousValidator {
when(mockCacheEntry.hasVariants()).thenReturn(false); when(mockCacheEntry.hasVariants()).thenReturn(false);
when(mockClient.revalidateCacheEntry( when(mockClient.revalidateCacheEntry(
route, request, context, mockExecAware, mockCacheEntry)).thenReturn(null); request, context, mockExecAware, mockCacheEntry)).thenReturn(null);
impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry); impl.revalidateCacheEntry(mockClient, request, context, mockExecAware, mockCacheEntry);
try { try {
// shut down backend executor and make sure all finishes properly, 1 second should be sufficient // shut down backend executor and make sure all finishes properly, 1 second should be sufficient
@ -195,7 +196,7 @@ public class TestAsynchronousValidator {
} finally { } finally {
verify(mockCacheEntry).hasVariants(); verify(mockCacheEntry).hasVariants();
verify(mockClient).revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry); verify(mockClient).revalidateCacheEntry(request, context, mockExecAware, mockCacheEntry);
Assert.assertEquals(0, impl.getScheduledIdentifiers().size()); Assert.assertEquals(0, impl.getScheduledIdentifiers().size());
} }

View File

@ -51,17 +51,16 @@ import org.apache.hc.client5.http.methods.HttpOptions;
import org.apache.hc.client5.http.methods.HttpPost; import org.apache.hc.client5.http.methods.HttpPost;
import org.apache.hc.client5.http.methods.HttpTrace; import org.apache.hc.client5.http.methods.HttpTrace;
import org.apache.hc.client5.http.utils.DateUtils; 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.Header;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; 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.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.io.entity.BasicHttpEntity;
import org.apache.hc.core5.http.entity.BasicHttpEntity; import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.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.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpResponse;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -81,7 +80,7 @@ public class TestBasicHttpCache {
public void testDoNotFlushCacheEntriesOnGet() throws Exception { public void testDoNotFlushCacheEntriesOnGet() throws Exception {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpGet("/bar"); final HttpRequest req = new HttpGet("/bar");
final String key = (new CacheKeyGenerator()).getURI(host, req); final String key = (new CacheKeyGenerator()).generateKey(host, req);
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
backing.map.put(key, entry); backing.map.put(key, entry);
@ -95,7 +94,7 @@ public class TestBasicHttpCache {
public void testDoNotFlushCacheEntriesOnHead() throws Exception { public void testDoNotFlushCacheEntriesOnHead() throws Exception {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpHead("/bar"); final HttpRequest req = new HttpHead("/bar");
final String key = (new CacheKeyGenerator()).getURI(host, req); final String key = (new CacheKeyGenerator()).generateKey(host, req);
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
backing.map.put(key, entry); backing.map.put(key, entry);
@ -109,7 +108,7 @@ public class TestBasicHttpCache {
public void testDoNotFlushCacheEntriesOnOptions() throws Exception { public void testDoNotFlushCacheEntriesOnOptions() throws Exception {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpOptions("/bar"); final HttpRequest req = new HttpOptions("/bar");
final String key = (new CacheKeyGenerator()).getURI(host, req); final String key = (new CacheKeyGenerator()).generateKey(host, req);
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
backing.map.put(key, entry); backing.map.put(key, entry);
@ -123,7 +122,7 @@ public class TestBasicHttpCache {
public void testDoNotFlushCacheEntriesOnTrace() throws Exception { public void testDoNotFlushCacheEntriesOnTrace() throws Exception {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpTrace("/bar"); final HttpRequest req = new HttpTrace("/bar");
final String key = (new CacheKeyGenerator()).getURI(host, req); final String key = (new CacheKeyGenerator()).generateKey(host, req);
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
backing.map.put(key, entry); backing.map.put(key, entry);
@ -138,10 +137,10 @@ public class TestBasicHttpCache {
throws Exception { throws Exception {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpPost("/foo"); final HttpRequest req = new HttpPost("/foo");
final HttpResponse resp = HttpTestUtils.make200Response(); final ClassicHttpResponse resp = HttpTestUtils.make200Response();
resp.setHeader("Content-Location", "/bar"); resp.setHeader("Content-Location", "/bar");
resp.setHeader(HeaderConstants.ETAG, "\"etag\""); resp.setHeader(HeaderConstants.ETAG, "\"etag\"");
final String key = (new CacheKeyGenerator()).getURI(host, new HttpGet("/bar")); final String key = (new CacheKeyGenerator()).generateKey(host, new HttpGet("/bar"));
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] { final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
new BasicHeader("Date", DateUtils.formatDate(new Date())), new BasicHeader("Date", DateUtils.formatDate(new Date())),
@ -160,9 +159,9 @@ public class TestBasicHttpCache {
throws Exception { throws Exception {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpGet("/foo"); final HttpRequest req = new HttpGet("/foo");
final HttpResponse resp = HttpTestUtils.make200Response(); final ClassicHttpResponse resp = HttpTestUtils.make200Response();
resp.setHeader("Content-Location", "/bar"); resp.setHeader("Content-Location", "/bar");
final String key = (new CacheKeyGenerator()).getURI(host, new HttpGet("/bar")); final String key = (new CacheKeyGenerator()).generateKey(host, new HttpGet("/bar"));
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] { final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
new BasicHeader("Date", DateUtils.formatDate(new Date())), new BasicHeader("Date", DateUtils.formatDate(new Date())),
@ -180,7 +179,7 @@ public class TestBasicHttpCache {
public void testCanFlushCacheEntriesAtUri() throws Exception { public void testCanFlushCacheEntriesAtUri() throws Exception {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpDelete("/bar"); final HttpRequest req = new HttpDelete("/bar");
final String key = (new CacheKeyGenerator()).getURI(host, req); final String key = (new CacheKeyGenerator()).generateKey(host, req);
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
backing.map.put(key, entry); backing.map.put(key, entry);
@ -193,7 +192,7 @@ public class TestBasicHttpCache {
@Test @Test
public void testRecognizesComplete200Response() public void testRecognizesComplete200Response()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
final byte[] bytes = HttpTestUtils.getRandomBytes(128); final byte[] bytes = HttpTestUtils.getRandomBytes(128);
resp.setEntity(new ByteArrayEntity(bytes)); resp.setEntity(new ByteArrayEntity(bytes));
resp.setHeader("Content-Length","128"); resp.setHeader("Content-Length","128");
@ -205,7 +204,7 @@ public class TestBasicHttpCache {
@Test @Test
public void testRecognizesComplete206Response() public void testRecognizesComplete206Response()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
final byte[] bytes = HttpTestUtils.getRandomBytes(128); final byte[] bytes = HttpTestUtils.getRandomBytes(128);
final Resource resource = new HeapResource(bytes); final Resource resource = new HeapResource(bytes);
resp.setEntity(new ByteArrayEntity(bytes)); resp.setEntity(new ByteArrayEntity(bytes));
@ -218,7 +217,7 @@ public class TestBasicHttpCache {
@Test @Test
public void testRecognizesIncomplete200Response() public void testRecognizesIncomplete200Response()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
final byte[] bytes = HttpTestUtils.getRandomBytes(128); final byte[] bytes = HttpTestUtils.getRandomBytes(128);
final Resource resource = new HeapResource(bytes); final Resource resource = new HeapResource(bytes);
resp.setEntity(new ByteArrayEntity(bytes)); resp.setEntity(new ByteArrayEntity(bytes));
@ -230,7 +229,7 @@ public class TestBasicHttpCache {
@Test @Test
public void testIgnoresIncompleteNon200Or206Responses() public void testIgnoresIncompleteNon200Or206Responses()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_FORBIDDEN, "Forbidden"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_FORBIDDEN, "Forbidden");
final byte[] bytes = HttpTestUtils.getRandomBytes(128); final byte[] bytes = HttpTestUtils.getRandomBytes(128);
final Resource resource = new HeapResource(bytes); final Resource resource = new HeapResource(bytes);
resp.setEntity(new ByteArrayEntity(bytes)); resp.setEntity(new ByteArrayEntity(bytes));
@ -242,7 +241,7 @@ public class TestBasicHttpCache {
@Test @Test
public void testResponsesWithoutExplicitContentLengthAreComplete() public void testResponsesWithoutExplicitContentLengthAreComplete()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
final byte[] bytes = HttpTestUtils.getRandomBytes(128); final byte[] bytes = HttpTestUtils.getRandomBytes(128);
final Resource resource = new HeapResource(bytes); final Resource resource = new HeapResource(bytes);
resp.setEntity(new ByteArrayEntity(bytes)); resp.setEntity(new ByteArrayEntity(bytes));
@ -253,7 +252,7 @@ public class TestBasicHttpCache {
@Test @Test
public void testResponsesWithUnparseableContentLengthHeaderAreComplete() public void testResponsesWithUnparseableContentLengthHeaderAreComplete()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
final byte[] bytes = HttpTestUtils.getRandomBytes(128); final byte[] bytes = HttpTestUtils.getRandomBytes(128);
final Resource resource = new HeapResource(bytes); final Resource resource = new HeapResource(bytes);
resp.setHeader("Content-Length","foo"); resp.setHeader("Content-Length","foo");
@ -265,7 +264,7 @@ public class TestBasicHttpCache {
@Test @Test
public void testNullResourcesAreComplete() public void testNullResourcesAreComplete()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
resp.setHeader("Content-Length","256"); resp.setHeader("Content-Length","256");
assertFalse(impl.isIncompleteResponse(resp, null)); assertFalse(impl.isIncompleteResponse(resp, null));
@ -274,13 +273,13 @@ public class TestBasicHttpCache {
@Test @Test
public void testIncompleteResponseErrorProvidesPlainTextErrorMessage() public void testIncompleteResponseErrorProvidesPlainTextErrorMessage()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
final byte[] bytes = HttpTestUtils.getRandomBytes(128); final byte[] bytes = HttpTestUtils.getRandomBytes(128);
final Resource resource = new HeapResource(bytes); final Resource resource = new HeapResource(bytes);
resp.setEntity(new ByteArrayEntity(bytes)); resp.setEntity(new ByteArrayEntity(bytes));
resp.setHeader("Content-Length","256"); resp.setHeader("Content-Length","256");
final HttpResponse result = impl.generateIncompleteResponseError(resp, resource); final ClassicHttpResponse result = impl.generateIncompleteResponseError(resp, resource);
final Header ctype = result.getFirstHeader("Content-Type"); final Header ctype = result.getFirstHeader("Content-Type");
assertEquals("text/plain;charset=UTF-8", ctype.getValue()); assertEquals("text/plain;charset=UTF-8", ctype.getValue());
} }
@ -288,13 +287,13 @@ public class TestBasicHttpCache {
@Test @Test
public void testIncompleteResponseErrorProvidesNonEmptyErrorMessage() public void testIncompleteResponseErrorProvidesNonEmptyErrorMessage()
throws Exception { throws Exception {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
final byte[] bytes = HttpTestUtils.getRandomBytes(128); final byte[] bytes = HttpTestUtils.getRandomBytes(128);
final Resource resource = new HeapResource(bytes); final Resource resource = new HeapResource(bytes);
resp.setEntity(new ByteArrayEntity(bytes)); resp.setEntity(new ByteArrayEntity(bytes));
resp.setHeader("Content-Length","256"); resp.setHeader("Content-Length","256");
final HttpResponse result = impl.generateIncompleteResponseError(resp, resource); final ClassicHttpResponse result = impl.generateIncompleteResponseError(resp, resource);
final int clen = Integer.parseInt(result.getFirstHeader("Content-Length").getValue()); final int clen = Integer.parseInt(result.getFirstHeader("Content-Length").getValue());
assertTrue(clen > 0); assertTrue(clen > 0);
final HttpEntity body = result.getEntity(); final HttpEntity body = result.getEntity();
@ -336,7 +335,7 @@ public class TestBasicHttpCache {
assertFalse(entry.hasVariants()); assertFalse(entry.hasVariants());
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req = new HttpGet("http://foo.example.com/bar"); final HttpRequest req = new HttpGet("http://foo.example.com/bar");
final String key = (new CacheKeyGenerator()).getURI(host, req); final String key = (new CacheKeyGenerator()).generateKey(host, req);
impl.storeInCache(host, req, entry); impl.storeInCache(host, req, entry);
assertSame(entry, backing.map.get(key)); assertSame(entry, backing.map.get(key));
@ -352,13 +351,13 @@ public class TestBasicHttpCache {
final Date responseGenerated = new Date(now.getTime() - 2 * 1000L); final Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
final Date responseReceived = new Date(now.getTime() - 1 * 1000L); final Date responseReceived = new Date(now.getTime() - 1 * 1000L);
final HttpResponse originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES + 1)); originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES + 1));
originResponse.setHeader("Cache-Control","public, max-age=3600"); originResponse.setHeader("Cache-Control","public, max-age=3600");
originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated)); originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
originResponse.setHeader("ETag", "\"etag\""); originResponse.setHeader("ETag", "\"etag\"");
final HttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived); final ClassicHttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
assertEquals(0, backing.map.size()); assertEquals(0, backing.map.size());
assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result));
} }
@ -374,15 +373,15 @@ public class TestBasicHttpCache {
final Date responseGenerated = new Date(now.getTime() - 2 * 1000L); final Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
final Date responseReceived = new Date(now.getTime() - 1 * 1000L); final Date responseReceived = new Date(now.getTime() - 1 * 1000L);
final HttpResponse originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES - 1)); originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES - 1));
originResponse.setHeader("Cache-Control","public, max-age=3600"); originResponse.setHeader("Cache-Control","public, max-age=3600");
originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated)); originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
originResponse.setHeader("ETag", "\"etag\""); originResponse.setHeader("ETag", "\"etag\"");
final HttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived); final ClassicHttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
assertEquals(1, backing.map.size()); assertEquals(1, backing.map.size());
assertTrue(backing.map.containsKey((new CacheKeyGenerator()).getURI(host, request))); assertTrue(backing.map.containsKey((new CacheKeyGenerator()).generateKey(host, request)));
assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result));
} }
@ -401,7 +400,7 @@ public class TestBasicHttpCache {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest request = new HttpGet("http://foo.example.com/bar"); final HttpRequest request = new HttpGet("http://foo.example.com/bar");
final String key = (new CacheKeyGenerator()).getURI(host, request); final String key = (new CacheKeyGenerator()).generateKey(host, request);
backing.map.put(key,entry); backing.map.put(key,entry);
@ -417,7 +416,7 @@ public class TestBasicHttpCache {
final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar"); final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
origRequest.setHeader("Accept-Encoding","gzip"); origRequest.setHeader("Accept-Encoding","gzip");
final HttpResponse origResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse origResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
origResponse.setEntity(HttpTestUtils.makeBody(128)); origResponse.setEntity(HttpTestUtils.makeBody(128));
origResponse.setHeader("Date", DateUtils.formatDate(new Date())); origResponse.setHeader("Date", DateUtils.formatDate(new Date()));
origResponse.setHeader("Cache-Control", "max-age=3600, public"); origResponse.setHeader("Cache-Control", "max-age=3600, public");
@ -439,7 +438,7 @@ public class TestBasicHttpCache {
final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar"); final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
origRequest.setHeader("Accept-Encoding","gzip"); origRequest.setHeader("Accept-Encoding","gzip");
final HttpResponse origResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse origResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
origResponse.setEntity(HttpTestUtils.makeBody(128)); origResponse.setEntity(HttpTestUtils.makeBody(128));
origResponse.setHeader("Date", DateUtils.formatDate(new Date())); origResponse.setHeader("Date", DateUtils.formatDate(new Date()));
origResponse.setHeader("Cache-Control", "max-age=3600, public"); origResponse.setHeader("Cache-Control", "max-age=3600, public");
@ -469,7 +468,7 @@ public class TestBasicHttpCache {
final HttpRequest req1 = new HttpGet("http://foo.example.com/bar"); final HttpRequest req1 = new HttpGet("http://foo.example.com/bar");
req1.setHeader("Accept-Encoding", "gzip"); req1.setHeader("Accept-Encoding", "gzip");
final HttpResponse resp1 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
resp1.setHeader("Date", DateUtils.formatDate(new Date())); resp1.setHeader("Date", DateUtils.formatDate(new Date()));
resp1.setHeader("Cache-Control", "max-age=3600, public"); resp1.setHeader("Cache-Control", "max-age=3600, public");
resp1.setHeader("ETag", "\"etag1\""); resp1.setHeader("ETag", "\"etag1\"");
@ -480,7 +479,7 @@ public class TestBasicHttpCache {
final HttpRequest req2 = new HttpGet("http://foo.example.com/bar"); final HttpRequest req2 = new HttpGet("http://foo.example.com/bar");
req2.setHeader("Accept-Encoding", "identity"); req2.setHeader("Accept-Encoding", "identity");
final HttpResponse resp2 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response();
resp2.setHeader("Date", DateUtils.formatDate(new Date())); resp2.setHeader("Date", DateUtils.formatDate(new Date()));
resp2.setHeader("Cache-Control", "max-age=3600, public"); resp2.setHeader("Cache-Control", "max-age=3600, public");
resp2.setHeader("ETag", "\"etag2\""); resp2.setHeader("ETag", "\"etag2\"");
@ -508,7 +507,7 @@ public class TestBasicHttpCache {
final Date responseGenerated = new Date(now.getTime() - 2 * 1000L); final Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
final Date responseReceived = new Date(now.getTime() - 1 * 1000L); final Date responseReceived = new Date(now.getTime() - 1 * 1000L);
final HttpResponse originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
final BasicHttpEntity entity = new BasicHttpEntity(); final BasicHttpEntity entity = new BasicHttpEntity();
final ConsumableInputStream inputStream = new ConsumableInputStream(new ByteArrayInputStream(HttpTestUtils.getRandomBytes(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES - 1))); final ConsumableInputStream inputStream = new ConsumableInputStream(new ByteArrayInputStream(HttpTestUtils.getRandomBytes(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES - 1)));
entity.setContent(inputStream); entity.setContent(inputStream);
@ -517,7 +516,7 @@ public class TestBasicHttpCache {
originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated)); originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
originResponse.setHeader("ETag", "\"etag\""); originResponse.setHeader("ETag", "\"etag\"");
final HttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived); final ClassicHttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
IOUtils.consume(result.getEntity()); IOUtils.consume(result.getEntity());
assertTrue(inputStream.wasClosed()); assertTrue(inputStream.wasClosed());
} }
@ -577,7 +576,7 @@ public class TestBasicHttpCache {
final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar"); final HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
origRequest.setHeader("Accept-Encoding","gzip"); origRequest.setHeader("Accept-Encoding","gzip");
final HttpResponse origResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse origResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
origResponse.setEntity(HttpTestUtils.makeBody(128)); origResponse.setEntity(HttpTestUtils.makeBody(128));
origResponse.setHeader("Date", DateUtils.formatDate(new Date())); origResponse.setHeader("Date", DateUtils.formatDate(new Date()));
origResponse.setHeader("Cache-Control", "max-age=3600, public"); origResponse.setHeader("Cache-Control", "max-age=3600, public");
@ -585,7 +584,7 @@ public class TestBasicHttpCache {
origResponse.setHeader("Vary", "Accept-Encoding"); origResponse.setHeader("Vary", "Accept-Encoding");
origResponse.setHeader("Content-Encoding","gzip"); origResponse.setHeader("Content-Encoding","gzip");
final HttpResponse response = impl.cacheAndReturnResponse( final ClassicHttpResponse response = impl.cacheAndReturnResponse(
host, origRequest, origResponse, new Date(), new Date()); host, origRequest, origResponse, new Date(), new Date());
final HttpEntity entity = response.getEntity(); final HttpEntity entity = response.getEntity();
Assert.assertNotNull(entity); Assert.assertNotNull(entity);

View File

@ -38,7 +38,6 @@ import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpResponse; import org.apache.hc.core5.http.message.BasicHttpResponse;
import org.junit.Before; import org.junit.Before;
@ -69,8 +68,7 @@ public class TestCacheEntryUpdater {
eightSecondsAgo = new Date(now.getTime() - 8000L); eightSecondsAgo = new Date(now.getTime() - 8000L);
tenSecondsAgo = new Date(now.getTime() - 10000L); tenSecondsAgo = new Date(now.getTime() - 10000L);
response = new BasicHttpResponse(HttpVersion.HTTP_1_1, response = new BasicHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified");
HttpStatus.SC_NOT_MODIFIED, "Not Modified");
impl = new CacheEntryUpdater(); impl = new CacheEntryUpdater();
} }
@ -227,8 +225,7 @@ public class TestCacheEntryUpdater {
@Test @Test
public void cannotUpdateFromANon304OriginResponse() throws Exception { public void cannotUpdateFromANon304OriginResponse() throws Exception {
entry = HttpTestUtils.makeCacheEntry(); entry = HttpTestUtils.makeCacheEntry();
response = new BasicHttpResponse(HttpVersion.HTTP_1_1, response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
HttpStatus.SC_OK, "OK");
try { try {
impl.updateCacheEntry("A", entry, new Date(), new Date(), impl.updateCacheEntry("A", entry, new Date(), new Date(),
response); response);

View File

@ -32,6 +32,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -39,16 +40,15 @@ import java.util.Map;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheStorage; import org.apache.hc.client5.http.cache.HttpCacheStorage;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
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.Header;
import org.apache.hc.core5.http.HttpHost; 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.HttpStatus;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.ProtocolVersion;
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.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.apache.hc.core5.http.message.BasicHttpResponse;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -61,8 +61,8 @@ public class TestCacheInvalidator {
private HttpHost host; private HttpHost host;
private CacheKeyGenerator cacheKeyGenerator; private CacheKeyGenerator cacheKeyGenerator;
private HttpCacheEntry mockEntry; private HttpCacheEntry mockEntry;
private HttpRequest request; private ClassicHttpRequest request;
private HttpResponse response; private ClassicHttpResponse response;
private Date now; private Date now;
private Date tenSecondsAgo; private Date tenSecondsAgo;
@ -85,7 +85,7 @@ public class TestCacheInvalidator {
// Tests // Tests
@Test @Test
public void testInvalidatesRequestsThatArentGETorHEAD() throws Exception { public void testInvalidatesRequestsThatArentGETorHEAD() throws Exception {
request = new BasicHttpRequest("POST","/path", HTTP_1_1); request = new BasicClassicHttpRequest("POST","/path");
final String theUri = "http://foo.example.com:80/path"; final String theUri = "http://foo.example.com:80/path";
final Map<String,String> variantMap = new HashMap<>(); final Map<String,String> variantMap = new HashMap<>();
cacheEntryHasVariantMap(variantMap); cacheEntryHasVariantMap(variantMap);
@ -101,7 +101,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testInvalidatesUrisInContentLocationHeadersOnPUTs() throws Exception { public void testInvalidatesUrisInContentLocationHeadersOnPUTs() throws Exception {
final HttpRequest putRequest = new BasicHttpRequest("PUT","/",HTTP_1_1); final ClassicHttpRequest putRequest = new BasicClassicHttpRequest("PUT","/");
putRequest.setEntity(HttpTestUtils.makeBody(128)); putRequest.setEntity(HttpTestUtils.makeBody(128));
putRequest.setHeader("Content-Length","128"); putRequest.setHeader("Content-Length","128");
@ -123,7 +123,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testInvalidatesUrisInLocationHeadersOnPUTs() throws Exception { public void testInvalidatesUrisInLocationHeadersOnPUTs() throws Exception {
final HttpRequest putRequest = new BasicHttpRequest("PUT","/",HTTP_1_1); final ClassicHttpRequest putRequest = new BasicClassicHttpRequest("PUT","/");
putRequest.setEntity(HttpTestUtils.makeBody(128)); putRequest.setEntity(HttpTestUtils.makeBody(128));
putRequest.setHeader("Content-Length","128"); putRequest.setHeader("Content-Length","128");
@ -140,12 +140,12 @@ public class TestCacheInvalidator {
verify(mockEntry).getVariantMap(); verify(mockEntry).getVariantMap();
verify(mockStorage).getEntry(theUri); verify(mockStorage).getEntry(theUri);
verify(mockStorage).removeEntry(theUri); verify(mockStorage).removeEntry(theUri);
verify(mockStorage).removeEntry(cacheKeyGenerator.canonicalizeUri(contentLocation)); verify(mockStorage).removeEntry(cacheKeyGenerator.generateKey(new URL(contentLocation)));
} }
@Test @Test
public void testInvalidatesRelativeUrisInContentLocationHeadersOnPUTs() throws Exception { public void testInvalidatesRelativeUrisInContentLocationHeadersOnPUTs() throws Exception {
final HttpRequest putRequest = new BasicHttpRequest("PUT","/",HTTP_1_1); final ClassicHttpRequest putRequest = new BasicClassicHttpRequest("PUT","/");
putRequest.setEntity(HttpTestUtils.makeBody(128)); putRequest.setEntity(HttpTestUtils.makeBody(128));
putRequest.setHeader("Content-Length","128"); putRequest.setHeader("Content-Length","128");
@ -167,7 +167,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testDoesNotInvalidateUrisInContentLocationHeadersOnPUTsToDifferentHosts() throws Exception { public void testDoesNotInvalidateUrisInContentLocationHeadersOnPUTsToDifferentHosts() throws Exception {
final HttpRequest putRequest = new BasicHttpRequest("PUT","/",HTTP_1_1); final ClassicHttpRequest putRequest = new BasicClassicHttpRequest("PUT","/");
putRequest.setEntity(HttpTestUtils.makeBody(128)); putRequest.setEntity(HttpTestUtils.makeBody(128));
putRequest.setHeader("Content-Length","128"); putRequest.setHeader("Content-Length","128");
@ -188,7 +188,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testDoesNotInvalidateGETRequest() throws Exception { public void testDoesNotInvalidateGETRequest() throws Exception {
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicClassicHttpRequest("GET","/");
impl.flushInvalidatedCacheEntries(host, request); impl.flushInvalidatedCacheEntries(host, request);
verify(mockStorage).getEntry("http://foo.example.com:80/"); verify(mockStorage).getEntry("http://foo.example.com:80/");
@ -197,7 +197,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testDoesNotInvalidateHEADRequest() throws Exception { public void testDoesNotInvalidateHEADRequest() throws Exception {
request = new BasicHttpRequest("HEAD","/",HTTP_1_1); request = new BasicClassicHttpRequest("HEAD","/");
impl.flushInvalidatedCacheEntries(host, request); impl.flushInvalidatedCacheEntries(host, request);
verify(mockStorage).getEntry("http://foo.example.com:80/"); verify(mockStorage).getEntry("http://foo.example.com:80/");
@ -208,7 +208,7 @@ public class TestCacheInvalidator {
public void testInvalidatesHEADCacheEntryIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception { public void testInvalidatesHEADCacheEntryIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception {
impl = new CacheInvalidator(cacheKeyGenerator, mockStorage); impl = new CacheInvalidator(cacheKeyGenerator, mockStorage);
final String theURI = "http://foo.example.com:80/"; final String theURI = "http://foo.example.com:80/";
request = new BasicHttpRequest("GET", theURI,HTTP_1_1); request = new BasicClassicHttpRequest("GET", theURI);
cacheEntryisForMethod("HEAD"); cacheEntryisForMethod("HEAD");
cacheEntryHasVariantMap(new HashMap<String, String>()); cacheEntryHasVariantMap(new HashMap<String, String>());
@ -226,7 +226,7 @@ public class TestCacheInvalidator {
public void testInvalidatesVariantHEADCacheEntriesIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception { public void testInvalidatesVariantHEADCacheEntriesIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception {
impl = new CacheInvalidator(cacheKeyGenerator, mockStorage); impl = new CacheInvalidator(cacheKeyGenerator, mockStorage);
final String theURI = "http://foo.example.com:80/"; final String theURI = "http://foo.example.com:80/";
request = new BasicHttpRequest("GET", theURI,HTTP_1_1); request = new BasicClassicHttpRequest("GET", theURI);
final String theVariantKey = "{Accept-Encoding=gzip%2Cdeflate&User-Agent=Apache-HttpClient}"; final String theVariantKey = "{Accept-Encoding=gzip%2Cdeflate&User-Agent=Apache-HttpClient}";
final String theVariantURI = "{Accept-Encoding=gzip%2Cdeflate&User-Agent=Apache-HttpClient}http://foo.example.com:80/"; final String theVariantURI = "{Accept-Encoding=gzip%2Cdeflate&User-Agent=Apache-HttpClient}http://foo.example.com:80/";
final Map<String, String> variants = HttpTestUtils.makeDefaultVariantMap(theVariantKey, theVariantURI); final Map<String, String> variants = HttpTestUtils.makeDefaultVariantMap(theVariantKey, theVariantURI);
@ -247,7 +247,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testDoesNotInvalidateHEADCacheEntry() throws Exception { public void testDoesNotInvalidateHEADCacheEntry() throws Exception {
final String theURI = "http://foo.example.com:80/"; final String theURI = "http://foo.example.com:80/";
request = new BasicHttpRequest("HEAD", theURI,HTTP_1_1); request = new BasicClassicHttpRequest("HEAD", theURI);
cacheReturnsEntryForUri(theURI); cacheReturnsEntryForUri(theURI);
@ -261,7 +261,7 @@ public class TestCacheInvalidator {
public void testDoesNotInvalidateHEADCacheEntryIfSubsequentHEADRequestsAreMadeToTheSameURI() throws Exception { public void testDoesNotInvalidateHEADCacheEntryIfSubsequentHEADRequestsAreMadeToTheSameURI() throws Exception {
impl = new CacheInvalidator(cacheKeyGenerator, mockStorage); impl = new CacheInvalidator(cacheKeyGenerator, mockStorage);
final String theURI = "http://foo.example.com:80/"; final String theURI = "http://foo.example.com:80/";
request = new BasicHttpRequest("HEAD", theURI,HTTP_1_1); request = new BasicClassicHttpRequest("HEAD", theURI);
cacheReturnsEntryForUri(theURI); cacheReturnsEntryForUri(theURI);
@ -275,7 +275,7 @@ public class TestCacheInvalidator {
public void testDoesNotInvalidateGETCacheEntryIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception { public void testDoesNotInvalidateGETCacheEntryIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception {
impl = new CacheInvalidator(cacheKeyGenerator, mockStorage); impl = new CacheInvalidator(cacheKeyGenerator, mockStorage);
final String theURI = "http://foo.example.com:80/"; final String theURI = "http://foo.example.com:80/";
request = new BasicHttpRequest("GET", theURI,HTTP_1_1); request = new BasicClassicHttpRequest("GET", theURI);
cacheEntryisForMethod("GET"); cacheEntryisForMethod("GET");
cacheReturnsEntryForUri(theURI); cacheReturnsEntryForUri(theURI);
@ -289,7 +289,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testDoesNotInvalidateRequestsWithClientCacheControlHeaders() throws Exception { public void testDoesNotInvalidateRequestsWithClientCacheControlHeaders() throws Exception {
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicClassicHttpRequest("GET","/");
request.setHeader("Cache-Control","no-cache"); request.setHeader("Cache-Control","no-cache");
impl.flushInvalidatedCacheEntries(host, request); impl.flushInvalidatedCacheEntries(host, request);
@ -300,7 +300,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testDoesNotInvalidateRequestsWithClientPragmaHeaders() throws Exception { public void testDoesNotInvalidateRequestsWithClientPragmaHeaders() throws Exception {
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicClassicHttpRequest("GET","/");
request.setHeader("Pragma","no-cache"); request.setHeader("Pragma","no-cache");
impl.flushInvalidatedCacheEntries(host, request); impl.flushInvalidatedCacheEntries(host, request);
@ -311,7 +311,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testVariantURIsAreFlushedAlso() throws Exception { public void testVariantURIsAreFlushedAlso() throws Exception {
request = new BasicHttpRequest("POST","/",HTTP_1_1); request = new BasicClassicHttpRequest("POST","/");
final String theUri = "http://foo.example.com:80/"; final String theUri = "http://foo.example.com:80/";
final String variantUri = "theVariantURI"; final String variantUri = "theVariantURI";
final Map<String,String> mapOfURIs = HttpTestUtils.makeDefaultVariantMap(variantUri, variantUri); final Map<String,String> mapOfURIs = HttpTestUtils.makeDefaultVariantMap(variantUri, variantUri);
@ -329,7 +329,7 @@ public class TestCacheInvalidator {
@Test @Test
public void testCacheFlushException() throws Exception { public void testCacheFlushException() throws Exception {
request = new BasicHttpRequest("POST","/",HTTP_1_1); request = new BasicClassicHttpRequest("POST","/");
final String theURI = "http://foo.example.com:80/"; final String theURI = "http://foo.example.com:80/";
cacheReturnsExceptionForUri(theURI); cacheReturnsExceptionForUri(theURI);
@ -372,7 +372,7 @@ public class TestCacheInvalidator {
@Test @Test
public void flushesEntryIfFresherAndSpecifiedByLocation() public void flushesEntryIfFresherAndSpecifiedByLocation()
throws Exception { throws Exception {
response.setStatusCode(201); response.setCode(201);
response.setHeader("ETag","\"new-etag\""); response.setHeader("ETag","\"new-etag\"");
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
final String theURI = "http://foo.example.com:80/bar"; final String theURI = "http://foo.example.com:80/bar";
@ -394,7 +394,7 @@ public class TestCacheInvalidator {
@Test @Test
public void doesNotFlushEntryForUnsuccessfulResponse() public void doesNotFlushEntryForUnsuccessfulResponse()
throws Exception { throws Exception {
response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); response = new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST, "Bad Request");
response.setHeader("ETag","\"new-etag\""); response.setHeader("ETag","\"new-etag\"");
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
final String theURI = "http://foo.example.com:80/bar"; final String theURI = "http://foo.example.com:80/bar";

View File

@ -35,8 +35,8 @@ import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicHeaderIterator;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -66,50 +66,50 @@ public class TestCacheKeyGenerator {
public void testExtractsUriFromAbsoluteUriInRequest() { public void testExtractsUriFromAbsoluteUriInRequest() {
final HttpHost host = new HttpHost("bar.example.com"); final HttpHost host = new HttpHost("bar.example.com");
final HttpRequest req = new HttpGet("http://foo.example.com/"); final HttpRequest req = new HttpGet("http://foo.example.com/");
Assert.assertEquals("http://foo.example.com:80/", extractor.getURI(host, req)); Assert.assertEquals("http://foo.example.com:80/", extractor.generateKey(host, req));
} }
@Test @Test
public void testGetURIWithDefaultPortAndScheme() { public void testGetURIWithDefaultPortAndScheme() {
Assert.assertEquals("http://www.comcast.net:80/", extractor.getURI(new HttpHost( Assert.assertEquals("http://www.comcast.net:80/", extractor.generateKey(new HttpHost(
"www.comcast.net"), REQUEST_ROOT)); "www.comcast.net"), REQUEST_ROOT));
Assert.assertEquals("http://www.fancast.com:80/full_episodes", extractor.getURI(new HttpHost( Assert.assertEquals("http://www.fancast.com:80/full_episodes", extractor.generateKey(new HttpHost(
"www.fancast.com"), REQUEST_FULL_EPISODES)); "www.fancast.com"), REQUEST_FULL_EPISODES));
} }
@Test @Test
public void testGetURIWithDifferentScheme() { public void testGetURIWithDifferentScheme() {
Assert.assertEquals("https://www.comcast.net:443/", extractor.getURI(new HttpHost( Assert.assertEquals("https://www.comcast.net:443/", extractor.generateKey(new HttpHost(
"www.comcast.net", -1, "https"), REQUEST_ROOT)); "www.comcast.net", -1, "https"), REQUEST_ROOT));
Assert.assertEquals("myhttp://www.fancast.com/full_episodes", extractor.getURI( Assert.assertEquals("myhttp://www.fancast.com/full_episodes", extractor.generateKey(
new HttpHost("www.fancast.com", -1, "myhttp"), REQUEST_FULL_EPISODES)); new HttpHost("www.fancast.com", -1, "myhttp"), REQUEST_FULL_EPISODES));
} }
@Test @Test
public void testGetURIWithDifferentPort() { public void testGetURIWithDifferentPort() {
Assert.assertEquals("http://www.comcast.net:8080/", extractor.getURI(new HttpHost( Assert.assertEquals("http://www.comcast.net:8080/", extractor.generateKey(new HttpHost(
"www.comcast.net", 8080), REQUEST_ROOT)); "www.comcast.net", 8080), REQUEST_ROOT));
Assert.assertEquals("http://www.fancast.com:9999/full_episodes", extractor.getURI( Assert.assertEquals("http://www.fancast.com:9999/full_episodes", extractor.generateKey(
new HttpHost("www.fancast.com", 9999), REQUEST_FULL_EPISODES)); new HttpHost("www.fancast.com", 9999), REQUEST_FULL_EPISODES));
} }
@Test @Test
public void testGetURIWithDifferentPortAndScheme() { public void testGetURIWithDifferentPortAndScheme() {
Assert.assertEquals("https://www.comcast.net:8080/", extractor.getURI(new HttpHost( Assert.assertEquals("https://www.comcast.net:8080/", extractor.generateKey(new HttpHost(
"www.comcast.net", 8080, "https"), REQUEST_ROOT)); "www.comcast.net", 8080, "https"), REQUEST_ROOT));
Assert.assertEquals("myhttp://www.fancast.com:9999/full_episodes", extractor.getURI( Assert.assertEquals("myhttp://www.fancast.com:9999/full_episodes", extractor.generateKey(
new HttpHost("www.fancast.com", 9999, "myhttp"), REQUEST_FULL_EPISODES)); new HttpHost("www.fancast.com", 9999, "myhttp"), REQUEST_FULL_EPISODES));
} }
@Test @Test
public void testGetURIWithQueryParameters() { public void testGetURIWithQueryParameters() {
Assert.assertEquals("http://www.comcast.net:80/?foo=bar", extractor.getURI(new HttpHost( Assert.assertEquals("http://www.comcast.net:80/?foo=bar", extractor.generateKey(new HttpHost(
"www.comcast.net", -1, "http"), new BasicHttpRequest("GET", "/?foo=bar"))); "www.comcast.net", -1, "http"), new BasicHttpRequest("GET", "/?foo=bar")));
Assert.assertEquals("http://www.fancast.com:80/full_episodes?foo=bar", extractor.getURI( Assert.assertEquals("http://www.fancast.com:80/full_episodes?foo=bar", extractor.generateKey(
new HttpHost("www.fancast.com", -1, "http"), new BasicHttpRequest("GET", new HttpHost("www.fancast.com", -1, "http"), new BasicHttpRequest("GET",
"/full_episodes?foo=bar"))); "/full_episodes?foo=bar")));
} }
@ -120,14 +120,14 @@ public class TestCacheKeyGenerator {
when(mockEntry.hasVariants()).thenReturn(false); when(mockEntry.hasVariants()).thenReturn(false);
extractor = new CacheKeyGenerator() { extractor = new CacheKeyGenerator() {
@Override @Override
public String getURI(final HttpHost h, final HttpRequest req) { public String generateKey(final HttpHost h, final HttpRequest req) {
Assert.assertSame(defaultHost, h); Assert.assertSame(defaultHost, h);
Assert.assertSame(mockRequest, req); Assert.assertSame(mockRequest, req);
return theURI; return theURI;
} }
}; };
final String result = extractor.getVariantURI(defaultHost, mockRequest, mockEntry); final String result = extractor.generateVariantURI(defaultHost, mockRequest, mockEntry);
verify(mockEntry).hasVariants(); verify(mockEntry).hasVariants();
Assert.assertSame(theURI, result); Assert.assertSame(theURI, result);
} }
@ -140,21 +140,20 @@ public class TestCacheKeyGenerator {
extractor = new CacheKeyGenerator() { extractor = new CacheKeyGenerator() {
@Override @Override
public String getURI(final HttpHost h, final HttpRequest req) { public String generateKey(final HttpHost h, final HttpRequest req) {
Assert.assertSame(defaultHost, h); Assert.assertSame(defaultHost, h);
Assert.assertSame(mockRequest, req); Assert.assertSame(mockRequest, req);
return theURI; return theURI;
} }
}; };
when(mockEntry.hasVariants()).thenReturn(true); when(mockEntry.hasVariants()).thenReturn(true);
when(mockEntry.getHeaders("Vary")).thenReturn(varyHeaders); when(mockEntry.headerIterator("Vary")).thenReturn(new BasicHeaderIterator(varyHeaders, "Vary"));
when(mockRequest.getHeaders("Accept-Encoding")).thenReturn( when(mockRequest.getHeaders("Accept-Encoding")).thenReturn(encHeaders);
encHeaders);
final String result = extractor.getVariantURI(defaultHost, mockRequest, mockEntry); final String result = extractor.generateVariantURI(defaultHost, mockRequest, mockEntry);
verify(mockEntry).hasVariants(); verify(mockEntry).hasVariants();
verify(mockEntry).getHeaders("Vary"); verify(mockEntry).headerIterator("Vary");
verify(mockRequest).getHeaders("Accept-Encoding"); verify(mockRequest).getHeaders("Accept-Encoding");
Assert.assertEquals("{Accept-Encoding=gzip}" + theURI, result); Assert.assertEquals("{Accept-Encoding=gzip}" + theURI, result);
} }
@ -166,21 +165,21 @@ public class TestCacheKeyGenerator {
final Header[] varyHeaders = { new BasicHeader("Vary", "Accept-Encoding") }; final Header[] varyHeaders = { new BasicHeader("Vary", "Accept-Encoding") };
extractor = new CacheKeyGenerator() { extractor = new CacheKeyGenerator() {
@Override @Override
public String getURI(final HttpHost h, final HttpRequest req) { public String generateKey(final HttpHost h, final HttpRequest req) {
Assert.assertSame(defaultHost, h); Assert.assertSame(defaultHost, h);
Assert.assertSame(mockRequest, req); Assert.assertSame(mockRequest, req);
return theURI; return theURI;
} }
}; };
when(mockEntry.hasVariants()).thenReturn(true); when(mockEntry.hasVariants()).thenReturn(true);
when(mockEntry.getHeaders("Vary")).thenReturn(varyHeaders); when(mockEntry.headerIterator("Vary")).thenReturn(new BasicHeaderIterator(varyHeaders, "Vary"));
when(mockRequest.getHeaders("Accept-Encoding")) when(mockRequest.getHeaders("Accept-Encoding"))
.thenReturn(noHeaders); .thenReturn(noHeaders);
final String result = extractor.getVariantURI(defaultHost, mockRequest, mockEntry); final String result = extractor.generateVariantURI(defaultHost, mockRequest, mockEntry);
verify(mockEntry).hasVariants(); verify(mockEntry).hasVariants();
verify(mockEntry).getHeaders("Vary"); verify(mockEntry).headerIterator("Vary");
verify(mockRequest).getHeaders("Accept-Encoding"); verify(mockRequest).getHeaders("Accept-Encoding");
Assert.assertEquals("{Accept-Encoding=}" + theURI, result); Assert.assertEquals("{Accept-Encoding=}" + theURI, result);
} }
@ -193,22 +192,21 @@ public class TestCacheKeyGenerator {
final Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") }; final Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") };
extractor = new CacheKeyGenerator() { extractor = new CacheKeyGenerator() {
@Override @Override
public String getURI(final HttpHost h, final HttpRequest req) { public String generateKey(final HttpHost h, final HttpRequest req) {
Assert.assertSame(defaultHost, h); Assert.assertSame(defaultHost, h);
Assert.assertSame(mockRequest, req); Assert.assertSame(mockRequest, req);
return theURI; return theURI;
} }
}; };
when(mockEntry.hasVariants()).thenReturn(true); when(mockEntry.hasVariants()).thenReturn(true);
when(mockEntry.getHeaders("Vary")).thenReturn(varyHeaders); when(mockEntry.headerIterator("Vary")).thenReturn(new BasicHeaderIterator(varyHeaders, "Vary"));
when(mockRequest.getHeaders("Accept-Encoding")).thenReturn( when(mockRequest.getHeaders("Accept-Encoding")).thenReturn(encHeaders);
encHeaders);
when(mockRequest.getHeaders("User-Agent")).thenReturn(uaHeaders); when(mockRequest.getHeaders("User-Agent")).thenReturn(uaHeaders);
final String result = extractor.getVariantURI(defaultHost, mockRequest, mockEntry); final String result = extractor.generateVariantURI(defaultHost, mockRequest, mockEntry);
verify(mockEntry).hasVariants(); verify(mockEntry).hasVariants();
verify(mockEntry).getHeaders("Vary"); verify(mockEntry).headerIterator("Vary");
verify(mockRequest).getHeaders("Accept-Encoding"); verify(mockRequest).getHeaders("Accept-Encoding");
verify(mockRequest).getHeaders("User-Agent"); verify(mockRequest).getHeaders("User-Agent");
Assert.assertEquals("{Accept-Encoding=gzip&User-Agent=browser}" + theURI, result); Assert.assertEquals("{Accept-Encoding=gzip&User-Agent=browser}" + theURI, result);
@ -223,21 +221,21 @@ public class TestCacheKeyGenerator {
final Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") }; final Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") };
extractor = new CacheKeyGenerator() { extractor = new CacheKeyGenerator() {
@Override @Override
public String getURI(final HttpHost h, final HttpRequest req) { public String generateKey(final HttpHost h, final HttpRequest req) {
Assert.assertSame(defaultHost, h); Assert.assertSame(defaultHost, h);
Assert.assertSame(mockRequest, req); Assert.assertSame(mockRequest, req);
return theURI; return theURI;
} }
}; };
when(mockEntry.hasVariants()).thenReturn(true); when(mockEntry.hasVariants()).thenReturn(true);
when(mockEntry.getHeaders("Vary")).thenReturn(varyHeaders); when(mockEntry.headerIterator("Vary")).thenReturn(new BasicHeaderIterator(varyHeaders, "Vary"));
when(mockRequest.getHeaders("Accept-Encoding")).thenReturn(encHeaders); when(mockRequest.getHeaders("Accept-Encoding")).thenReturn(encHeaders);
when(mockRequest.getHeaders("User-Agent")).thenReturn(uaHeaders); when(mockRequest.getHeaders("User-Agent")).thenReturn(uaHeaders);
final String result = extractor.getVariantURI(defaultHost, mockRequest, mockEntry); final String result = extractor.generateVariantURI(defaultHost, mockRequest, mockEntry);
verify(mockEntry).hasVariants(); verify(mockEntry).hasVariants();
verify(mockEntry).getHeaders("Vary"); verify(mockEntry).headerIterator("Vary");
verify(mockRequest).getHeaders("Accept-Encoding"); verify(mockRequest).getHeaders("Accept-Encoding");
verify(mockRequest).getHeaders("User-Agent"); verify(mockRequest).getHeaders("User-Agent");
Assert.assertEquals("{Accept-Encoding=gzip&User-Agent=browser}" + theURI, result); Assert.assertEquals("{Accept-Encoding=gzip&User-Agent=browser}" + theURI, result);
@ -252,26 +250,24 @@ public class TestCacheKeyGenerator {
final Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") }; final Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") };
extractor = new CacheKeyGenerator() { extractor = new CacheKeyGenerator() {
@Override @Override
public String getURI(final HttpHost h, final HttpRequest req) { public String generateKey(final HttpHost h, final HttpRequest req) {
Assert.assertSame(defaultHost, h); Assert.assertSame(defaultHost, h);
Assert.assertSame(mockRequest, req); Assert.assertSame(mockRequest, req);
return theURI; return theURI;
} }
}; };
when(mockEntry.hasVariants()).thenReturn(true); when(mockEntry.hasVariants()).thenReturn(true);
when(mockEntry.getHeaders("Vary")).thenReturn(varyHeaders); when(mockEntry.headerIterator("Vary")).thenReturn(new BasicHeaderIterator(varyHeaders, "Vary"));
when(mockRequest.getHeaders("Accept-Encoding")).thenReturn(encHeaders); when(mockRequest.getHeaders("Accept-Encoding")).thenReturn(encHeaders);
when(mockRequest.getHeaders("User-Agent")).thenReturn(uaHeaders); when(mockRequest.getHeaders("User-Agent")).thenReturn(uaHeaders);
final String result = extractor.getVariantURI(defaultHost, mockRequest, mockEntry); final String result = extractor.generateVariantURI(defaultHost, mockRequest, mockEntry);
verify(mockEntry).hasVariants(); verify(mockEntry).hasVariants();
verify(mockEntry).getHeaders("Vary"); verify(mockEntry).headerIterator("Vary");
verify(mockRequest).getHeaders("Accept-Encoding"); verify(mockRequest).getHeaders("Accept-Encoding");
verify(mockRequest).getHeaders("User-Agent"); verify(mockRequest).getHeaders("User-Agent");
Assert Assert.assertEquals("{Accept-Encoding=gzip%2C+deflate&User-Agent=browser}" + theURI, result);
.assertEquals("{Accept-Encoding=gzip%2C+deflate&User-Agent=browser}" + theURI,
result);
} }
/* /*
@ -292,17 +288,17 @@ public class TestCacheKeyGenerator {
public void testEmptyPortEquivalentToDefaultPortForHttp() { public void testEmptyPortEquivalentToDefaultPortForHttp() {
final HttpHost host1 = new HttpHost("foo.example.com:"); final HttpHost host1 = new HttpHost("foo.example.com:");
final HttpHost host2 = new HttpHost("foo.example.com:80"); final HttpHost host2 = new HttpHost("foo.example.com:80");
final HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET", "/");
Assert.assertEquals(extractor.getURI(host1, req), extractor.getURI(host2, req)); Assert.assertEquals(extractor.generateKey(host1, req), extractor.generateKey(host2, req));
} }
@Test @Test
public void testEmptyPortEquivalentToDefaultPortForHttps() { public void testEmptyPortEquivalentToDefaultPortForHttps() {
final HttpHost host1 = new HttpHost("foo.example.com", -1, "https"); final HttpHost host1 = new HttpHost("foo.example.com", -1, "https");
final HttpHost host2 = new HttpHost("foo.example.com", 443, "https"); final HttpHost host2 = new HttpHost("foo.example.com", 443, "https");
final HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET", "/");
final String uri1 = extractor.getURI(host1, req); final String uri1 = extractor.generateKey(host1, req);
final String uri2 = extractor.getURI(host2, req); final String uri2 = extractor.generateKey(host2, req);
Assert.assertEquals(uri1, uri2); Assert.assertEquals(uri1, uri2);
} }
@ -311,8 +307,8 @@ public class TestCacheKeyGenerator {
final HttpHost host = new HttpHost("foo.example.com", -1, "https"); final HttpHost host = new HttpHost("foo.example.com", -1, "https");
final HttpGet get1 = new HttpGet("https://bar.example.com:/"); final HttpGet get1 = new HttpGet("https://bar.example.com:/");
final HttpGet get2 = new HttpGet("https://bar.example.com:443/"); final HttpGet get2 = new HttpGet("https://bar.example.com:443/");
final String uri1 = extractor.getURI(host, get1); final String uri1 = extractor.generateKey(host, get1);
final String uri2 = extractor.getURI(host, get2); final String uri2 = extractor.generateKey(host, get2);
Assert.assertEquals(uri1, uri2); Assert.assertEquals(uri1, uri2);
} }
@ -321,8 +317,8 @@ public class TestCacheKeyGenerator {
final HttpHost host = new HttpHost("foo.example.com", -1, "https"); final HttpHost host = new HttpHost("foo.example.com", -1, "https");
final HttpGet get1 = new HttpGet("https://bar.example.com/"); final HttpGet get1 = new HttpGet("https://bar.example.com/");
final HttpGet get2 = new HttpGet("https://bar.example.com:443/"); final HttpGet get2 = new HttpGet("https://bar.example.com:443/");
final String uri1 = extractor.getURI(host, get1); final String uri1 = extractor.generateKey(host, get1);
final String uri2 = extractor.getURI(host, get2); final String uri2 = extractor.generateKey(host, get2);
Assert.assertEquals(uri1, uri2); Assert.assertEquals(uri1, uri2);
} }
@ -330,95 +326,95 @@ public class TestCacheKeyGenerator {
public void testNotProvidedPortEquivalentToDefaultPortForHttp() { public void testNotProvidedPortEquivalentToDefaultPortForHttp() {
final HttpHost host1 = new HttpHost("foo.example.com"); final HttpHost host1 = new HttpHost("foo.example.com");
final HttpHost host2 = new HttpHost("foo.example.com:80"); final HttpHost host2 = new HttpHost("foo.example.com:80");
final HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET", "/");
Assert.assertEquals(extractor.getURI(host1, req), extractor.getURI(host2, req)); Assert.assertEquals(extractor.generateKey(host1, req), extractor.generateKey(host2, req));
} }
@Test @Test
public void testHostNameComparisonsAreCaseInsensitive() { public void testHostNameComparisonsAreCaseInsensitive() {
final HttpHost host1 = new HttpHost("foo.example.com"); final HttpHost host1 = new HttpHost("foo.example.com");
final HttpHost host2 = new HttpHost("FOO.EXAMPLE.COM"); final HttpHost host2 = new HttpHost("FOO.EXAMPLE.COM");
final HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET", "/");
Assert.assertEquals(extractor.getURI(host1, req), extractor.getURI(host2, req)); Assert.assertEquals(extractor.generateKey(host1, req), extractor.generateKey(host2, req));
} }
@Test @Test
public void testSchemeNameComparisonsAreCaseInsensitive() { public void testSchemeNameComparisonsAreCaseInsensitive() {
final HttpHost host1 = new HttpHost("foo.example.com", -1, "http"); final HttpHost host1 = new HttpHost("foo.example.com", -1, "http");
final HttpHost host2 = new HttpHost("foo.example.com", -1, "HTTP"); final HttpHost host2 = new HttpHost("foo.example.com", -1, "HTTP");
final HttpRequest req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET", "/");
Assert.assertEquals(extractor.getURI(host1, req), extractor.getURI(host2, req)); Assert.assertEquals(extractor.generateKey(host1, req), extractor.generateKey(host2, req));
} }
@Test @Test
public void testEmptyAbsPathIsEquivalentToSlash() { public void testEmptyAbsPathIsEquivalentToSlash() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/");
final HttpRequest req2 = new HttpGet("http://foo.example.com"); final HttpRequest req2 = new HttpGet("http://foo.example.com");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
@Test @Test
public void testExtraDotSegmentsAreIgnored() { public void testExtraDotSegmentsAreIgnored() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/");
final HttpRequest req2 = new HttpGet("http://foo.example.com/./"); final HttpRequest req2 = new HttpGet("http://foo.example.com/./");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
@Test @Test
public void testExtraDotDotSegmentsAreIgnored() { public void testExtraDotDotSegmentsAreIgnored() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/");
final HttpRequest req2 = new HttpGet("http://foo.example.com/.././../"); final HttpRequest req2 = new HttpGet("http://foo.example.com/.././../");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
@Test @Test
public void testIntermidateDotDotSegementsAreEquivalent() { public void testIntermidateDotDotSegementsAreEquivalent() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/home.html", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/home.html");
final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith/../home.html", HttpVersion.HTTP_1_1); final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith/../home.html");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
@Test @Test
public void testIntermidateEncodedDotDotSegementsAreEquivalent() { public void testIntermidateEncodedDotDotSegementsAreEquivalent() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/home.html", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/home.html");
final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith%2F../home.html", HttpVersion.HTTP_1_1); final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith%2F../home.html");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
@Test @Test
public void testIntermidateDotSegementsAreEquivalent() { public void testIntermidateDotSegementsAreEquivalent() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/~smith/home.html", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/~smith/home.html");
final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith/./home.html", HttpVersion.HTTP_1_1); final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith/./home.html");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
@Test @Test
public void testEquivalentPathEncodingsAreEquivalent() { public void testEquivalentPathEncodingsAreEquivalent() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/~smith/home.html", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/~smith/home.html");
final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith/home.html", HttpVersion.HTTP_1_1); final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith/home.html");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
@Test @Test
public void testEquivalentExtraPathEncodingsAreEquivalent() { public void testEquivalentExtraPathEncodingsAreEquivalent() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/~smith/home.html", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/~smith/home.html");
final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith%2Fhome.html", HttpVersion.HTTP_1_1); final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith%2Fhome.html");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
@Test @Test
public void testEquivalentExtraPathEncodingsWithPercentAreEquivalent() { public void testEquivalentExtraPathEncodingsWithPercentAreEquivalent() {
final HttpHost host = new HttpHost("foo.example.com"); final HttpHost host = new HttpHost("foo.example.com");
final HttpRequest req1 = new BasicHttpRequest("GET", "/~smith/home%20folder.html", HttpVersion.HTTP_1_1); final HttpRequest req1 = new BasicHttpRequest("GET", "/~smith/home%20folder.html");
final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith%2Fhome%20folder.html", HttpVersion.HTTP_1_1); final HttpRequest req2 = new BasicHttpRequest("GET", "/%7Esmith%2Fhome%20folder.html");
Assert.assertEquals(extractor.getURI(host, req1), extractor.getURI(host, req2)); Assert.assertEquals(extractor.generateKey(host, req1), extractor.generateKey(host, req2));
} }
} }

View File

@ -39,7 +39,6 @@ import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.junit.Before; import org.junit.Before;
@ -432,7 +431,7 @@ public class TestCacheValidityPolicy {
new BasicHeader("Cache-Control", "max-age=5, stale-if-error=15") new BasicHeader("Cache-Control", "max-age=5, stale-if-error=15")
}; };
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
final HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET","/");
assertTrue(impl.mayReturnStaleIfError(req, entry, now)); assertTrue(impl.mayReturnStaleIfError(req, entry, now));
} }
@ -443,7 +442,7 @@ public class TestCacheValidityPolicy {
new BasicHeader("Cache-Control", "max-age=5") new BasicHeader("Cache-Control", "max-age=5")
}; };
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
final HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET","/");
req.setHeader("Cache-Control","stale-if-error=15"); req.setHeader("Cache-Control","stale-if-error=15");
assertTrue(impl.mayReturnStaleIfError(req, entry, now)); assertTrue(impl.mayReturnStaleIfError(req, entry, now));
} }
@ -455,7 +454,7 @@ public class TestCacheValidityPolicy {
new BasicHeader("Cache-Control", "max-age=5, stale-if-error=1") new BasicHeader("Cache-Control", "max-age=5, stale-if-error=1")
}; };
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
final HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET","/");
assertFalse(impl.mayReturnStaleIfError(req, entry, now)); assertFalse(impl.mayReturnStaleIfError(req, entry, now));
} }
@ -466,7 +465,7 @@ public class TestCacheValidityPolicy {
new BasicHeader("Cache-Control", "max-age=5") new BasicHeader("Cache-Control", "max-age=5")
}; };
final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers); final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
final HttpRequest req = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); final HttpRequest req = new BasicHttpRequest("GET","/");
req.setHeader("Cache-Control","stale-if-error=1"); req.setHeader("Cache-Control","stale-if-error=1");
assertFalse(impl.mayReturnStaleIfError(req, entry, now)); assertFalse(impl.mayReturnStaleIfError(req, entry, now));
} }

View File

@ -35,11 +35,12 @@ import static org.mockito.Mockito.when;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -49,16 +50,18 @@ import org.junit.Test;
public class TestCachedHttpResponseGenerator { public class TestCachedHttpResponseGenerator {
private HttpHost host; private HttpHost host;
private HttpRoute route;
private HttpCacheEntry entry; private HttpCacheEntry entry;
private HttpRequestWrapper request; private RoutedHttpRequest request;
private CacheValidityPolicy mockValidityPolicy; private CacheValidityPolicy mockValidityPolicy;
private CachedHttpResponseGenerator impl; private CachedHttpResponseGenerator impl;
@Before @Before
public void setUp() { public void setUp() {
host = new HttpHost("foo.example.com", 80); host = new HttpHost("foo.example.com", 80);
route = new HttpRoute(host);
entry = HttpTestUtils.makeCacheEntry(new HashMap<String, String>()); entry = HttpTestUtils.makeCacheEntry(new HashMap<String, String>());
request = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); request = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
mockValidityPolicy = mock(CacheValidityPolicy.class); mockValidityPolicy = mock(CacheValidityPolicy.class);
impl = new CachedHttpResponseGenerator(mockValidityPolicy); impl = new CachedHttpResponseGenerator(mockValidityPolicy);
} }
@ -68,7 +71,7 @@ public class TestCachedHttpResponseGenerator {
final byte[] buf = new byte[] { 1, 2, 3, 4, 5 }; final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(buf); final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(buf);
final HttpResponse response = impl.generateResponse(request, entry1); final ClassicHttpResponse response = impl.generateResponse(request, entry1);
final Header length = response.getFirstHeader("Content-Length"); final Header length = response.getFirstHeader("Content-Length");
Assert.assertNotNull("Content-Length Header is missing", length); Assert.assertNotNull("Content-Length Header is missing", length);
@ -84,7 +87,7 @@ public class TestCachedHttpResponseGenerator {
final byte[] buf = new byte[] { 1, 2, 3, 4, 5 }; final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(hdrs, buf); final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(hdrs, buf);
final HttpResponse response = impl.generateResponse(request, entry1); final ClassicHttpResponse response = impl.generateResponse(request, entry1);
final Header length = response.getFirstHeader("Content-Length"); final Header length = response.getFirstHeader("Content-Length");
@ -93,27 +96,27 @@ public class TestCachedHttpResponseGenerator {
@Test @Test
public void testResponseMatchesCacheEntry() { public void testResponseMatchesCacheEntry() {
final HttpResponse response = impl.generateResponse(request, entry); final ClassicHttpResponse response = impl.generateResponse(request, entry);
Assert.assertTrue(response.containsHeader("Content-Length")); Assert.assertTrue(response.containsHeader("Content-Length"));
Assert.assertSame("HTTP", response.getProtocolVersion().getProtocol()); Assert.assertSame("HTTP", response.getVersion().getProtocol());
Assert.assertEquals(1, response.getProtocolVersion().getMajor()); Assert.assertEquals(1, response.getVersion().getMajor());
Assert.assertEquals(1, response.getProtocolVersion().getMinor()); Assert.assertEquals(1, response.getVersion().getMinor());
} }
@Test @Test
public void testResponseStatusCodeMatchesCacheEntry() { public void testResponseStatusCodeMatchesCacheEntry() {
final HttpResponse response = impl.generateResponse(request, entry); final ClassicHttpResponse response = impl.generateResponse(request, entry);
Assert.assertEquals(entry.getStatusCode(), response.getStatusLine().getStatusCode()); Assert.assertEquals(entry.getStatus(), response.getCode());
} }
@Test @Test
public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() { public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() {
currentAge(10L); currentAge(10L);
final HttpResponse response = impl.generateResponse(request, entry); final ClassicHttpResponse response = impl.generateResponse(request, entry);
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class)); verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
@ -126,7 +129,7 @@ public class TestCachedHttpResponseGenerator {
public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() { public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() {
currentAge(0L); currentAge(0L);
final HttpResponse response = impl.generateResponse(request, entry); final ClassicHttpResponse response = impl.generateResponse(request, entry);
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class)); verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
@ -138,7 +141,7 @@ public class TestCachedHttpResponseGenerator {
public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() { public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() {
currentAge(CacheValidityPolicy.MAX_AGE + 1L); currentAge(CacheValidityPolicy.MAX_AGE + 1L);
final HttpResponse response = impl.generateResponse(request, entry); final ClassicHttpResponse response = impl.generateResponse(request, entry);
verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class)); verify(mockValidityPolicy).getCurrentAgeSecs(same(entry), isA(Date.class));
@ -155,15 +158,15 @@ public class TestCachedHttpResponseGenerator {
@Test @Test
public void testResponseContainsEntityToServeGETRequestIfEntryContainsResource() throws Exception { public void testResponseContainsEntityToServeGETRequestIfEntryContainsResource() throws Exception {
final HttpResponse response = impl.generateResponse(request, entry); final ClassicHttpResponse response = impl.generateResponse(request, entry);
Assert.assertNotNull(response.getEntity()); Assert.assertNotNull(response.getEntity());
} }
@Test @Test
public void testResponseDoesNotContainEntityToServeHEADRequestIfEntryContainsResource() throws Exception { public void testResponseDoesNotContainEntityToServeHEADRequestIfEntryContainsResource() throws Exception {
final HttpRequestWrapper headRequest = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultHEADRequest(), host); final RoutedHttpRequest headRequest = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultHEADRequest(), route);
final HttpResponse response = impl.generateResponse(headRequest, entry); final ClassicHttpResponse response = impl.generateResponse(headRequest, entry);
Assert.assertNull(response.getEntity()); Assert.assertNull(response.getEntity());
} }

View File

@ -33,7 +33,6 @@ import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.junit.Assert; import org.junit.Assert;
@ -60,7 +59,7 @@ public class TestCachedResponseSuitabilityChecker {
nineSecondsAgo = new Date(now.getTime() - 9 * 1000L); nineSecondsAgo = new Date(now.getTime() - 9 * 1000L);
host = new HttpHost("foo.example.com"); host = new HttpHost("foo.example.com");
request = new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1); request = new BasicHttpRequest("GET", "/foo");
entry = HttpTestUtils.makeCacheEntry(); entry = HttpTestUtils.makeCacheEntry();
impl = new CachedResponseSuitabilityChecker(CacheConfig.DEFAULT); impl = new CachedResponseSuitabilityChecker(CacheConfig.DEFAULT);
@ -253,7 +252,7 @@ public class TestCachedResponseSuitabilityChecker {
@Test @Test
public void testSuitableIfRequestMethodisHEAD() { public void testSuitableIfRequestMethodisHEAD() {
final HttpRequest headRequest = new BasicHttpRequest("HEAD", "/foo", HttpVersion.HTTP_1_1); final HttpRequest headRequest = new BasicHttpRequest("HEAD", "/foo");
final Header[] headers = { final Header[] headers = {
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)), new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
new BasicHeader("Cache-Control", "max-age=3600"), new BasicHeader("Cache-Control", "max-age=3600"),
@ -316,7 +315,7 @@ public class TestCachedResponseSuitabilityChecker {
@Test @Test
public void testSuitableForHEADIfHeadResponseCachingEnabledAndEntryDoesNotSpecifyARequestMethod() { public void testSuitableForHEADIfHeadResponseCachingEnabledAndEntryDoesNotSpecifyARequestMethod() {
final HttpRequest headRequest = new BasicHttpRequest("HEAD", "/foo", HttpVersion.HTTP_1_1); final HttpRequest headRequest = new BasicHttpRequest("HEAD", "/foo");
impl = new CachedResponseSuitabilityChecker(CacheConfig.custom().build()); impl = new CachedResponseSuitabilityChecker(CacheConfig.custom().build());
final Header[] headers = { final Header[] headers = {
new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)), new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),

View File

@ -45,15 +45,14 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.impl.sync.ClientExecChain; import org.apache.hc.client5.http.impl.sync.ClientExecChain;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HeaderElements; import org.apache.hc.core5.http.HeaderElements;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
@ -61,10 +60,9 @@ import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.entity.InputStreamEntity; import org.apache.hc.core5.http.io.entity.InputStreamEntity;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicHttpResponse; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicStatusLine;
import org.easymock.EasyMock; import org.easymock.EasyMock;
import org.easymock.IExpectationSetters; import org.easymock.IExpectationSetters;
import org.junit.Assert; import org.junit.Assert;
@ -85,7 +83,7 @@ public class TestCachingExec extends TestCachingExecChain {
private CachingExec impl; private CachingExec impl;
private boolean mockedImpl; private boolean mockedImpl;
private CloseableHttpResponse mockBackendResponse; private ClassicHttpResponse mockBackendResponse;
private Date requestDate; private Date requestDate;
private Date responseDate; private Date responseDate;
@ -95,7 +93,7 @@ public class TestCachingExec extends TestCachingExecChain {
public void setUp() { public void setUp() {
super.setUp(); super.setUp();
mockBackendResponse = createNiceMock(CloseableHttpResponse.class); mockBackendResponse = createNiceMock(ClassicHttpResponse.class);
requestDate = new Date(System.currentTimeMillis() - 1000); requestDate = new Date(System.currentTimeMillis() - 1000);
responseDate = new Date(); responseDate = new Date();
@ -162,7 +160,7 @@ public class TestCachingExec extends TestCachingExecChain {
requestIsFatallyNonCompliant(null); requestIsFatallyNonCompliant(null);
replayMocks(); replayMocks();
final HttpResponse result = impl.execute(route, request, context); final HttpResponse result = impl.execute(request, context);
verifyMocks(); verifyMocks();
Assert.assertSame(mockBackendResponse, result); Assert.assertSame(mockBackendResponse, result);
@ -181,7 +179,7 @@ public class TestCachingExec extends TestCachingExecChain {
implExpectsAnyRequestAndReturn(mockBackendResponse); implExpectsAnyRequestAndReturn(mockBackendResponse);
replayMocks(); replayMocks();
final HttpResponse result = impl.execute(route, request, context); final HttpResponse result = impl.execute(request, context);
verifyMocks(); verifyMocks();
Assert.assertSame(mockBackendResponse, result); Assert.assertSame(mockBackendResponse, result);
@ -203,12 +201,11 @@ public class TestCachingExec extends TestCachingExecChain {
expect(mockConditionalRequestBuilder.buildConditionalRequest(request, mockCacheEntry)) expect(mockConditionalRequestBuilder.buildConditionalRequest(request, mockCacheEntry))
.andReturn(request); .andReturn(request);
backendExpectsRequestAndReturn(request, mockBackendResponse); backendExpectsRequestAndReturn(request, mockBackendResponse);
expect(mockBackendResponse.getProtocolVersion()).andReturn(HttpVersion.HTTP_1_1); expect(mockBackendResponse.getVersion()).andReturn(HttpVersion.HTTP_1_1).anyTimes();
expect(mockBackendResponse.getStatusLine()).andReturn( expect(mockBackendResponse.getCode()).andReturn(200);
new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "Ok"));
replayMocks(); replayMocks();
final HttpResponse result = impl.execute(route, request, context); final HttpResponse result = impl.execute(request, context);
verifyMocks(); verifyMocks();
Assert.assertSame(mockBackendResponse, result); Assert.assertSame(mockBackendResponse, result);
@ -232,14 +229,13 @@ public class TestCachingExec extends TestCachingExecChain {
mayReturnStaleWhileRevalidating(false); mayReturnStaleWhileRevalidating(false);
expect(impl.revalidateCacheEntry( expect(impl.revalidateCacheEntry(
isA(HttpRoute.class), isA(RoutedHttpRequest.class),
isA(HttpRequestWrapper.class),
isA(HttpClientContext.class), isA(HttpClientContext.class),
(HttpExecutionAware) isNull(), (HttpExecutionAware) isNull(),
isA(HttpCacheEntry.class))).andReturn(mockBackendResponse); isA(HttpCacheEntry.class))).andReturn(mockBackendResponse);
replayMocks(); replayMocks();
final HttpResponse result = impl.execute(route, request, context); final HttpResponse result = impl.execute(request, context);
verifyMocks(); verifyMocks();
Assert.assertSame(mockBackendResponse, result); Assert.assertSame(mockBackendResponse, result);
@ -252,12 +248,10 @@ public class TestCachingExec extends TestCachingExecChain {
public void testRevalidationCallsHandleBackEndResponseWhenNot200Or304() throws Exception { public void testRevalidationCallsHandleBackEndResponseWhenNot200Or304() throws Exception {
mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE); mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE);
final HttpRequestWrapper validate = HttpRequestWrapper.wrap( final RoutedHttpRequest validate = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final CloseableHttpResponse originResponse = Proxies.enhanceResponse( final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_NOT_FOUND, "Not Found");
new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_FOUND, "Not Found")); final ClassicHttpResponse finalResponse = HttpTestUtils.make200Response();
final CloseableHttpResponse finalResponse = Proxies.enhanceResponse(
HttpTestUtils.make200Response());
conditionalRequestBuilderReturns(validate); conditionalRequestBuilderReturns(validate);
getCurrentDateReturns(requestDate); getCurrentDateReturns(requestDate);
@ -272,7 +266,7 @@ public class TestCachingExec extends TestCachingExecChain {
replayMocks(); replayMocks();
final HttpResponse result = final HttpResponse result =
impl.revalidateCacheEntry(route, request, context, null, entry); impl.revalidateCacheEntry(request, context, null, entry);
verifyMocks(); verifyMocks();
Assert.assertSame(finalResponse, result); Assert.assertSame(finalResponse, result);
@ -284,10 +278,9 @@ public class TestCachingExec extends TestCachingExecChain {
mockImplMethods(GET_CURRENT_DATE); mockImplMethods(GET_CURRENT_DATE);
final HttpRequestWrapper validate = HttpRequestWrapper.wrap( final RoutedHttpRequest validate = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final HttpResponse originResponse = Proxies.enhanceResponse( final ClassicHttpResponse originResponse = HttpTestUtils.make304Response();
new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"));
final HttpCacheEntry updatedEntry = HttpTestUtils.makeCacheEntry(); final HttpCacheEntry updatedEntry = HttpTestUtils.makeCacheEntry();
conditionalRequestBuilderReturns(validate); conditionalRequestBuilderReturns(validate);
@ -306,7 +299,7 @@ public class TestCachingExec extends TestCachingExecChain {
responseIsGeneratedFromCache(); responseIsGeneratedFromCache();
replayMocks(); replayMocks();
impl.revalidateCacheEntry(route, request, context, null, entry); impl.revalidateCacheEntry(request, context, null, entry);
verifyMocks(); verifyMocks();
} }
@ -318,17 +311,16 @@ public class TestCachingExec extends TestCachingExecChain {
// Fail on an unexpected request, rather than causing a later NPE // Fail on an unexpected request, rather than causing a later NPE
EasyMock.resetToStrict(mockBackend); EasyMock.resetToStrict(mockBackend);
final HttpRequestWrapper validate = HttpRequestWrapper.wrap( final RoutedHttpRequest validate = RoutedHttpRequest.adapt(
new HttpGet("http://foo.example.com/resource"), host); new HttpGet("http://foo.example.com/resource"), route);
final HttpRequestWrapper relativeValidate = HttpRequestWrapper.wrap( final RoutedHttpRequest relativeValidate = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/resource", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/resource"), route);
final CloseableHttpResponse originResponse = Proxies.enhanceResponse( final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "Okay");
new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "Okay"));
conditionalRequestBuilderReturns(validate); conditionalRequestBuilderReturns(validate);
getCurrentDateReturns(requestDate); getCurrentDateReturns(requestDate);
final CloseableHttpResponse resp = mockBackend.execute(EasyMock.isA(HttpRoute.class), final ClassicHttpResponse resp = mockBackend.execute(
eqRequest(relativeValidate), EasyMock.isA(HttpClientContext.class), eqRequest(relativeValidate), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware> isNull()); EasyMock.<HttpExecutionAware> isNull());
expect(resp).andReturn(originResponse); expect(resp).andReturn(originResponse);
@ -336,7 +328,7 @@ public class TestCachingExec extends TestCachingExecChain {
getCurrentDateReturns(responseDate); getCurrentDateReturns(responseDate);
replayMocks(); replayMocks();
impl.revalidateCacheEntry(route, request, context, null, entry); impl.revalidateCacheEntry(request, context, null, entry);
verifyMocks(); verifyMocks();
} }
@ -344,7 +336,7 @@ public class TestCachingExec extends TestCachingExecChain {
public void testEndlessResponsesArePassedThrough() throws Exception { public void testEndlessResponsesArePassedThrough() throws Exception {
impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT);
final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
resp1.setHeader("Date", DateUtils.formatDate(new Date())); resp1.setHeader("Date", DateUtils.formatDate(new Date()));
resp1.setHeader("Server", "MockOrigin/1.0"); resp1.setHeader("Server", "MockOrigin/1.0");
resp1.setHeader(HttpHeaders.TRANSFER_ENCODING, HeaderElements.CHUNKED_ENCODING); resp1.setHeader(HttpHeaders.TRANSFER_ENCODING, HeaderElements.CHUNKED_ENCODING);
@ -374,17 +366,16 @@ public class TestCachingExec extends TestCachingExecChain {
} }
}, -1)); }, -1));
final CloseableHttpResponse resp = mockBackend.execute( final ClassicHttpResponse resp = mockBackend.execute(
EasyMock.isA(HttpRoute.class), EasyMock.isA(RoutedHttpRequest.class),
EasyMock.isA(HttpRequestWrapper.class),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull()); EasyMock.<HttpExecutionAware>isNull());
EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(resp1)); EasyMock.expect(resp).andReturn(resp1);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
replayMocks(); replayMocks();
final CloseableHttpResponse resp2 = impl.execute(route, req1, context, null); final ClassicHttpResponse resp2 = impl.execute(req1, context, null);
maxlength.set(size.get() * 2); maxlength.set(size.get() * 2);
verifyMocks(); verifyMocks();
assertTrue(HttpTestUtils.semanticallyTransparent(resp1, resp2)); assertTrue(HttpTestUtils.semanticallyTransparent(resp1, resp2));
@ -393,7 +384,7 @@ public class TestCachingExec extends TestCachingExecChain {
@Test @Test
public void testCallBackendMakesBackEndRequestAndHandlesResponse() throws Exception { public void testCallBackendMakesBackEndRequestAndHandlesResponse() throws Exception {
mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE); mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE);
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
getCurrentDateReturns(requestDate); getCurrentDateReturns(requestDate);
backendExpectsRequestAndReturn(request, resp); backendExpectsRequestAndReturn(request, resp);
getCurrentDateReturns(responseDate); getCurrentDateReturns(responseDate);
@ -401,16 +392,15 @@ public class TestCachingExec extends TestCachingExecChain {
replayMocks(); replayMocks();
impl.callBackend(route, request, context, null); impl.callBackend(request, context, null);
verifyMocks(); verifyMocks();
} }
private IExpectationSetters<CloseableHttpResponse> implExpectsAnyRequestAndReturn( private IExpectationSetters<ClassicHttpResponse> implExpectsAnyRequestAndReturn(
final CloseableHttpResponse response) throws Exception { final ClassicHttpResponse response) throws Exception {
final CloseableHttpResponse resp = impl.callBackend( final ClassicHttpResponse resp = impl.callBackend(
EasyMock.isA(HttpRoute.class), EasyMock.isA(RoutedHttpRequest.class),
EasyMock.isA(HttpRequestWrapper.class),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull()); EasyMock.<HttpExecutionAware>isNull());
return EasyMock.expect(resp).andReturn(response); return EasyMock.expect(resp).andReturn(response);
@ -430,7 +420,7 @@ public class TestCachingExec extends TestCachingExecChain {
expect(impl.getCurrentDate()).andReturn(date); expect(impl.getCurrentDate()).andReturn(date);
} }
private void handleBackendResponseReturnsResponse(final HttpRequestWrapper request, final HttpResponse response) private void handleBackendResponseReturnsResponse(final RoutedHttpRequest request, final ClassicHttpResponse response)
throws IOException { throws IOException {
expect( expect(
impl.handleBackendResponse( impl.handleBackendResponse(
@ -438,8 +428,7 @@ public class TestCachingExec extends TestCachingExecChain {
isA(HttpClientContext.class), isA(HttpClientContext.class),
isA(Date.class), isA(Date.class),
isA(Date.class), isA(Date.class),
isA(CloseableHttpResponse.class))).andReturn( isA(ClassicHttpResponse.class))).andReturn(response);
Proxies.enhanceResponse(response));
} }
private void mockImplMethods(final String... methods) { private void mockImplMethods(final String... methods) {

View File

@ -33,7 +33,7 @@ import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.core5.http.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;

View File

@ -28,20 +28,23 @@ package org.apache.hc.client5.http.impl.cache;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HeaderConstants; import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolException; import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -50,16 +53,15 @@ public class TestConditionalRequestBuilder {
private ConditionalRequestBuilder impl; private ConditionalRequestBuilder impl;
private HttpHost host; private HttpHost host;
private HttpRequestWrapper request; private HttpRoute route;
private HttpCacheEntry entry; private RoutedHttpRequest request;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
impl = new ConditionalRequestBuilder(); impl = new ConditionalRequestBuilder();
host = new HttpHost("foo.example.com", 80); host = new HttpHost("foo.example.com", 80);
request = HttpRequestWrapper.wrap( route = new HttpRoute(host);
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("GET", "/"), route);
entry = HttpTestUtils.makeCacheEntry();
} }
@Test @Test
@ -68,23 +70,21 @@ public class TestConditionalRequestBuilder {
final String theUri = "/theuri"; final String theUri = "/theuri";
final String lastModified = "this is my last modified date"; final String lastModified = "this is my last modified date";
final HttpRequest basicRequest = new BasicHttpRequest(theMethod, theUri); final ClassicHttpRequest basicRequest = new BasicClassicHttpRequest(theMethod, theUri);
basicRequest.addHeader("Accept-Encoding", "gzip"); basicRequest.addHeader("Accept-Encoding", "gzip");
final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest, host); final RoutedHttpRequest requestWrapper = RoutedHttpRequest.adapt(basicRequest, route);
final Header[] headers = new Header[] { final Header[] headers = new Header[] {
new BasicHeader("Date", DateUtils.formatDate(new Date())), new BasicHeader("Date", DateUtils.formatDate(new Date())),
new BasicHeader("Last-Modified", lastModified) }; new BasicHeader("Last-Modified", lastModified) };
final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers); final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers);
final HttpRequestWrapper newRequest = impl.buildConditionalRequest(requestWrapper, cacheEntry); final RoutedHttpRequest newRequest = impl.buildConditionalRequest(requestWrapper, cacheEntry);
Assert.assertNotSame(basicRequest, newRequest); Assert.assertNotSame(basicRequest, newRequest);
Assert.assertEquals(theMethod, newRequest.getRequestLine().getMethod()); Assert.assertEquals(theMethod, newRequest.getMethod());
Assert.assertEquals(theUri, newRequest.getRequestLine().getUri()); Assert.assertEquals(theUri, newRequest.getRequestUri());
Assert.assertEquals(basicRequest.getRequestLine().getProtocolVersion(), newRequest
.getRequestLine().getProtocolVersion());
Assert.assertEquals(2, newRequest.getAllHeaders().length); Assert.assertEquals(2, newRequest.getAllHeaders().length);
Assert.assertEquals("Accept-Encoding", newRequest.getAllHeaders()[0].getName()); Assert.assertEquals("Accept-Encoding", newRequest.getAllHeaders()[0].getName());
@ -107,10 +107,10 @@ public class TestConditionalRequestBuilder {
new BasicHeader("Last-Modified", lmDate), new BasicHeader("Last-Modified", lmDate),
new BasicHeader("ETag", etag) new BasicHeader("ETag", etag)
}; };
final HttpRequest basicRequest = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); final ClassicHttpRequest basicRequest = new BasicClassicHttpRequest("GET", "/");
final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest, host); final RoutedHttpRequest requestWrapper = RoutedHttpRequest.adapt(basicRequest, route);
final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers); final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers);
final HttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry); final ClassicHttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry);
Assert.assertEquals(lmDate, Assert.assertEquals(lmDate,
result.getFirstHeader("If-Modified-Since").getValue()); result.getFirstHeader("If-Modified-Since").getValue());
Assert.assertEquals(etag, Assert.assertEquals(etag,
@ -123,9 +123,9 @@ public class TestConditionalRequestBuilder {
final String theUri = "/theuri"; final String theUri = "/theuri";
final String theETag = "this is my eTag"; final String theETag = "this is my eTag";
final HttpRequest basicRequest = new BasicHttpRequest(theMethod, theUri); final ClassicHttpRequest basicRequest = new BasicClassicHttpRequest(theMethod, theUri);
basicRequest.addHeader("Accept-Encoding", "gzip"); basicRequest.addHeader("Accept-Encoding", "gzip");
final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest, host); final RoutedHttpRequest requestWrapper = RoutedHttpRequest.adapt(basicRequest, route);
final Header[] headers = new Header[] { final Header[] headers = new Header[] {
new BasicHeader("Date", DateUtils.formatDate(new Date())), new BasicHeader("Date", DateUtils.formatDate(new Date())),
@ -134,14 +134,12 @@ public class TestConditionalRequestBuilder {
final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers); final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers);
final HttpRequest newRequest = impl.buildConditionalRequest(requestWrapper, cacheEntry); final ClassicHttpRequest newRequest = impl.buildConditionalRequest(requestWrapper, cacheEntry);
Assert.assertNotSame(basicRequest, newRequest); Assert.assertNotSame(basicRequest, newRequest);
Assert.assertEquals(theMethod, newRequest.getRequestLine().getMethod()); Assert.assertEquals(theMethod, newRequest.getMethod());
Assert.assertEquals(theUri, newRequest.getRequestLine().getUri()); Assert.assertEquals(theUri, newRequest.getRequestUri());
Assert.assertEquals(basicRequest.getRequestLine().getProtocolVersion(), newRequest
.getRequestLine().getProtocolVersion());
Assert.assertEquals(3, newRequest.getAllHeaders().length); Assert.assertEquals(3, newRequest.getAllHeaders().length);
@ -154,8 +152,8 @@ public class TestConditionalRequestBuilder {
@Test @Test
public void testCacheEntryWithMustRevalidateDoesEndToEndRevalidation() throws Exception { public void testCacheEntryWithMustRevalidateDoesEndToEndRevalidation() throws Exception {
final HttpRequest basicRequest = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); final ClassicHttpRequest basicRequest = new BasicClassicHttpRequest("GET","/");
final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest, host); final RoutedHttpRequest requestWrapper = RoutedHttpRequest.adapt(basicRequest, route);
final Date now = new Date(); final Date now = new Date();
final Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L); final Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L);
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
@ -167,15 +165,15 @@ public class TestConditionalRequestBuilder {
new BasicHeader("Cache-Control","max-age=5, must-revalidate") }; new BasicHeader("Cache-Control","max-age=5, must-revalidate") };
final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(elevenSecondsAgo, nineSecondsAgo, cacheEntryHeaders); final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(elevenSecondsAgo, nineSecondsAgo, cacheEntryHeaders);
final HttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry); final ClassicHttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry);
boolean foundMaxAge0 = false; boolean foundMaxAge0 = false;
for(final Header h : result.getHeaders("Cache-Control")) {
for(final HeaderElement elt : h.getElements()) { final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.CACHE_CONTROL);
if ("max-age".equalsIgnoreCase(elt.getName()) while (it.hasNext()) {
&& "0".equals(elt.getValue())) { final HeaderElement elt = it.next();
foundMaxAge0 = true; if ("max-age".equalsIgnoreCase(elt.getName()) && "0".equals(elt.getValue())) {
} foundMaxAge0 = true;
} }
} }
Assert.assertTrue(foundMaxAge0); Assert.assertTrue(foundMaxAge0);
@ -183,8 +181,8 @@ public class TestConditionalRequestBuilder {
@Test @Test
public void testCacheEntryWithProxyRevalidateDoesEndToEndRevalidation() throws Exception { public void testCacheEntryWithProxyRevalidateDoesEndToEndRevalidation() throws Exception {
final HttpRequest basicRequest = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); final ClassicHttpRequest basicRequest = new BasicClassicHttpRequest("GET", "/");
final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest, host); final RoutedHttpRequest requestWrapper = RoutedHttpRequest.adapt(basicRequest, route);
final Date now = new Date(); final Date now = new Date();
final Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L); final Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L);
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
@ -196,15 +194,14 @@ public class TestConditionalRequestBuilder {
new BasicHeader("Cache-Control","max-age=5, proxy-revalidate") }; new BasicHeader("Cache-Control","max-age=5, proxy-revalidate") };
final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(elevenSecondsAgo, nineSecondsAgo, cacheEntryHeaders); final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(elevenSecondsAgo, nineSecondsAgo, cacheEntryHeaders);
final HttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry); final ClassicHttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry);
boolean foundMaxAge0 = false; boolean foundMaxAge0 = false;
for(final Header h : result.getHeaders("Cache-Control")) { final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.CACHE_CONTROL);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if ("max-age".equalsIgnoreCase(elt.getName()) final HeaderElement elt = it.next();
&& "0".equals(elt.getValue())) { if ("max-age".equalsIgnoreCase(elt.getName()) && "0".equals(elt.getValue())) {
foundMaxAge0 = true; foundMaxAge0 = true;
}
} }
} }
Assert.assertTrue(foundMaxAge0); Assert.assertTrue(foundMaxAge0);
@ -213,36 +210,36 @@ public class TestConditionalRequestBuilder {
@Test @Test
public void testBuildUnconditionalRequestUsesGETMethod() public void testBuildUnconditionalRequestUsesGETMethod()
throws Exception { throws Exception {
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertEquals("GET", result.getRequestLine().getMethod()); Assert.assertEquals("GET", result.getMethod());
} }
@Test @Test
public void testBuildUnconditionalRequestUsesRequestUri() public void testBuildUnconditionalRequestUsesRequestUri()
throws Exception { throws Exception {
final String uri = "/theURI"; final String uri = "/theURI";
request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", uri, HttpVersion.HTTP_1_1), host); request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("GET", uri), route);
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertEquals(uri, result.getRequestLine().getUri()); Assert.assertEquals(uri, result.getRequestUri());
} }
@Test @Test
public void testBuildUnconditionalRequestUsesHTTP_1_1() public void testBuildUnconditionalRequestUsesHTTP_1_1()
throws Exception { throws Exception {
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion()); Assert.assertEquals(HttpVersion.HTTP_1_1, result.getVersion());
} }
@Test @Test
public void testBuildUnconditionalRequestAddsCacheControlNoCache() public void testBuildUnconditionalRequestAddsCacheControlNoCache()
throws Exception { throws Exception {
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
boolean ccNoCacheFound = false; boolean ccNoCacheFound = false;
for(final Header h : result.getHeaders("Cache-Control")) { final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.CACHE_CONTROL);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if ("no-cache".equals(elt.getName())) { final HeaderElement elt = it.next();
ccNoCacheFound = true; if ("no-cache".equals(elt.getName())) {
} ccNoCacheFound = true;
} }
} }
Assert.assertTrue(ccNoCacheFound); Assert.assertTrue(ccNoCacheFound);
@ -251,13 +248,13 @@ public class TestConditionalRequestBuilder {
@Test @Test
public void testBuildUnconditionalRequestAddsPragmaNoCache() public void testBuildUnconditionalRequestAddsPragmaNoCache()
throws Exception { throws Exception {
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
boolean ccNoCacheFound = false; boolean ccNoCacheFound = false;
for(final Header h : result.getHeaders("Pragma")) { final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.PRAGMA);
for(final HeaderElement elt : h.getElements()) { while (it.hasNext()) {
if ("no-cache".equals(elt.getName())) { final HeaderElement elt = it.next();
ccNoCacheFound = true; if ("no-cache".equals(elt.getName())) {
} ccNoCacheFound = true;
} }
} }
Assert.assertTrue(ccNoCacheFound); Assert.assertTrue(ccNoCacheFound);
@ -267,7 +264,7 @@ public class TestConditionalRequestBuilder {
public void testBuildUnconditionalRequestDoesNotUseIfRange() public void testBuildUnconditionalRequestDoesNotUseIfRange()
throws Exception { throws Exception {
request.addHeader("If-Range","\"etag\""); request.addHeader("If-Range","\"etag\"");
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertNull(result.getFirstHeader("If-Range")); Assert.assertNull(result.getFirstHeader("If-Range"));
} }
@ -275,7 +272,7 @@ public class TestConditionalRequestBuilder {
public void testBuildUnconditionalRequestDoesNotUseIfMatch() public void testBuildUnconditionalRequestDoesNotUseIfMatch()
throws Exception { throws Exception {
request.addHeader("If-Match","\"etag\""); request.addHeader("If-Match","\"etag\"");
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertNull(result.getFirstHeader("If-Match")); Assert.assertNull(result.getFirstHeader("If-Match"));
} }
@ -283,7 +280,7 @@ public class TestConditionalRequestBuilder {
public void testBuildUnconditionalRequestDoesNotUseIfNoneMatch() public void testBuildUnconditionalRequestDoesNotUseIfNoneMatch()
throws Exception { throws Exception {
request.addHeader("If-None-Match","\"etag\""); request.addHeader("If-None-Match","\"etag\"");
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertNull(result.getFirstHeader("If-None-Match")); Assert.assertNull(result.getFirstHeader("If-None-Match"));
} }
@ -291,7 +288,7 @@ public class TestConditionalRequestBuilder {
public void testBuildUnconditionalRequestDoesNotUseIfUnmodifiedSince() public void testBuildUnconditionalRequestDoesNotUseIfUnmodifiedSince()
throws Exception { throws Exception {
request.addHeader("If-Unmodified-Since", DateUtils.formatDate(new Date())); request.addHeader("If-Unmodified-Since", DateUtils.formatDate(new Date()));
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertNull(result.getFirstHeader("If-Unmodified-Since")); Assert.assertNull(result.getFirstHeader("If-Unmodified-Since"));
} }
@ -299,7 +296,7 @@ public class TestConditionalRequestBuilder {
public void testBuildUnconditionalRequestDoesNotUseIfModifiedSince() public void testBuildUnconditionalRequestDoesNotUseIfModifiedSince()
throws Exception { throws Exception {
request.addHeader("If-Modified-Since", DateUtils.formatDate(new Date())); request.addHeader("If-Modified-Since", DateUtils.formatDate(new Date()));
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertNull(result.getFirstHeader("If-Modified-Since")); Assert.assertNull(result.getFirstHeader("If-Modified-Since"));
} }
@ -307,7 +304,7 @@ public class TestConditionalRequestBuilder {
public void testBuildUnconditionalRequestCarriesOtherRequestHeaders() public void testBuildUnconditionalRequestCarriesOtherRequestHeaders()
throws Exception { throws Exception {
request.addHeader("User-Agent","MyBrowser/1.0"); request.addHeader("User-Agent","MyBrowser/1.0");
final HttpRequest result = impl.buildUnconditionalRequest(request, entry); final ClassicHttpRequest result = impl.buildUnconditionalRequest(request);
Assert.assertEquals("MyBrowser/1.0", Assert.assertEquals("MyBrowser/1.0",
result.getFirstHeader("User-Agent").getValue()); result.getFirstHeader("User-Agent").getValue());
} }
@ -323,7 +320,7 @@ public class TestConditionalRequestBuilder {
variantEntries.put(etag2, new Variant("C","D",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag2) }))); variantEntries.put(etag2, new Variant("C","D",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag2) })));
variantEntries.put(etag3, new Variant("E","F",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag3) }))); variantEntries.put(etag3, new Variant("E","F",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag3) })));
final HttpRequest conditional = impl.buildConditionalRequestFromVariants(request, variantEntries); final ClassicHttpRequest conditional = impl.buildConditionalRequestFromVariants(request, variantEntries);
// seems like a lot of work, but necessary, check for existence and exclusiveness // seems like a lot of work, but necessary, check for existence and exclusiveness
String ifNoneMatch = conditional.getFirstHeader(HeaderConstants.IF_NONE_MATCH).getValue(); String ifNoneMatch = conditional.getFirstHeader(HeaderConstants.IF_NONE_MATCH).getValue();

View File

@ -35,10 +35,10 @@ import java.util.concurrent.TimeUnit;
import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.impl.sync.ClientExecChain; import org.apache.hc.client5.http.impl.sync.ClientExecChain;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -160,10 +160,10 @@ public class TestExponentialBackingOffSchedulingStrategy {
final CachingExec cachingHttpClient = new CachingExec(clientExecChain); final CachingExec cachingHttpClient = new CachingExec(clientExecChain);
final AsynchronousValidator mockValidator = new AsynchronousValidator(impl); final AsynchronousValidator mockValidator = new AsynchronousValidator(impl);
final HttpHost host = new HttpHost("foo.example.com", 80); final HttpHost host = new HttpHost("foo.example.com", 80);
final HttpRoute httpRoute = new HttpRoute(host); final HttpRoute route = new HttpRoute(host);
final HttpRequestWrapper httpRequestWrapper = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/"), host); final RoutedHttpRequest routedHttpRequest = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("GET", "/"), route);
final HttpClientContext httpClientContext = new HttpClientContext(); final HttpClientContext httpClientContext = new HttpClientContext();
return new AsynchronousValidationRequest(mockValidator, cachingHttpClient, httpRoute, httpRequestWrapper, return new AsynchronousValidationRequest(mockValidator, cachingHttpClient, routedHttpRequest,
httpClientContext, null, null, "identifier", errorCount); httpClientContext, null, null, "identifier", errorCount);
} }

View File

@ -39,15 +39,12 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.hc.client5.http.cache.HeaderConstants;
import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer; import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer;
import org.apache.hc.client5.http.cache.Resource; import org.apache.hc.client5.http.cache.Resource;
import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.StatusLine;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicStatusLine;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -87,14 +84,12 @@ public class TestHttpCacheEntrySerializers {
} }
final String body = "Lorem ipsum dolor sit amet"; final String body = "Lorem ipsum dolor sit amet";
final ProtocolVersion pvObj = new ProtocolVersion("HTTP", 1, 1);
final StatusLine slObj = new BasicStatusLine(pvObj, 200, "ok");
final Map<String,String> variantMap = new HashMap<>(); final Map<String,String> variantMap = new HashMap<>();
variantMap.put("test variant 1","true"); variantMap.put("test variant 1","true");
variantMap.put("test variant 2","true"); variantMap.put("test variant 2","true");
final HttpCacheEntry cacheEntry = new HttpCacheEntry(new Date(), new Date(), final HttpCacheEntry cacheEntry = new HttpCacheEntry(new Date(), new Date(),
slObj, headers, new HeapResource(Base64.decodeBase64(body HttpStatus.SC_OK, headers,
.getBytes(UTF8))), variantMap, HeaderConstants.GET_METHOD); new HeapResource(Base64.decodeBase64(body.getBytes(UTF8))), variantMap);
return cacheEntry; return cacheEntry;
} }
@ -109,9 +104,6 @@ public class TestHttpCacheEntrySerializers {
.getResponseDate().getTime() / 1000))) { .getResponseDate().getTime() / 1000))) {
return false; return false;
} }
if (!one.getProtocolVersion().equals(two.getProtocolVersion())) {
return false;
}
final byte[] onesByteArray = resourceToBytes(one.getResource()); final byte[] onesByteArray = resourceToBytes(one.getResource());
final byte[] twosByteArray = resourceToBytes(two.getResource()); final byte[] twosByteArray = resourceToBytes(two.getResource());

View File

@ -26,7 +26,6 @@
*/ */
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA; import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset; import static org.mockito.Mockito.reset;
@ -42,13 +41,12 @@ import org.apache.hc.client5.http.cache.ResourceFactory;
import org.apache.hc.client5.http.impl.sync.ClientExecChain; import org.apache.hc.client5.http.impl.sync.ClientExecChain;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.message.BasicHttpResponse;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -95,17 +93,15 @@ public class TestHttpCacheJiraNumber1147 {
final HttpCacheStorage httpCacheStorage = new ManagedHttpCacheStorage(cacheConfig); final HttpCacheStorage httpCacheStorage = new ManagedHttpCacheStorage(cacheConfig);
final ClientExecChain backend = mock(ClientExecChain.class); final ClientExecChain backend = mock(ClientExecChain.class);
final HttpRequestWrapper get = HttpRequestWrapper.wrap(new HttpGet("http://somehost/"), new HttpHost("somehost"));
final HttpClientContext context = HttpClientContext.create();
final HttpHost target = new HttpHost("somehost", 80); final HttpHost target = new HttpHost("somehost", 80);
final HttpRoute route = new HttpRoute(target); final HttpRoute route = new HttpRoute(target);
final RoutedHttpRequest get = RoutedHttpRequest.adapt(new HttpGet("http://somehost/"), route);
context.setTargetHost(target); final HttpClientContext context = HttpClientContext.create();
final Date now = new Date(); final Date now = new Date();
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK"); final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
response.setEntity(HttpTestUtils.makeBody(128)); response.setEntity(HttpTestUtils.makeBody(128));
response.setHeader("Content-Length", "128"); response.setHeader("Content-Length", "128");
response.setHeader("ETag", "\"etag\""); response.setHeader("ETag", "\"etag\"");
@ -113,21 +109,19 @@ public class TestHttpCacheJiraNumber1147 {
response.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); response.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo));
when(backend.execute( when(backend.execute(
eq(route), isA(RoutedHttpRequest.class),
isA(HttpRequestWrapper.class),
isA(HttpClientContext.class), isA(HttpClientContext.class),
(HttpExecutionAware) Matchers.isNull())).thenReturn(Proxies.enhanceResponse(response)); (HttpExecutionAware) Matchers.isNull())).thenReturn(response);
final BasicHttpCache cache = new BasicHttpCache(resourceFactory, httpCacheStorage, cacheConfig); final BasicHttpCache cache = new BasicHttpCache(resourceFactory, httpCacheStorage, cacheConfig);
final ClientExecChain t = createCachingExecChain(backend, cache, cacheConfig); final ClientExecChain t = createCachingExecChain(backend, cache, cacheConfig);
final HttpResponse response1 = t.execute(route, get, context, null); final ClassicHttpResponse response1 = t.execute(get, context, null);
Assert.assertEquals(200, response1.getStatusLine().getStatusCode()); Assert.assertEquals(200, response1.getCode());
IOUtils.consume(response1.getEntity()); IOUtils.consume(response1.getEntity());
verify(backend).execute( verify(backend).execute(
eq(route), isA(RoutedHttpRequest.class),
isA(HttpRequestWrapper.class),
isA(HttpClientContext.class), isA(HttpClientContext.class),
(HttpExecutionAware) Matchers.isNull()); (HttpExecutionAware) Matchers.isNull());
@ -135,18 +129,16 @@ public class TestHttpCacheJiraNumber1147 {
reset(backend); reset(backend);
when(backend.execute( when(backend.execute(
eq(route), isA(RoutedHttpRequest.class),
isA(HttpRequestWrapper.class),
isA(HttpClientContext.class), isA(HttpClientContext.class),
(HttpExecutionAware) Matchers.isNull())).thenReturn(Proxies.enhanceResponse(response)); (HttpExecutionAware) Matchers.isNull())).thenReturn(response);
final HttpResponse response2 = t.execute(route, get, context, null); final ClassicHttpResponse response2 = t.execute(get, context, null);
Assert.assertEquals(200, response2.getStatusLine().getStatusCode()); Assert.assertEquals(200, response2.getCode());
IOUtils.consume(response2.getEntity()); IOUtils.consume(response2.getEntity());
verify(backend).execute( verify(backend).execute(
eq(route), isA(RoutedHttpRequest.class),
isA(HttpRequestWrapper.class),
isA(HttpClientContext.class), isA(HttpClientContext.class),
(HttpExecutionAware) Matchers.isNull()); (HttpExecutionAware) Matchers.isNull());
} }

View File

@ -29,27 +29,25 @@ package org.apache.hc.client5.http.impl.cache;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.util.Date; import java.util.Date;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
/** /**
* This class tests behavior that is allowed (MAY) by the HTTP/1.1 protocol * This class tests behavior that is allowed (MAY) by the HTTP/1.1 protocol
* specification and for which we have implemented the behavior in the * specification and for which we have implemented the behavior in HTTP cache.
* {@link CachingHttpClient}.
*/ */
public class TestProtocolAllowedBehavior extends AbstractProtocolTest { public class TestProtocolAllowedBehavior extends AbstractProtocolTest {
@Test @Test
public void testNonSharedCacheReturnsStaleResponseWhenRevalidationFailsForProxyRevalidate() public void testNonSharedCacheReturnsStaleResponseWhenRevalidationFailsForProxyRevalidate()
throws Exception { throws Exception {
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap( final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET","/"), route);
final Date now = new Date(); final Date now = new Date();
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
originResponse.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); originResponse.setHeader("Date", DateUtils.formatDate(tenSecondsAgo));
@ -58,38 +56,38 @@ public class TestProtocolAllowedBehavior extends AbstractProtocolTest {
backendExpectsAnyRequest().andReturn(originResponse); backendExpectsAnyRequest().andReturn(originResponse);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap( final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET","/"), route);
backendExpectsAnyRequest().andThrow(new SocketTimeoutException()); backendExpectsAnyRequest().andThrow(new SocketTimeoutException());
replayMocks(); replayMocks();
behaveAsNonSharedCache(); behaveAsNonSharedCache();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final HttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); Assert.assertEquals(HttpStatus.SC_OK, result.getCode());
} }
@Test @Test
public void testNonSharedCacheMayCacheResponsesWithCacheControlPrivate() public void testNonSharedCacheMayCacheResponsesWithCacheControlPrivate()
throws Exception { throws Exception {
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap( final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET","/"), route);
originResponse.setHeader("Cache-Control","private,max-age=3600"); originResponse.setHeader("Cache-Control","private,max-age=3600");
backendExpectsAnyRequest().andReturn(originResponse); backendExpectsAnyRequest().andReturn(originResponse);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap( final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET","/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET","/"), route);
replayMocks(); replayMocks();
behaveAsNonSharedCache(); behaveAsNonSharedCache();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final HttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); Assert.assertEquals(HttpStatus.SC_OK, result.getCode());
} }
} }

View File

@ -32,21 +32,22 @@ import java.util.Random;
import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HttpCacheContext; import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.impl.sync.ClientExecChain; import org.apache.hc.client5.http.impl.sync.ClientExecChain;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpExecutionAware; import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.ClientProtocolException; import org.apache.hc.client5.http.protocol.ClientProtocolException;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.entity.ByteArrayEntity; import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicHttpResponse; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.easymock.Capture; import org.easymock.Capture;
import org.easymock.EasyMock; import org.easymock.EasyMock;
import org.junit.Assert; import org.junit.Assert;
@ -83,9 +84,9 @@ public class TestProtocolDeviations {
private HttpEntity mockEntity; private HttpEntity mockEntity;
private ClientExecChain mockBackend; private ClientExecChain mockBackend;
private HttpCache mockCache; private HttpCache mockCache;
private HttpRequest request; private ClassicHttpRequest request;
private HttpCacheContext context; private HttpCacheContext context;
private CloseableHttpResponse originResponse; private ClassicHttpResponse originResponse;
private ClientExecChain impl; private ClientExecChain impl;
@ -97,12 +98,11 @@ public class TestProtocolDeviations {
body = makeBody(entityLength); body = makeBody(entityLength);
request = new BasicHttpRequest("GET", "/foo", HTTP_1_1); request = new BasicClassicHttpRequest("GET", "/foo");
context = HttpCacheContext.create(); context = HttpCacheContext.create();
context.setTargetHost(host);
originResponse = Proxies.enhanceResponse(make200Response()); originResponse = make200Response();
final CacheConfig config = CacheConfig.custom() final CacheConfig config = CacheConfig.custom()
.setMaxCacheEntries(MAX_ENTRIES) .setMaxCacheEntries(MAX_ENTRIES)
@ -122,8 +122,8 @@ public class TestProtocolDeviations {
return new CachingExec(backend, cache, config); return new CachingExec(backend, cache, config);
} }
private HttpResponse make200Response() { private ClassicHttpResponse make200Response() {
final HttpResponse out = new BasicHttpResponse(HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse out = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
out.setHeader("Date", DateUtils.formatDate(new Date())); out.setHeader("Date", DateUtils.formatDate(new Date()));
out.setHeader("Server", "MockOrigin/1.0"); out.setHeader("Server", "MockOrigin/1.0");
out.setEntity(makeBody(128)); out.setEntity(makeBody(128));
@ -172,19 +172,16 @@ public class TestProtocolDeviations {
*/ */
@Ignore @Ignore
public void testHTTP1_1RequestsWithBodiesOfKnownLengthMustHaveContentLength() throws Exception { public void testHTTP1_1RequestsWithBodiesOfKnownLengthMustHaveContentLength() throws Exception {
final BasicHttpRequest post = new BasicHttpRequest("POST", "/", final ClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
HTTP_1_1);
post.setEntity(mockEntity); post.setEntity(mockEntity);
replayMocks(); replayMocks();
final HttpResponse response = impl.execute(route, HttpRequestWrapper.wrap(post, host), context, null); final HttpResponse response = impl.execute(RoutedHttpRequest.adapt(post, route), context, null);
verifyMocks(); verifyMocks();
Assert Assert.assertEquals(HttpStatus.SC_LENGTH_REQUIRED, response.getCode());
.assertEquals(HttpStatus.SC_LENGTH_REQUIRED, response.getStatusLine()
.getStatusCode());
} }
/* /*
@ -213,8 +210,7 @@ public class TestProtocolDeviations {
@Ignore @Ignore
public void testHTTP1_1RequestsWithUnknownBodyLengthAreRejectedOrHaveContentLengthAdded() public void testHTTP1_1RequestsWithUnknownBodyLengthAreRejectedOrHaveContentLengthAdded()
throws Exception { throws Exception {
final BasicHttpRequest post = new BasicHttpRequest("POST", "/", final ClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
HTTP_1_1);
final byte[] bytes = new byte[128]; final byte[] bytes = new byte[128];
new Random().nextBytes(bytes); new Random().nextBytes(bytes);
@ -224,10 +220,9 @@ public class TestProtocolDeviations {
org.easymock.EasyMock.expect(mockBody.getContentLength()).andReturn(-1L).anyTimes(); org.easymock.EasyMock.expect(mockBody.getContentLength()).andReturn(-1L).anyTimes();
post.setEntity(mockBody); post.setEntity(mockBody);
final Capture<HttpRequestWrapper> reqCap = new Capture<>(); final Capture<RoutedHttpRequest> reqCap = new Capture<>();
EasyMock.expect( EasyMock.expect(
mockBackend.execute( mockBackend.execute(
EasyMock.eq(route),
EasyMock.capture(reqCap), EasyMock.capture(reqCap),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull())).andReturn( EasyMock.<HttpExecutionAware>isNull())).andReturn(
@ -236,7 +231,7 @@ public class TestProtocolDeviations {
replayMocks(); replayMocks();
EasyMock.replay(mockBody); EasyMock.replay(mockBody);
final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(post, host), context, null); final HttpResponse result = impl.execute(RoutedHttpRequest.adapt(post, route), context, null);
verifyMocks(); verifyMocks();
EasyMock.verify(mockBody); EasyMock.verify(mockBody);
@ -246,7 +241,7 @@ public class TestProtocolDeviations {
final HttpRequest forwarded = reqCap.getValue(); final HttpRequest forwarded = reqCap.getValue();
Assert.assertNotNull(forwarded.getFirstHeader("Content-Length")); Assert.assertNotNull(forwarded.getFirstHeader("Content-Length"));
} else { } else {
final int status = result.getStatusLine().getStatusCode(); final int status = result.getCode();
Assert.assertTrue(HttpStatus.SC_LENGTH_REQUIRED == status Assert.assertTrue(HttpStatus.SC_LENGTH_REQUIRED == status
|| HttpStatus.SC_BAD_REQUEST == status); || HttpStatus.SC_BAD_REQUEST == status);
} }
@ -261,25 +256,23 @@ public class TestProtocolDeviations {
*/ */
@Test @Test
public void testOPTIONSRequestsWithBodiesAndNoContentTypeHaveOneSupplied() throws Exception { public void testOPTIONSRequestsWithBodiesAndNoContentTypeHaveOneSupplied() throws Exception {
final BasicHttpRequest options = new BasicHttpRequest("OPTIONS", final ClassicHttpRequest options = new BasicClassicHttpRequest("OPTIONS", "/");
"/", HTTP_1_1);
options.setEntity(body); options.setEntity(body);
options.setHeader("Content-Length", "1"); options.setHeader("Content-Length", "1");
final Capture<HttpRequestWrapper> reqCap = new Capture<>(); final Capture<RoutedHttpRequest> reqCap = new Capture<>();
EasyMock.expect( EasyMock.expect(
mockBackend.execute( mockBackend.execute(
EasyMock.eq(route),
EasyMock.capture(reqCap), EasyMock.capture(reqCap),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse); EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
replayMocks(); replayMocks();
impl.execute(route, HttpRequestWrapper.wrap(options, host), context, null); impl.execute(RoutedHttpRequest.adapt(options, route), context, null);
verifyMocks(); verifyMocks();
final HttpRequest reqWithBody = reqCap.getValue(); final ClassicHttpRequest reqWithBody = reqCap.getValue();
final HttpEntity reqBody = reqWithBody.getEntity(); final HttpEntity reqBody = reqWithBody.getEntity();
Assert.assertNotNull(reqBody); Assert.assertNotNull(reqBody);
Assert.assertNotNull(reqBody.getContentType()); Assert.assertNotNull(reqBody.getContentType());
@ -300,24 +293,20 @@ public class TestProtocolDeviations {
// this situation, but it better not just pass the response // this situation, but it better not just pass the response
// on. // on.
request.removeHeaders("Range"); request.removeHeaders("Range");
originResponse = Proxies.enhanceResponse( originResponse = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
new BasicHttpResponse(HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT,
"Partial Content"));
originResponse.setHeader("Content-Range", "bytes 0-499/1234"); originResponse.setHeader("Content-Range", "bytes 0-499/1234");
originResponse.setEntity(makeBody(500)); originResponse.setEntity(makeBody(500));
EasyMock.expect( EasyMock.expect(
mockBackend.execute( mockBackend.execute(
EasyMock.eq(route), EasyMock.isA(RoutedHttpRequest.class),
EasyMock.isA(HttpRequestWrapper.class),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse); EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
replayMocks(); replayMocks();
try { try {
final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request, host), context, null); final HttpResponse result = impl.execute(RoutedHttpRequest.adapt(request, route), context, null);
Assert.assertTrue(HttpStatus.SC_PARTIAL_CONTENT != result.getStatusLine() Assert.assertTrue(HttpStatus.SC_PARTIAL_CONTENT != result.getCode());
.getStatusCode());
} catch (final ClientProtocolException acceptableBehavior) { } catch (final ClientProtocolException acceptableBehavior) {
// this is probably ok // this is probably ok
} }
@ -333,17 +322,15 @@ public class TestProtocolDeviations {
@Test @Test
public void testPassesOnOrigin401ResponseWithoutWWWAuthenticateHeader() throws Exception { public void testPassesOnOrigin401ResponseWithoutWWWAuthenticateHeader() throws Exception {
originResponse = Proxies.enhanceResponse( originResponse = new BasicClassicHttpResponse(401, "Unauthorized");
new BasicHttpResponse(HTTP_1_1, 401, "Unauthorized"));
EasyMock.expect( EasyMock.expect(
mockBackend.execute( mockBackend.execute(
EasyMock.eq(route), EasyMock.isA(RoutedHttpRequest.class),
EasyMock.isA(HttpRequestWrapper.class),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse); EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
replayMocks(); replayMocks();
final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request, host), context, null); final HttpResponse result = impl.execute(RoutedHttpRequest.adapt(request, route), context, null);
verifyMocks(); verifyMocks();
Assert.assertSame(originResponse, result); Assert.assertSame(originResponse, result);
} }
@ -356,17 +343,15 @@ public class TestProtocolDeviations {
*/ */
@Test @Test
public void testPassesOnOrigin405WithoutAllowHeader() throws Exception { public void testPassesOnOrigin405WithoutAllowHeader() throws Exception {
originResponse = Proxies.enhanceResponse( originResponse = new BasicClassicHttpResponse(405, "Method Not Allowed");
new BasicHttpResponse(HTTP_1_1, 405, "Method Not Allowed"));
EasyMock.expect( EasyMock.expect(
mockBackend.execute( mockBackend.execute(
EasyMock.eq(route), EasyMock.isA(RoutedHttpRequest.class),
EasyMock.isA(HttpRequestWrapper.class),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse); EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
replayMocks(); replayMocks();
final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request, host), context, null); final HttpResponse result = impl.execute(RoutedHttpRequest.adapt(request, route), context, null);
verifyMocks(); verifyMocks();
Assert.assertSame(originResponse, result); Assert.assertSame(originResponse, result);
} }
@ -380,17 +365,15 @@ public class TestProtocolDeviations {
*/ */
@Test @Test
public void testPassesOnOrigin407WithoutAProxyAuthenticateHeader() throws Exception { public void testPassesOnOrigin407WithoutAProxyAuthenticateHeader() throws Exception {
originResponse = Proxies.enhanceResponse( originResponse = new BasicClassicHttpResponse(407, "Proxy Authentication Required");
new BasicHttpResponse(HTTP_1_1, 407, "Proxy Authentication Required"));
EasyMock.expect( EasyMock.expect(
mockBackend.execute( mockBackend.execute(
EasyMock.eq(route), EasyMock.isA(RoutedHttpRequest.class),
EasyMock.isA(HttpRequestWrapper.class),
EasyMock.isA(HttpClientContext.class), EasyMock.isA(HttpClientContext.class),
EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse); EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
replayMocks(); replayMocks();
final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request, host), context, null); final HttpResponse result = impl.execute(RoutedHttpRequest.adapt(request, route), context, null);
verifyMocks(); verifyMocks();
Assert.assertSame(originResponse, result); Assert.assertSame(originResponse, result);
} }

View File

@ -33,15 +33,14 @@ import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.Date; import java.util.Date;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.utils.DateUtils; 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.Header;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.io.entity.InputStreamEntity;
import org.apache.hc.core5.http.entity.InputStreamEntity; import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.junit.Test; import org.junit.Test;
/** /**
@ -70,20 +69,20 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
public void testStaleIfErrorInResponseIsTrueReturnsStaleEntryWithWarning() public void testStaleIfErrorInResponseIsTrueReturnsStaleEntryWithWarning()
throws Exception{ throws Exception{
final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5, stale-if-error=60"); "public, max-age=5, stale-if-error=60");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
HttpTestUtils.assert110WarningFound(result); HttpTestUtils.assert110WarningFound(result);
@ -93,14 +92,14 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
public void testConsumesErrorResponseWhenServingStale() public void testConsumesErrorResponseWhenServingStale()
throws Exception{ throws Exception{
final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5, stale-if-error=60"); "public, max-age=5, stale-if-error=60");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
final byte[] body101 = HttpTestUtils.getRandomBytes(101); final byte[] body101 = HttpTestUtils.getRandomBytes(101);
final ByteArrayInputStream buf = new ByteArrayInputStream(body101); final ByteArrayInputStream buf = new ByteArrayInputStream(body101);
final ConsumableInputStream cis = new ConsumableInputStream(buf); final ConsumableInputStream cis = new ConsumableInputStream(buf);
@ -110,8 +109,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
impl.execute(route, req2, context, null); impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertTrue(cis.wasClosed()); assertTrue(cis.wasClosed());
@ -121,23 +120,23 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
public void testStaleIfErrorInResponseYieldsToMustRevalidate() public void testStaleIfErrorInResponseYieldsToMustRevalidate()
throws Exception{ throws Exception{
final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5, stale-if-error=60, must-revalidate"); "public, max-age=5, stale-if-error=60, must-revalidate");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); assertTrue(HttpStatus.SC_OK != result.getCode());
} }
@Test @Test
@ -145,23 +144,23 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
throws Exception{ throws Exception{
assertTrue(config.isSharedCache()); assertTrue(config.isSharedCache());
final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5, stale-if-error=60, proxy-revalidate"); "public, max-age=5, stale-if-error=60, proxy-revalidate");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); assertTrue(HttpStatus.SC_OK != result.getCode());
} }
@Test @Test
@ -172,20 +171,20 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
impl = new CachingExec(mockBackend, new BasicHttpCache(configUnshared), configUnshared); impl = new CachingExec(mockBackend, new BasicHttpCache(configUnshared), configUnshared);
final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5, stale-if-error=60, proxy-revalidate"); "public, max-age=5, stale-if-error=60, proxy-revalidate");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
HttpTestUtils.assert110WarningFound(result); HttpTestUtils.assert110WarningFound(result);
@ -195,45 +194,45 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
public void testStaleIfErrorInResponseYieldsToExplicitFreshnessRequest() public void testStaleIfErrorInResponseYieldsToExplicitFreshnessRequest()
throws Exception{ throws Exception{
final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5, stale-if-error=60"); "public, max-age=5, stale-if-error=60");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
req2.setHeader("Cache-Control","min-fresh=2"); req2.setHeader("Cache-Control","min-fresh=2");
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); assertTrue(HttpStatus.SC_OK != result.getCode());
} }
@Test @Test
public void testStaleIfErrorInRequestIsTrueReturnsStaleEntryWithWarning() public void testStaleIfErrorInRequestIsTrueReturnsStaleEntryWithWarning()
throws Exception{ throws Exception{
final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5"); "public, max-age=5");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
req2.setHeader("Cache-Control","public, stale-if-error=60"); req2.setHeader("Cache-Control","public, stale-if-error=60");
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
HttpTestUtils.assert110WarningFound(result); HttpTestUtils.assert110WarningFound(result);
@ -243,22 +242,22 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
public void testStaleIfErrorInRequestIsTrueReturnsStaleNonRevalidatableEntryWithWarning() public void testStaleIfErrorInRequestIsTrueReturnsStaleNonRevalidatableEntryWithWarning()
throws Exception { throws Exception {
final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(new Date().getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo));
resp1.setHeader("Cache-Control", "public, max-age=5"); resp1.setHeader("Cache-Control", "public, max-age=5");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
req2.setHeader("Cache-Control", "public, stale-if-error=60"); req2.setHeader("Cache-Control", "public, stale-if-error=60");
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
HttpTestUtils.assert110WarningFound(result); HttpTestUtils.assert110WarningFound(result);
@ -269,24 +268,24 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
throws Exception{ throws Exception{
final Date now = new Date(); final Date now = new Date();
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5, stale-if-error=2"); "public, max-age=5, stale-if-error=2");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR,
result.getStatusLine().getStatusCode()); result.getCode());
} }
@Test @Test
@ -294,25 +293,25 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
throws Exception{ throws Exception{
final Date now = new Date(); final Date now = new Date();
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo,
"public, max-age=5"); "public, max-age=5");
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest(), host); final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(HttpTestUtils.makeDefaultRequest(), route);
req2.setHeader("Cache-Control","stale-if-error=2"); req2.setHeader("Cache-Control","stale-if-error=2");
final HttpResponse resp2 = HttpTestUtils.make500Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response();
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR,
result.getStatusLine().getStatusCode()); result.getCode());
} }
/* /*
@ -334,9 +333,9 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
impl = new CachingExec(mockBackend, cache, config, new AsynchronousValidator(config)); impl = new CachingExec(mockBackend, cache, config, new AsynchronousValidator(config));
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap( final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
final Date now = new Date(); final Date now = new Date();
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15"); resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15");
@ -345,15 +344,15 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
backendExpectsAnyRequestAndReturn(resp1).times(1,2); backendExpectsAnyRequestAndReturn(resp1).times(1,2);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap( final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); assertEquals(HttpStatus.SC_OK, result.getCode());
boolean warning110Found = false; boolean warning110Found = false;
for(final Header h : result.getHeaders("Warning")) { for(final Header h : result.getHeaders("Warning")) {
for(final WarningValue wv : WarningValue.getWarningValues(h)) { for(final WarningValue wv : WarningValue.getWarningValues(h)) {
@ -379,9 +378,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
impl = new CachingExec(mockBackend, cache, config, new AsynchronousValidator(config)); impl = new CachingExec(mockBackend, cache, config, new AsynchronousValidator(config));
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("GET", "/"), route);
HttpVersion.HTTP_1_1), host); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
final HttpResponse resp1 = HttpTestUtils.make200Response();
final Date now = new Date(); final Date now = new Date();
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15"); resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15");
@ -389,15 +387,14 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
backendExpectsAnyRequestAndReturn(resp1).times(1, 2); backendExpectsAnyRequestAndReturn(resp1).times(1, 2);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("GET", "/"), route);
HttpVersion.HTTP_1_1), host);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); assertEquals(HttpStatus.SC_OK, result.getCode());
boolean warning110Found = false; boolean warning110Found = false;
for (final Header h : result.getHeaders("Warning")) { for (final Header h : result.getHeaders("Warning")) {
for (final WarningValue wv : WarningValue.getWarningValues(h)) { for (final WarningValue wv : WarningValue.getWarningValues(h)) {
@ -422,9 +419,9 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
.build(); .build();
impl = new CachingExec(mockBackend, cache, config, new AsynchronousValidator(config)); impl = new CachingExec(mockBackend, cache, config, new AsynchronousValidator(config));
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap( final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
final Date now = new Date(); final Date now = new Date();
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
resp1.setHeader("Cache-Control", "private, stale-while-revalidate=15"); resp1.setHeader("Cache-Control", "private, stale-while-revalidate=15");
@ -433,16 +430,16 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
backendExpectsAnyRequestAndReturn(resp1).times(1,2); backendExpectsAnyRequestAndReturn(resp1).times(1,2);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap( final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
req2.setHeader("If-None-Match","\"etag\""); req2.setHeader("If-None-Match","\"etag\"");
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode());
boolean warning110Found = false; boolean warning110Found = false;
for(final Header h : result.getHeaders("Warning")) { for(final Header h : result.getHeaders("Warning")) {
for(final WarningValue wv : WarningValue.getWarningValues(h)) { for(final WarningValue wv : WarningValue.getWarningValues(h)) {
@ -470,18 +467,18 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
.build(); .build();
impl = new CachingExec(mockBackend, cache, config); impl = new CachingExec(mockBackend, cache, config);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap( final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, must-revalidate"); resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, must-revalidate");
resp1.setHeader("ETag","\"etag\""); resp1.setHeader("ETag","\"etag\"");
resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo));
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap( final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final HttpResponse resp2 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response();
resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, must-revalidate"); resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, must-revalidate");
resp2.setHeader("ETag","\"etag\""); resp2.setHeader("ETag","\"etag\"");
resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Date", DateUtils.formatDate(now));
@ -489,11 +486,11 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); assertEquals(HttpStatus.SC_OK, result.getCode());
boolean warning110Found = false; boolean warning110Found = false;
for(final Header h : result.getHeaders("Warning")) { for(final Header h : result.getHeaders("Warning")) {
for(final WarningValue wv : WarningValue.getWarningValues(h)) { for(final WarningValue wv : WarningValue.getWarningValues(h)) {
@ -521,18 +518,18 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
.build(); .build();
impl = new CachingExec(mockBackend, cache, config); impl = new CachingExec(mockBackend, cache, config);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap( final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, proxy-revalidate"); resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, proxy-revalidate");
resp1.setHeader("ETag","\"etag\""); resp1.setHeader("ETag","\"etag\"");
resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo));
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap( final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final HttpResponse resp2 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response();
resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, proxy-revalidate"); resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, proxy-revalidate");
resp2.setHeader("ETag","\"etag\""); resp2.setHeader("ETag","\"etag\"");
resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Date", DateUtils.formatDate(now));
@ -540,11 +537,11 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); assertEquals(HttpStatus.SC_OK, result.getCode());
boolean warning110Found = false; boolean warning110Found = false;
for(final Header h : result.getHeaders("Warning")) { for(final Header h : result.getHeaders("Warning")) {
for(final WarningValue wv : WarningValue.getWarningValues(h)) { for(final WarningValue wv : WarningValue.getWarningValues(h)) {
@ -572,19 +569,19 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
.build(); .build();
impl = new CachingExec(mockBackend, cache, config); impl = new CachingExec(mockBackend, cache, config);
final HttpRequestWrapper req1 = HttpRequestWrapper.wrap( final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
final HttpResponse resp1 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15"); resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15");
resp1.setHeader("ETag","\"etag\""); resp1.setHeader("ETag","\"etag\"");
resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo));
backendExpectsAnyRequestAndReturn(resp1); backendExpectsAnyRequestAndReturn(resp1);
final HttpRequestWrapper req2 = HttpRequestWrapper.wrap( final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host); new BasicClassicHttpRequest("GET", "/"), route);
req2.setHeader("Cache-Control","min-fresh=2"); req2.setHeader("Cache-Control","min-fresh=2");
final HttpResponse resp2 = HttpTestUtils.make200Response(); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response();
resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15"); resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15");
resp2.setHeader("ETag","\"etag\""); resp2.setHeader("ETag","\"etag\"");
resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Date", DateUtils.formatDate(now));
@ -592,11 +589,11 @@ public class TestRFC5861Compliance extends AbstractProtocolTest {
backendExpectsAnyRequestAndReturn(resp2); backendExpectsAnyRequestAndReturn(resp2);
replayMocks(); replayMocks();
impl.execute(route, req1, context, null); impl.execute(req1, context, null);
final HttpResponse result = impl.execute(route, req2, context, null); final ClassicHttpResponse result = impl.execute(req2, context, null);
verifyMocks(); verifyMocks();
assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); assertEquals(HttpStatus.SC_OK, result.getCode());
boolean warning110Found = false; boolean warning110Found = false;
for(final Header h : result.getHeaders("Warning")) { for(final Header h : result.getHeaders("Warning")) {
for(final WarningValue wv : WarningValue.getWarningValues(h)) { for(final WarningValue wv : WarningValue.getWarningValues(h)) {

View File

@ -32,25 +32,26 @@ import static org.junit.Assert.assertTrue;
import java.util.Arrays; import java.util.Arrays;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.methods.HttpPut; import org.apache.hc.client5.http.methods.HttpPut;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
public class TestRequestProtocolCompliance { public class TestRequestProtocolCompliance {
private HttpHost host; private HttpRoute route;
private RequestProtocolCompliance impl; private RequestProtocolCompliance impl;
private HttpRequest req; private ClassicHttpRequest req;
@Before @Before
public void setUp() { public void setUp() {
host = new HttpHost("foo.example.com", 80); route = new HttpRoute(new HttpHost("foo.example.com", 80));
req = HttpTestUtils.makeDefaultRequest(); req = HttpTestUtils.makeDefaultRequest();
impl = new RequestProtocolCompliance(false); impl = new RequestProtocolCompliance(false);
} }
@ -85,43 +86,44 @@ public class TestRequestProtocolCompliance {
@Test @Test
public void doesNotModifyACompliantRequest() throws Exception { public void doesNotModifyACompliantRequest() throws Exception {
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertTrue(HttpTestUtils.equivalent(req, wrapper)); assertTrue(HttpTestUtils.equivalent(req, wrapper));
} }
@Test @Test
public void removesEntityFromTRACERequest() throws Exception { public void removesEntityFromTRACERequest() throws Exception {
final HttpRequest request = final ClassicHttpRequest request = new BasicClassicHttpRequest("TRACE", "/");
new BasicHttpRequest("TRACE", "/", HttpVersion.HTTP_1_1); request.setVersion(HttpVersion.HTTP_1_1);
request.setEntity(HttpTestUtils.makeBody(50)); request.setEntity(HttpTestUtils.makeBody(50));
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(request, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(request, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertNull(wrapper.getEntity()); assertNull(wrapper.getEntity());
} }
@Test @Test
public void upgrades1_0RequestTo1_1() throws Exception { public void upgrades1_0RequestTo1_1() throws Exception {
req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_0); req = new BasicClassicHttpRequest("GET", "/");
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); req.setVersion(HttpVersion.HTTP_1_0);
final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertEquals(HttpVersion.HTTP_1_1, wrapper.getProtocolVersion()); assertEquals(HttpVersion.HTTP_1_1, wrapper.getVersion());
} }
@Test @Test
public void downgrades1_2RequestTo1_1() throws Exception { public void downgrades1_2RequestTo1_1() throws Exception {
final ProtocolVersion HTTP_1_2 = new ProtocolVersion("HTTP", 1, 2); req = new BasicClassicHttpRequest("GET", "/");
req = new BasicHttpRequest("GET", "/", HTTP_1_2); req.setVersion(new ProtocolVersion("HTTP", 1, 2));
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertEquals(HttpVersion.HTTP_1_1, wrapper.getProtocolVersion()); assertEquals(HttpVersion.HTTP_1_1, wrapper.getVersion());
} }
@Test @Test
public void stripsMinFreshFromRequestIfNoCachePresent() public void stripsMinFreshFromRequestIfNoCachePresent()
throws Exception { throws Exception {
req.setHeader("Cache-Control", "no-cache, min-fresh=10"); req.setHeader("Cache-Control", "no-cache, min-fresh=10");
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertEquals("no-cache", assertEquals("no-cache",
wrapper.getFirstHeader("Cache-Control").getValue()); wrapper.getFirstHeader("Cache-Control").getValue());
@ -131,7 +133,7 @@ public class TestRequestProtocolCompliance {
public void stripsMaxFreshFromRequestIfNoCachePresent() public void stripsMaxFreshFromRequestIfNoCachePresent()
throws Exception { throws Exception {
req.setHeader("Cache-Control", "no-cache, max-stale=10"); req.setHeader("Cache-Control", "no-cache, max-stale=10");
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertEquals("no-cache", assertEquals("no-cache",
wrapper.getFirstHeader("Cache-Control").getValue()); wrapper.getFirstHeader("Cache-Control").getValue());
@ -141,7 +143,7 @@ public class TestRequestProtocolCompliance {
public void stripsMaxAgeFromRequestIfNoCachePresent() public void stripsMaxAgeFromRequestIfNoCachePresent()
throws Exception { throws Exception {
req.setHeader("Cache-Control", "no-cache, max-age=10"); req.setHeader("Cache-Control", "no-cache, max-age=10");
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertEquals("no-cache", assertEquals("no-cache",
wrapper.getFirstHeader("Cache-Control").getValue()); wrapper.getFirstHeader("Cache-Control").getValue());
@ -151,7 +153,7 @@ public class TestRequestProtocolCompliance {
public void doesNotStripMinFreshFromRequestWithoutNoCache() public void doesNotStripMinFreshFromRequestWithoutNoCache()
throws Exception { throws Exception {
req.setHeader("Cache-Control", "min-fresh=10"); req.setHeader("Cache-Control", "min-fresh=10");
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertEquals("min-fresh=10", assertEquals("min-fresh=10",
wrapper.getFirstHeader("Cache-Control").getValue()); wrapper.getFirstHeader("Cache-Control").getValue());
@ -161,7 +163,7 @@ public class TestRequestProtocolCompliance {
public void correctlyStripsMinFreshFromMiddleIfNoCache() public void correctlyStripsMinFreshFromMiddleIfNoCache()
throws Exception { throws Exception {
req.setHeader("Cache-Control", "no-cache,min-fresh=10,no-store"); req.setHeader("Cache-Control", "no-cache,min-fresh=10,no-store");
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);
impl.makeRequestCompliant(wrapper); impl.makeRequestCompliant(wrapper);
assertEquals("no-cache,no-store", assertEquals("no-cache,no-store",
wrapper.getFirstHeader("Cache-Control").getValue()); wrapper.getFirstHeader("Cache-Control").getValue());

View File

@ -38,7 +38,6 @@ import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.apache.hc.core5.http.message.BasicHttpResponse; import org.apache.hc.core5.http.message.BasicHttpResponse;
import org.apache.hc.core5.http.message.BasicStatusLine;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -63,9 +62,8 @@ public class TestResponseCachingPolicy {
tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L); tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
policy = new ResponseCachingPolicy(0, true, false, false); policy = new ResponseCachingPolicy(0, true, false, false);
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicHttpRequest("GET","/");
response = new BasicHttpResponse( response = new BasicHttpResponse(HttpStatus.SC_OK, "");
new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
response.setHeader("Date", DateUtils.formatDate(new Date())); response.setHeader("Date", DateUtils.formatDate(new Date()));
response.setHeader("Content-Length", "0"); response.setHeader("Content-Length", "0");
} }
@ -83,7 +81,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testResponsesToRequestsWithAuthorizationHeadersAreNotCacheableBySharedCache() { public void testResponsesToRequestsWithAuthorizationHeadersAreNotCacheableBySharedCache() {
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicHttpRequest("GET","/");
request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q="); request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
Assert.assertFalse(policy.isResponseCacheable(request,response)); Assert.assertFalse(policy.isResponseCacheable(request,response));
} }
@ -91,14 +89,14 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testResponsesToRequestsWithAuthorizationHeadersAreCacheableByNonSharedCache() { public void testResponsesToRequestsWithAuthorizationHeadersAreCacheableByNonSharedCache() {
policy = new ResponseCachingPolicy(0, false, false, false); policy = new ResponseCachingPolicy(0, false, false, false);
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicHttpRequest("GET","/");
request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q="); request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
Assert.assertTrue(policy.isResponseCacheable(request,response)); Assert.assertTrue(policy.isResponseCacheable(request,response));
} }
@Test @Test
public void testAuthorizedResponsesWithSMaxAgeAreCacheable() { public void testAuthorizedResponsesWithSMaxAgeAreCacheable() {
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicHttpRequest("GET","/");
request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q="); request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
response.setHeader("Cache-Control","s-maxage=3600"); response.setHeader("Cache-Control","s-maxage=3600");
Assert.assertTrue(policy.isResponseCacheable(request,response)); Assert.assertTrue(policy.isResponseCacheable(request,response));
@ -106,7 +104,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testAuthorizedResponsesWithMustRevalidateAreCacheable() { public void testAuthorizedResponsesWithMustRevalidateAreCacheable() {
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicHttpRequest("GET","/");
request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q="); request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
response.setHeader("Cache-Control","must-revalidate"); response.setHeader("Cache-Control","must-revalidate");
Assert.assertTrue(policy.isResponseCacheable(request,response)); Assert.assertTrue(policy.isResponseCacheable(request,response));
@ -114,7 +112,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testAuthorizedResponsesWithCacheControlPublicAreCacheable() { public void testAuthorizedResponsesWithCacheControlPublicAreCacheable() {
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicHttpRequest("GET","/");
request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q="); request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
response.setHeader("Cache-Control","public"); response.setHeader("Cache-Control","public");
Assert.assertTrue(policy.isResponseCacheable(request,response)); Assert.assertTrue(policy.isResponseCacheable(request,response));
@ -122,7 +120,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testAuthorizedResponsesWithCacheControlMaxAgeAreNotCacheable() { public void testAuthorizedResponsesWithCacheControlMaxAgeAreNotCacheable() {
request = new BasicHttpRequest("GET","/",HTTP_1_1); request = new BasicHttpRequest("GET","/");
request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q="); request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
response.setHeader("Cache-Control","max-age=3600"); response.setHeader("Cache-Control","max-age=3600");
Assert.assertFalse(policy.isResponseCacheable(request,response)); Assert.assertFalse(policy.isResponseCacheable(request,response));
@ -130,13 +128,13 @@ public class TestResponseCachingPolicy {
@Test @Test
public void test203ResponseCodeIsCacheable() { public void test203ResponseCodeIsCacheable() {
response.setStatusCode(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION); response.setCode(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION);
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@Test @Test
public void test206ResponseCodeIsNotCacheable() { public void test206ResponseCodeIsNotCacheable() {
response.setStatusCode(HttpStatus.SC_PARTIAL_CONTENT); response.setCode(HttpStatus.SC_PARTIAL_CONTENT);
Assert.assertFalse(policy.isResponseCacheable("GET", response)); Assert.assertFalse(policy.isResponseCacheable("GET", response));
} }
@ -145,32 +143,32 @@ public class TestResponseCachingPolicy {
policy = new ResponseCachingPolicy(0, true, false, false); policy = new ResponseCachingPolicy(0, true, false, false);
request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
response.setStatusCode(HttpStatus.SC_PARTIAL_CONTENT); response.setCode(HttpStatus.SC_PARTIAL_CONTENT);
response.setHeader("Cache-Control", "public"); response.setHeader("Cache-Control", "public");
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
} }
@Test @Test
public void test300ResponseCodeIsCacheable() { public void test300ResponseCodeIsCacheable() {
response.setStatusCode(HttpStatus.SC_MULTIPLE_CHOICES); response.setCode(HttpStatus.SC_MULTIPLE_CHOICES);
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@Test @Test
public void test301ResponseCodeIsCacheable() { public void test301ResponseCodeIsCacheable() {
response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY); response.setCode(HttpStatus.SC_MOVED_PERMANENTLY);
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@Test @Test
public void test410ResponseCodeIsCacheable() { public void test410ResponseCodeIsCacheable() {
response.setStatusCode(HttpStatus.SC_GONE); response.setCode(HttpStatus.SC_GONE);
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@Test @Test
public void testPlain302ResponseCodeIsNotCacheable() { public void testPlain302ResponseCodeIsNotCacheable() {
response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY); response.setCode(HttpStatus.SC_MOVED_TEMPORARILY);
response.removeHeaders("Expires"); response.removeHeaders("Expires");
response.removeHeaders("Cache-Control"); response.removeHeaders("Cache-Control");
Assert.assertFalse(policy.isResponseCacheable("GET", response)); Assert.assertFalse(policy.isResponseCacheable("GET", response));
@ -178,7 +176,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testPlain303ResponseCodeIsNotCacheableUnderDefaultBehavior() { public void testPlain303ResponseCodeIsNotCacheableUnderDefaultBehavior() {
response.setStatusCode(HttpStatus.SC_SEE_OTHER); response.setCode(HttpStatus.SC_SEE_OTHER);
response.removeHeaders("Expires"); response.removeHeaders("Expires");
response.removeHeaders("Cache-Control"); response.removeHeaders("Cache-Control");
Assert.assertFalse(policy.isResponseCacheable("GET", response)); Assert.assertFalse(policy.isResponseCacheable("GET", response));
@ -187,7 +185,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testPlain303ResponseCodeIsNotCacheableEvenIf303CachingEnabled() { public void testPlain303ResponseCodeIsNotCacheableEvenIf303CachingEnabled() {
policy = new ResponseCachingPolicy(0, true, false, true); policy = new ResponseCachingPolicy(0, true, false, true);
response.setStatusCode(HttpStatus.SC_SEE_OTHER); response.setCode(HttpStatus.SC_SEE_OTHER);
response.removeHeaders("Expires"); response.removeHeaders("Expires");
response.removeHeaders("Cache-Control"); response.removeHeaders("Cache-Control");
Assert.assertFalse(policy.isResponseCacheable("GET", response)); Assert.assertFalse(policy.isResponseCacheable("GET", response));
@ -196,7 +194,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testPlain307ResponseCodeIsNotCacheable() { public void testPlain307ResponseCodeIsNotCacheable() {
response.setStatusCode(HttpStatus.SC_TEMPORARY_REDIRECT); response.setCode(HttpStatus.SC_TEMPORARY_REDIRECT);
response.removeHeaders("Expires"); response.removeHeaders("Expires");
response.removeHeaders("Cache-Control"); response.removeHeaders("Cache-Control");
Assert.assertFalse(policy.isResponseCacheable("GET", response)); Assert.assertFalse(policy.isResponseCacheable("GET", response));
@ -205,7 +203,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testNon206WithExplicitExpiresIsCacheable() { public void testNon206WithExplicitExpiresIsCacheable() {
final int status = getRandomStatus(); final int status = getRandomStatus();
response.setStatusCode(status); response.setCode(status);
response.setHeader("Expires", DateUtils.formatDate(new Date())); response.setHeader("Expires", DateUtils.formatDate(new Date()));
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@ -213,7 +211,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testNon206WithMaxAgeIsCacheable() { public void testNon206WithMaxAgeIsCacheable() {
final int status = getRandomStatus(); final int status = getRandomStatus();
response.setStatusCode(status); response.setCode(status);
response.setHeader("Cache-Control", "max-age=0"); response.setHeader("Cache-Control", "max-age=0");
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@ -221,7 +219,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testNon206WithSMaxAgeIsCacheable() { public void testNon206WithSMaxAgeIsCacheable() {
final int status = getRandomStatus(); final int status = getRandomStatus();
response.setStatusCode(status); response.setCode(status);
response.setHeader("Cache-Control", "s-maxage=0"); response.setHeader("Cache-Control", "s-maxage=0");
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@ -229,7 +227,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testNon206WithMustRevalidateIsCacheable() { public void testNon206WithMustRevalidateIsCacheable() {
final int status = getRandomStatus(); final int status = getRandomStatus();
response.setStatusCode(status); response.setCode(status);
response.setHeader("Cache-Control", "must-revalidate"); response.setHeader("Cache-Control", "must-revalidate");
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@ -237,7 +235,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testNon206WithProxyRevalidateIsCacheable() { public void testNon206WithProxyRevalidateIsCacheable() {
final int status = getRandomStatus(); final int status = getRandomStatus();
response.setStatusCode(status); response.setCode(status);
response.setHeader("Cache-Control", "proxy-revalidate"); response.setHeader("Cache-Control", "proxy-revalidate");
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@ -245,7 +243,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testNon206WithPublicCacheControlIsCacheable() { public void testNon206WithPublicCacheControlIsCacheable() {
final int status = getRandomStatus(); final int status = getRandomStatus();
response.setStatusCode(status); response.setCode(status);
response.setHeader("Cache-Control", "public"); response.setHeader("Cache-Control", "public");
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@ -253,7 +251,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testNon206WithPrivateCacheControlIsNotCacheableBySharedCache() { public void testNon206WithPrivateCacheControlIsNotCacheableBySharedCache() {
final int status = getRandomStatus(); final int status = getRandomStatus();
response.setStatusCode(status); response.setCode(status);
response.setHeader("Cache-Control", "private"); response.setHeader("Cache-Control", "private");
Assert.assertFalse(policy.isResponseCacheable("GET", response)); Assert.assertFalse(policy.isResponseCacheable("GET", response));
} }
@ -261,7 +259,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void test200ResponseWithPrivateCacheControlIsCacheableByNonSharedCache() { public void test200ResponseWithPrivateCacheControlIsCacheableByNonSharedCache() {
policy = new ResponseCachingPolicy(0, false, false, false); policy = new ResponseCachingPolicy(0, false, false, false);
response.setStatusCode(HttpStatus.SC_OK); response.setCode(HttpStatus.SC_OK);
response.setHeader("Cache-Control", "private"); response.setHeader("Cache-Control", "private");
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
} }
@ -360,8 +358,7 @@ public class TestResponseCachingPolicy {
Assert.assertTrue(policy.isResponseCacheable("GET", response)); Assert.assertTrue(policy.isResponseCacheable("GET", response));
response = new BasicHttpResponse( response = new BasicHttpResponse(HttpStatus.SC_OK, "");
new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
response.setHeader("Date", DateUtils.formatDate(new Date())); response.setHeader("Date", DateUtils.formatDate(new Date()));
response.addHeader("Cache-Control", "no-transform"); response.addHeader("Cache-Control", "no-transform");
response.setHeader("Content-Length", "0"); response.setHeader("Content-Length", "0");
@ -376,8 +373,7 @@ public class TestResponseCachingPolicy {
Assert.assertTrue(policy.isResponseCacheable("HEAD", response)); Assert.assertTrue(policy.isResponseCacheable("HEAD", response));
response = new BasicHttpResponse( response = new BasicHttpResponse(HttpStatus.SC_OK, "");
new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
response.setHeader("Date", DateUtils.formatDate(new Date())); response.setHeader("Date", DateUtils.formatDate(new Date()));
response.addHeader("Cache-Control", "no-transform"); response.addHeader("Cache-Control", "no-transform");
response.setHeader("Content-Length", "0"); response.setHeader("Content-Length", "0");
@ -387,26 +383,22 @@ public class TestResponseCachingPolicy {
@Test @Test
public void testIsGetWithout200Cacheable() { public void testIsGetWithout200Cacheable() {
HttpResponse response404 = new BasicHttpResponse(new BasicStatusLine(HTTP_1_1, HttpResponse response404 = new BasicHttpResponse(HttpStatus.SC_NOT_FOUND, "");
HttpStatus.SC_NOT_FOUND, ""));
Assert.assertFalse(policy.isResponseCacheable("GET", response404)); Assert.assertFalse(policy.isResponseCacheable("GET", response404));
response404 = new BasicHttpResponse(new BasicStatusLine(HTTP_1_1, response404 = new BasicHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "");
HttpStatus.SC_GATEWAY_TIMEOUT, ""));
Assert.assertFalse(policy.isResponseCacheable("GET", response404)); Assert.assertFalse(policy.isResponseCacheable("GET", response404));
} }
@Test @Test
public void testIsHeadWithout200Cacheable() { public void testIsHeadWithout200Cacheable() {
HttpResponse response404 = new BasicHttpResponse(new BasicStatusLine(HTTP_1_1, HttpResponse response404 = new BasicHttpResponse(HttpStatus.SC_NOT_FOUND, "");
HttpStatus.SC_NOT_FOUND, ""));
Assert.assertFalse(policy.isResponseCacheable("HEAD", response404)); Assert.assertFalse(policy.isResponseCacheable("HEAD", response404));
response404 = new BasicHttpResponse(new BasicStatusLine(HTTP_1_1, response404 = new BasicHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "");
HttpStatus.SC_GATEWAY_TIMEOUT, ""));
Assert.assertFalse(policy.isResponseCacheable("HEAD", response404)); Assert.assertFalse(policy.isResponseCacheable("HEAD", response404));
} }
@ -454,7 +446,7 @@ public class TestResponseCachingPolicy {
request = new HttpOptions("http://foo.example.com/"); request = new HttpOptions("http://foo.example.com/");
request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); request.setHeader("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
response.setStatusCode(HttpStatus.SC_NO_CONTENT); response.setCode(HttpStatus.SC_NO_CONTENT);
response.setHeader("Cache-Control", "public"); response.setHeader("Cache-Control", "public");
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
@ -629,14 +621,16 @@ public class TestResponseCachingPolicy {
@Test @Test
public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() { public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() {
request = new BasicHttpRequest("GET", "/foo?s=bar"); request = new BasicHttpRequest("GET", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
} }
@Test @Test
public void headsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() { public void headsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() {
request = new BasicHttpRequest("HEAD", "/foo?s=bar"); request = new BasicHttpRequest("HEAD", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
} }
@ -644,7 +638,8 @@ public class TestResponseCachingPolicy {
public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() { public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() {
policy = new ResponseCachingPolicy(0, true, true, false); policy = new ResponseCachingPolicy(0, true, true, false);
request = new BasicHttpRequest("GET", "/foo?s=bar"); request = new BasicHttpRequest("GET", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
} }
@ -652,14 +647,16 @@ public class TestResponseCachingPolicy {
public void headsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() { public void headsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() {
policy = new ResponseCachingPolicy(0, true, true, false); policy = new ResponseCachingPolicy(0, true, true, false);
request = new BasicHttpRequest("HEAD", "/foo?s=bar"); request = new BasicHttpRequest("HEAD", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
} }
@Test @Test
public void getsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() { public void getsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() {
request = new BasicHttpRequest("GET", "/foo?s=bar"); request = new BasicHttpRequest("GET", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)); response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
Assert.assertTrue(policy.isResponseCacheable(request, response)); Assert.assertTrue(policy.isResponseCacheable(request, response));
@ -669,7 +666,8 @@ public class TestResponseCachingPolicy {
public void headsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() { public void headsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() {
policy = new ResponseCachingPolicy(0, true, false, false); policy = new ResponseCachingPolicy(0, true, false, false);
request = new BasicHttpRequest("HEAD", "/foo?s=bar"); request = new BasicHttpRequest("HEAD", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)); response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
Assert.assertTrue(policy.isResponseCacheable(request, response)); Assert.assertTrue(policy.isResponseCacheable(request, response));
@ -679,7 +677,8 @@ public class TestResponseCachingPolicy {
public void getsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() { public void getsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() {
policy = new ResponseCachingPolicy(0, true, true, false); policy = new ResponseCachingPolicy(0, true, true, false);
request = new BasicHttpRequest("GET", "/foo?s=bar"); request = new BasicHttpRequest("GET", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)); response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
@ -689,7 +688,8 @@ public class TestResponseCachingPolicy {
public void headsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() { public void headsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() {
policy = new ResponseCachingPolicy(0, true, true, false); policy = new ResponseCachingPolicy(0, true, true, false);
request = new BasicHttpRequest("HEAD", "/foo?s=bar"); request = new BasicHttpRequest("HEAD", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)); response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
@ -790,7 +790,8 @@ public class TestResponseCachingPolicy {
@Test @Test
public void getsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() { public void getsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() {
request = new BasicHttpRequest("GET", "/foo?s=bar"); request = new BasicHttpRequest("GET", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)); response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
response.setHeader("Via", "1.1 someproxy"); response.setHeader("Via", "1.1 someproxy");
@ -801,7 +802,8 @@ public class TestResponseCachingPolicy {
public void headsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() { public void headsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() {
policy = new ResponseCachingPolicy(0, true, false, false); policy = new ResponseCachingPolicy(0, true, false, false);
request = new BasicHttpRequest("HEAD", "/foo?s=bar"); request = new BasicHttpRequest("HEAD", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
response.setVersion(HttpVersion.HTTP_1_0);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)); response.setHeader("Expires", DateUtils.formatDate(tenSecondsFromNow));
response.setHeader("Via", "1.1 someproxy"); response.setHeader("Via", "1.1 someproxy");
@ -826,7 +828,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void test302WithExplicitCachingHeaders() { public void test302WithExplicitCachingHeaders() {
response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY); response.setCode(HttpStatus.SC_MOVED_TEMPORARILY);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Cache-Control","max-age=300"); response.setHeader("Cache-Control","max-age=300");
Assert.assertTrue(policy.isResponseCacheable(request, response)); Assert.assertTrue(policy.isResponseCacheable(request, response));
@ -835,7 +837,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void test303WithExplicitCachingHeadersUnderDefaultBehavior() { public void test303WithExplicitCachingHeadersUnderDefaultBehavior() {
// RFC 2616 says: 303 should not be cached // RFC 2616 says: 303 should not be cached
response.setStatusCode(HttpStatus.SC_SEE_OTHER); response.setCode(HttpStatus.SC_SEE_OTHER);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Cache-Control","max-age=300"); response.setHeader("Cache-Control","max-age=300");
Assert.assertFalse(policy.isResponseCacheable(request, response)); Assert.assertFalse(policy.isResponseCacheable(request, response));
@ -846,7 +848,7 @@ public class TestResponseCachingPolicy {
// HTTPbis working group says ok if explicitly indicated by // HTTPbis working group says ok if explicitly indicated by
// response headers // response headers
policy = new ResponseCachingPolicy(0, true, false, true); policy = new ResponseCachingPolicy(0, true, false, true);
response.setStatusCode(HttpStatus.SC_SEE_OTHER); response.setCode(HttpStatus.SC_SEE_OTHER);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Cache-Control","max-age=300"); response.setHeader("Cache-Control","max-age=300");
Assert.assertTrue(policy.isResponseCacheable(request, response)); Assert.assertTrue(policy.isResponseCacheable(request, response));
@ -854,7 +856,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void test307WithExplicitCachingHeaders() { public void test307WithExplicitCachingHeaders() {
response.setStatusCode(HttpStatus.SC_TEMPORARY_REDIRECT); response.setCode(HttpStatus.SC_TEMPORARY_REDIRECT);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Cache-Control","max-age=300"); response.setHeader("Cache-Control","max-age=300");
Assert.assertTrue(policy.isResponseCacheable(request, response)); Assert.assertTrue(policy.isResponseCacheable(request, response));
@ -862,7 +864,7 @@ public class TestResponseCachingPolicy {
@Test @Test
public void otherStatusCodesAreCacheableWithExplicitCachingHeaders() { public void otherStatusCodesAreCacheableWithExplicitCachingHeaders() {
response.setStatusCode(HttpStatus.SC_NOT_FOUND); response.setCode(HttpStatus.SC_NOT_FOUND);
response.setHeader("Date", DateUtils.formatDate(now)); response.setHeader("Date", DateUtils.formatDate(now));
response.setHeader("Cache-Control","max-age=300"); response.setHeader("Cache-Control","max-age=300");
Assert.assertTrue(policy.isResponseCacheable(request, response)); Assert.assertTrue(policy.isResponseCacheable(request, response));

View File

@ -32,32 +32,32 @@ import static junit.framework.TestCase.assertTrue;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.Date; import java.util.Date;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.client5.http.methods.HttpHead; import org.apache.hc.client5.http.methods.HttpHead;
import org.apache.hc.client5.http.methods.HttpRequestWrapper; import org.apache.hc.client5.http.methods.RoutedHttpRequest;
import org.apache.hc.client5.http.protocol.ClientProtocolException; import org.apache.hc.client5.http.protocol.ClientProtocolException;
import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost; 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.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.entity.ByteArrayEntity; import org.apache.hc.core5.http.io.entity.InputStreamEntity;
import org.apache.hc.core5.http.entity.InputStreamEntity; import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHttpResponse;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
public class TestResponseProtocolCompliance { public class TestResponseProtocolCompliance {
private HttpHost host; private HttpRoute route;
private ResponseProtocolCompliance impl; private ResponseProtocolCompliance impl;
@Before @Before
public void setUp() { public void setUp() {
host = new HttpHost("foo.example.com", 80); route = new HttpRoute(new HttpHost("foo.example.com", 80));
impl = new ResponseProtocolCompliance(); impl = new ResponseProtocolCompliance();
} }
@ -65,7 +65,7 @@ public class TestResponseProtocolCompliance {
public boolean set; public boolean set;
} }
private void setMinimalResponseHeaders(final HttpResponse resp) { private void setMinimalResponseHeaders(final ClassicHttpResponse resp) {
resp.setHeader("Date", DateUtils.formatDate(new Date())); resp.setHeader("Date", DateUtils.formatDate(new Date()));
resp.setHeader("Server", "MyServer/1.0"); resp.setHeader("Server", "MyServer/1.0");
} }
@ -81,8 +81,8 @@ public class TestResponseProtocolCompliance {
return bais; return bais;
} }
private HttpResponse makePartialResponse(final int nbytes) { private ClassicHttpResponse makePartialResponse(final int nbytes) {
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
setMinimalResponseHeaders(resp); setMinimalResponseHeaders(resp);
resp.setHeader("Content-Length","" + nbytes); resp.setHeader("Content-Length","" + nbytes);
resp.setHeader("Content-Range","0-127/256"); resp.setHeader("Content-Range","0-127/256");
@ -91,9 +91,9 @@ public class TestResponseProtocolCompliance {
@Test @Test
public void consumesBodyIfOriginSendsOneInResponseToHEAD() throws Exception { public void consumesBodyIfOriginSendsOneInResponseToHEAD() throws Exception {
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(new HttpHead("http://foo.example.com/"), host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(new HttpHead("http://foo.example.com/"), route);;
final int nbytes = 128; final int nbytes = 128;
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
setMinimalResponseHeaders(resp); setMinimalResponseHeaders(resp);
resp.setHeader("Content-Length","" + nbytes); resp.setHeader("Content-Length","" + nbytes);
@ -108,9 +108,9 @@ public class TestResponseProtocolCompliance {
@Test(expected=ClientProtocolException.class) @Test(expected=ClientProtocolException.class)
public void throwsExceptionIfOriginReturnsPartialResponseWhenNotRequested() throws Exception { public void throwsExceptionIfOriginReturnsPartialResponseWhenNotRequested() throws Exception {
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/"), host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(new HttpGet("http://foo.example.com/"), route);;
final int nbytes = 128; final int nbytes = 128;
final HttpResponse resp = makePartialResponse(nbytes); final ClassicHttpResponse resp = makePartialResponse(nbytes);
resp.setEntity(HttpTestUtils.makeBody(nbytes)); resp.setEntity(HttpTestUtils.makeBody(nbytes));
impl.ensureProtocolCompliance(wrapper, resp); impl.ensureProtocolCompliance(wrapper, resp);
@ -118,9 +118,9 @@ public class TestResponseProtocolCompliance {
@Test @Test
public void consumesPartialContentFromOriginEvenIfNotRequested() throws Exception { public void consumesPartialContentFromOriginEvenIfNotRequested() throws Exception {
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/"), host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(new HttpGet("http://foo.example.com/"), route);;
final int nbytes = 128; final int nbytes = 128;
final HttpResponse resp = makePartialResponse(nbytes); final ClassicHttpResponse resp = makePartialResponse(nbytes);
final Flag closed = new Flag(); final Flag closed = new Flag();
final ByteArrayInputStream bais = makeTrackableBody(nbytes, closed); final ByteArrayInputStream bais = makeTrackableBody(nbytes, closed);
@ -135,15 +135,15 @@ public class TestResponseProtocolCompliance {
@Test @Test
public void consumesBodyOf100ContinueResponseIfItArrives() throws Exception { public void consumesBodyOf100ContinueResponseIfItArrives() throws Exception {
final HttpRequest req = new BasicHttpRequest("POST", "/", HttpVersion.HTTP_1_1); final ClassicHttpRequest req = new BasicClassicHttpRequest("POST", "/");
final int nbytes = 128; final int nbytes = 128;
req.setHeader("Content-Length","" + nbytes); req.setHeader("Content-Length","" + nbytes);
req.setHeader("Content-Type", "application/octet-stream"); req.setHeader("Content-Type", "application/octet-stream");
final HttpEntity postBody = new ByteArrayEntity(HttpTestUtils.getRandomBytes(nbytes)); final HttpEntity postBody = new ByteArrayEntity(HttpTestUtils.getRandomBytes(nbytes));
req.setEntity(postBody); req.setEntity(postBody);
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(req, host); final RoutedHttpRequest wrapper = RoutedHttpRequest.adapt(req, route);;
final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_CONTINUE, "Continue"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_CONTINUE, "Continue");
final Flag closed = new Flag(); final Flag closed = new Flag();
final ByteArrayInputStream bais = makeTrackableBody(nbytes, closed); final ByteArrayInputStream bais = makeTrackableBody(nbytes, closed);
resp.setEntity(new InputStreamEntity(bais, -1)); resp.setEntity(new InputStreamEntity(bais, -1));

View File

@ -27,20 +27,17 @@
package org.apache.hc.client5.http.impl.cache; package org.apache.hc.client5.http.impl.cache;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Proxy;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpRequest; 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.HttpStatus;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.entity.ByteArrayEntity; import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.entity.StringEntity; import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.message.BasicHttpResponse;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -60,13 +57,13 @@ public class TestSizeLimitedResponseReader {
@Test @Test
public void testLargeResponseIsTooLarge() throws Exception { public void testLargeResponseIsTooLarge() throws Exception {
final byte[] buf = new byte[] { 1, 2, 3, 4, 5 }; final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
final CloseableHttpResponse response = make200Response(buf); final ClassicHttpResponse response = make200Response(buf);
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response); impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
impl.readResponse(); impl.readResponse();
final boolean tooLarge = impl.isLimitReached(); final boolean tooLarge = impl.isLimitReached();
final HttpResponse result = impl.getReconstructedResponse(); final ClassicHttpResponse result = impl.getReconstructedResponse();
final byte[] body = EntityUtils.toByteArray(result.getEntity()); final byte[] body = EntityUtils.toByteArray(result.getEntity());
Assert.assertTrue(tooLarge); Assert.assertTrue(tooLarge);
@ -76,13 +73,13 @@ public class TestSizeLimitedResponseReader {
@Test @Test
public void testExactSizeResponseIsNotTooLarge() throws Exception { public void testExactSizeResponseIsNotTooLarge() throws Exception {
final byte[] buf = new byte[] { 1, 2, 3, 4 }; final byte[] buf = new byte[] { 1, 2, 3, 4 };
final CloseableHttpResponse response = make200Response(buf); final ClassicHttpResponse response = make200Response(buf);
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response); impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
impl.readResponse(); impl.readResponse();
final boolean tooLarge = impl.isLimitReached(); final boolean tooLarge = impl.isLimitReached();
final HttpResponse reconstructed = impl.getReconstructedResponse(); final ClassicHttpResponse reconstructed = impl.getReconstructedResponse();
final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity()); final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
Assert.assertFalse(tooLarge); Assert.assertFalse(tooLarge);
@ -92,13 +89,13 @@ public class TestSizeLimitedResponseReader {
@Test @Test
public void testSmallResponseIsNotTooLarge() throws Exception { public void testSmallResponseIsNotTooLarge() throws Exception {
final byte[] buf = new byte[] { 1, 2, 3 }; final byte[] buf = new byte[] { 1, 2, 3 };
final CloseableHttpResponse response = make200Response(buf); final ClassicHttpResponse response = make200Response(buf);
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response); impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
impl.readResponse(); impl.readResponse();
final boolean tooLarge = impl.isLimitReached(); final boolean tooLarge = impl.isLimitReached();
final HttpResponse reconstructed = impl.getReconstructedResponse(); final ClassicHttpResponse reconstructed = impl.getReconstructedResponse();
final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity()); final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
Assert.assertFalse(tooLarge); Assert.assertFalse(tooLarge);
@ -107,7 +104,7 @@ public class TestSizeLimitedResponseReader {
@Test @Test
public void testResponseWithNoEntityIsNotTooLarge() throws Exception { public void testResponseWithNoEntityIsNotTooLarge() throws Exception {
final CloseableHttpResponse response = make200Response(); final ClassicHttpResponse response = make200Response();
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response); impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
@ -119,7 +116,7 @@ public class TestSizeLimitedResponseReader {
@Test @Test
public void testTooLargeEntityHasOriginalContentTypes() throws Exception { public void testTooLargeEntityHasOriginalContentTypes() throws Exception {
final CloseableHttpResponse response = make200Response(); final ClassicHttpResponse response = make200Response();
final StringEntity entity = new StringEntity("large entity content"); final StringEntity entity = new StringEntity("large entity content");
response.setEntity(entity); response.setEntity(entity);
@ -127,7 +124,7 @@ public class TestSizeLimitedResponseReader {
impl.readResponse(); impl.readResponse();
final boolean tooLarge = impl.isLimitReached(); final boolean tooLarge = impl.isLimitReached();
final HttpResponse result = impl.getReconstructedResponse(); final ClassicHttpResponse result = impl.getReconstructedResponse();
final HttpEntity reconstructedEntity = result.getEntity(); final HttpEntity reconstructedEntity = result.getEntity();
Assert.assertEquals(entity.getContentEncoding(), reconstructedEntity.getContentEncoding()); Assert.assertEquals(entity.getContentEncoding(), reconstructedEntity.getContentEncoding());
Assert.assertEquals(entity.getContentType(), reconstructedEntity.getContentType()); Assert.assertEquals(entity.getContentType(), reconstructedEntity.getContentType());
@ -141,16 +138,12 @@ public class TestSizeLimitedResponseReader {
@Test @Test
public void testTooLargeResponseCombinedClosed() throws Exception { public void testTooLargeResponseCombinedClosed() throws Exception {
final AtomicBoolean closed = new AtomicBoolean(false); final AtomicBoolean closed = new AtomicBoolean(false);
final CloseableHttpResponse response = (CloseableHttpResponse) Proxy final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK") {
.newProxyInstance(ResponseProxyHandler.class.getClassLoader(), @Override
new Class<?>[] { CloseableHttpResponse.class }, public void close() throws IOException {
new ResponseProxyHandler(new BasicHttpResponse( closed.set(true);
HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK")) { }
@Override };
public void close() throws IOException {
closed.set(true);
}
});
final StringEntity entity = new StringEntity("large entity content"); final StringEntity entity = new StringEntity("large entity content");
response.setEntity(entity); response.setEntity(entity);
@ -158,7 +151,7 @@ public class TestSizeLimitedResponseReader {
impl.readResponse(); impl.readResponse();
final boolean tooLarge = impl.isLimitReached(); final boolean tooLarge = impl.isLimitReached();
try (CloseableHttpResponse result = impl.getReconstructedResponse()) { try (ClassicHttpResponse result = impl.getReconstructedResponse()) {
final HttpEntity reconstructedEntity = result.getEntity(); final HttpEntity reconstructedEntity = result.getEntity();
Assert.assertEquals(entity.getContentEncoding(), reconstructedEntity.getContentEncoding()); Assert.assertEquals(entity.getContentEncoding(), reconstructedEntity.getContentEncoding());
Assert.assertEquals(entity.getContentType(), reconstructedEntity.getContentType()); Assert.assertEquals(entity.getContentType(), reconstructedEntity.getContentType());
@ -175,14 +168,14 @@ public class TestSizeLimitedResponseReader {
@Test @Test
public void testResponseCopiesAllOriginalHeaders() throws Exception { public void testResponseCopiesAllOriginalHeaders() throws Exception {
final byte[] buf = new byte[] { 1, 2, 3 }; final byte[] buf = new byte[] { 1, 2, 3 };
final CloseableHttpResponse response = make200Response(buf); final ClassicHttpResponse response = make200Response(buf);
response.setHeader("Content-Encoding", "gzip"); response.setHeader("Content-Encoding", "gzip");
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response); impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
impl.readResponse(); impl.readResponse();
final boolean tooLarge = impl.isLimitReached(); final boolean tooLarge = impl.isLimitReached();
final HttpResponse reconstructed = impl.getReconstructedResponse(); final ClassicHttpResponse reconstructed = impl.getReconstructedResponse();
final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity()); final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
Assert.assertFalse(tooLarge); Assert.assertFalse(tooLarge);
@ -190,16 +183,14 @@ public class TestSizeLimitedResponseReader {
Assert.assertEquals("gzip", reconstructed.getFirstHeader("Content-Encoding").getValue()); Assert.assertEquals("gzip", reconstructed.getFirstHeader("Content-Encoding").getValue());
} }
private CloseableHttpResponse make200Response() { private ClassicHttpResponse make200Response() {
return Proxies.enhanceResponse(new BasicHttpResponse( return new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"));
} }
private CloseableHttpResponse make200Response(final byte[] buf) { private ClassicHttpResponse make200Response(final byte[] buf) {
final HttpResponse response = new BasicHttpResponse( final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
response.setEntity(new ByteArrayEntity(buf)); response.setEntity(new ByteArrayEntity(buf));
return Proxies.enhanceResponse(response); return response;
} }
} }

View File

@ -40,17 +40,18 @@ import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.sync.HttpClientBuilder; import org.apache.hc.client5.http.impl.sync.HttpClientBuilder;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.client5.http.protocol.ClientProtocolException; import org.apache.hc.client5.http.protocol.ClientProtocolException;
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.Header;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.MethodNotSupportedException; import org.apache.hc.core5.http.MethodNotSupportedException;
import org.apache.hc.core5.http.bootstrap.io.HttpServer;
import org.apache.hc.core5.http.bootstrap.io.ServerBootstrap;
import org.apache.hc.core5.http.config.SocketConfig; import org.apache.hc.core5.http.config.SocketConfig;
import org.apache.hc.core5.http.entity.ByteArrayEntity; import org.apache.hc.core5.http.impl.io.bootstrap.HttpServer;
import org.apache.hc.core5.http.impl.io.bootstrap.ServerBootstrap;
import org.apache.hc.core5.http.io.HttpRequestHandler; import org.apache.hc.core5.http.io.HttpRequestHandler;
import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.protocol.BasicHttpContext; import org.apache.hc.core5.http.protocol.BasicHttpContext;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
import org.junit.After; import org.junit.After;
@ -195,7 +196,7 @@ public class TestStaleWhileRevalidationReleasesConnection {
httpget.setHeader(cacheHandler.getUserContentHeader(),content); httpget.setHeader(cacheHandler.getUserContentHeader(),content);
} }
HttpResponse response = null; ClassicHttpResponse response = null;
try { try {
response = cachingClient.execute(httpget, localContext); response = cachingClient.execute(httpget, localContext);
return null; return null;
@ -256,12 +257,12 @@ public class TestStaleWhileRevalidationReleasesConnection {
* @throws java.io.IOException in case of an IO problem * @throws java.io.IOException in case of an IO problem
*/ */
@Override @Override
public void handle(final HttpRequest request, public void handle(final ClassicHttpRequest request,
final HttpResponse response, final ClassicHttpResponse response,
final HttpContext context) final HttpContext context)
throws HttpException, IOException { throws HttpException, IOException {
final String method = request.getRequestLine().getMethod().toUpperCase(Locale.ROOT); final String method = request.getMethod().toUpperCase(Locale.ROOT);
if (!"GET".equals(method) && if (!"GET".equals(method) &&
!"POST".equals(method) && !"POST".equals(method) &&
!"PUT".equals(method) !"PUT".equals(method)
@ -270,7 +271,7 @@ public class TestStaleWhileRevalidationReleasesConnection {
(method + " not supported by " + getClass().getName()); (method + " not supported by " + getClass().getName());
} }
response.setStatusCode(org.apache.hc.core5.http.HttpStatus.SC_OK); response.setCode(org.apache.hc.core5.http.HttpStatus.SC_OK);
response.addHeader("Cache-Control",getCacheContent(request)); response.addHeader("Cache-Control",getCacheContent(request));
final byte[] content = getHeaderContent(request); final byte[] content = getHeaderContent(request);
final ByteArrayEntity bae = new ByteArrayEntity(content); final ByteArrayEntity bae = new ByteArrayEntity(content);

View File

@ -33,7 +33,7 @@ import org.apache.hc.client5.http.fluent.Form;
import org.apache.hc.client5.http.fluent.Request; import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.ContentType;
/** /**
* This example demonstrates how the he HttpClient fluent API can be used to execute multiple * This example demonstrates how the he HttpClient fluent API can be used to execute multiple

View File

@ -32,7 +32,7 @@ import org.apache.hc.client5.http.fluent.Form;
import org.apache.hc.client5.http.fluent.Request; import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.ContentType;
/** /**
* This example demonstrates basics of request execution with the HttpClient fluent API. * This example demonstrates basics of request execution with the HttpClient fluent API.

View File

@ -37,11 +37,12 @@ import javax.xml.parsers.ParserConfigurationException;
import org.apache.hc.client5.http.fluent.Request; import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.client5.http.protocol.ClientProtocolException; import org.apache.hc.client5.http.protocol.ClientProtocolException;
import org.apache.hc.client5.http.protocol.HttpResponseException; import org.apache.hc.client5.http.protocol.HttpResponseException;
import org.apache.hc.client5.http.sync.ResponseHandler; import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.StatusLine; import org.apache.hc.core5.http.io.ResponseHandler;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -56,13 +57,11 @@ public class FluentResponseHandling {
.execute().handleResponse(new ResponseHandler<Document>() { .execute().handleResponse(new ResponseHandler<Document>() {
@Override @Override
public Document handleResponse(final HttpResponse response) throws IOException { public Document handleResponse(final ClassicHttpResponse response) throws IOException {
StatusLine statusLine = response.getStatusLine(); int status = response.getCode();
HttpEntity entity = response.getEntity(); HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() >= 300) { if (status >= HttpStatus.SC_REDIRECTION) {
throw new HttpResponseException( throw new HttpResponseException(status, response.getReasonPhrase());
statusLine.getStatusCode(),
statusLine.getReasonPhrase());
} }
if (entity == null) { if (entity == null) {
throw new ClientProtocolException("Response contains no content"); throw new ClientProtocolException("Response contains no content");
@ -70,7 +69,7 @@ public class FluentResponseHandling {
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
try { try {
DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
ContentType contentType = ContentType.getOrDefault(entity); ContentType contentType = EntityUtils.getContentTypeOrDefault(entity);
if (!contentType.equals(ContentType.APPLICATION_XML)) { if (!contentType.equals(ContentType.APPLICATION_XML)) {
throw new ClientProtocolException("Unexpected content type:" + contentType); throw new ClientProtocolException("Unexpected content type:" + contentType);
} }

View File

@ -28,9 +28,9 @@ package org.apache.hc.client5.http.fluent;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import org.apache.hc.client5.http.sync.ResponseHandler;
import org.apache.hc.core5.concurrent.BasicFuture; import org.apache.hc.core5.concurrent.BasicFuture;
import org.apache.hc.core5.concurrent.FutureCallback; import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.io.ResponseHandler;
public class Async { public class Async {

View File

@ -31,7 +31,7 @@ import java.io.InputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.ContentType;
/** /**
* This class represents arbitrary content of a specific type that can be consumed * This class represents arbitrary content of a specific type that can be consumed

View File

@ -30,8 +30,7 @@ import java.io.IOException;
import org.apache.hc.client5.http.impl.sync.AbstractResponseHandler; import org.apache.hc.client5.http.impl.sync.AbstractResponseHandler;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.entity.EntityUtils;
/** /**
* {@link org.apache.hc.client5.http.sync.ResponseHandler} implementation that converts * {@link org.apache.hc.client5.http.sync.ResponseHandler} implementation that converts
@ -47,7 +46,7 @@ public class ContentResponseHandler extends AbstractResponseHandler<Content> {
@Override @Override
public Content handleEntity(final HttpEntity entity) throws IOException { public Content handleEntity(final HttpEntity entity) throws IOException {
return entity != null ? return entity != null ?
new Content(EntityUtils.toByteArray(entity), ContentType.getOrDefault(entity)) : new Content(EntityUtils.toByteArray(entity), EntityUtils.getContentTypeOrDefault(entity)) :
Content.NO_CONTENT; Content.NO_CONTENT;
} }

View File

@ -27,6 +27,7 @@
package org.apache.hc.client5.http.fluent; package org.apache.hc.client5.http.fluent;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -141,7 +142,13 @@ public class Executor {
* @since 4.4 * @since 4.4
*/ */
public Executor auth(final String host, final Credentials creds) { public Executor auth(final String host, final Credentials creds) {
return auth(HttpHost.create(host), creds); final HttpHost httpHost;
try {
httpHost = HttpHost.create(host);
} catch (URISyntaxException ex) {
throw new IllegalArgumentException("Invalid host: " + host);
}
return auth(httpHost, creds);
} }
public Executor authPreemptive(final HttpHost host) { public Executor authPreemptive(final HttpHost host) {
@ -160,7 +167,13 @@ public class Executor {
* @since 4.4 * @since 4.4
*/ */
public Executor authPreemptive(final String host) { public Executor authPreemptive(final String host) {
return authPreemptive(HttpHost.create(host)); final HttpHost httpHost;
try {
httpHost = HttpHost.create(host);
} catch (URISyntaxException ex) {
throw new IllegalArgumentException("Invalid host: " + host);
}
return authPreemptive(httpHost);
} }
public Executor authPreemptiveProxy(final HttpHost proxy) { public Executor authPreemptiveProxy(final HttpHost proxy) {
@ -179,7 +192,13 @@ public class Executor {
* @since 4.4 * @since 4.4
*/ */
public Executor authPreemptiveProxy(final String proxy) { public Executor authPreemptiveProxy(final String proxy) {
return authPreemptiveProxy(HttpHost.create(proxy)); final HttpHost httpHost;
try {
httpHost = HttpHost.create(proxy);
} catch (URISyntaxException ex) {
throw new IllegalArgumentException("Invalid host: " + proxy);
}
return authPreemptiveProxy(httpHost);
} }
public Executor auth(final Credentials cred) { public Executor auth(final Credentials cred) {
@ -256,7 +275,7 @@ public class Executor {
* @since 4.4 * @since 4.4
*/ */
public static void closeIdleConnections() { public static void closeIdleConnections() {
CONNMGR.closeIdleConnections(0, TimeUnit.MICROSECONDS); CONNMGR.closeIdle(0, TimeUnit.MICROSECONDS);
} }
} }

View File

@ -1,105 +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.fluent;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.hc.core5.http.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.entity.ContentType;
import org.apache.hc.core5.util.Args;
class InternalByteArrayEntity extends AbstractHttpEntity implements Cloneable {
private final byte[] b;
private final int off, len;
public InternalByteArrayEntity(final byte[] b, final ContentType contentType) {
super();
Args.notNull(b, "Source byte array");
this.b = b;
this.off = 0;
this.len = this.b.length;
if (contentType != null) {
setContentType(contentType.toString());
}
}
public InternalByteArrayEntity(final byte[] b, final int off, final int len, final ContentType contentType) {
super();
Args.notNull(b, "Source byte array");
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) < 0) || ((off + len) > b.length)) {
throw new IndexOutOfBoundsException("off: " + off + " len: " + len + " b.length: " + b.length);
}
this.b = b;
this.off = off;
this.len = len;
if (contentType != null) {
setContentType(contentType.toString());
}
}
public InternalByteArrayEntity(final byte[] b) {
this(b, null);
}
public InternalByteArrayEntity(final byte[] b, final int off, final int len) {
this(b, off, len, null);
}
@Override
public boolean isRepeatable() {
return true;
}
@Override
public long getContentLength() {
return this.len;
}
@Override
public InputStream getContent() {
return new ByteArrayInputStream(this.b, this.off, this.len);
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
Args.notNull(outstream, "Output stream");
outstream.write(this.b, this.off, this.len);
outstream.flush();
}
@Override
public boolean isStreaming() {
return false;
}
}

View File

@ -1,85 +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.fluent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.hc.core5.http.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.entity.ContentType;
import org.apache.hc.core5.util.Args;
class InternalFileEntity extends AbstractHttpEntity implements Cloneable {
private final File file;
public InternalFileEntity(final File file, final ContentType contentType) {
super();
this.file = Args.notNull(file, "File");
if (contentType != null) {
setContentType(contentType.toString());
}
}
@Override
public boolean isRepeatable() {
return true;
}
@Override
public long getContentLength() {
return this.file.length();
}
@Override
public InputStream getContent() throws IOException {
return new FileInputStream(this.file);
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
Args.notNull(outstream, "Output stream");
try (InputStream instream = new FileInputStream(this.file)) {
final byte[] tmp = new byte[4096];
int l;
while ((l = instream.read(tmp)) != -1) {
outstream.write(tmp, 0, l);
}
outstream.flush();
}
}
@Override
public boolean isStreaming() {
return false;
}
}

View File

@ -1,142 +0,0 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.hc.client5.http.fluent;
import java.net.URI;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.methods.Configurable;
import org.apache.hc.client5.http.methods.HttpExecutionAware;
import org.apache.hc.client5.http.methods.HttpUriRequest;
import org.apache.hc.core5.annotation.NotThreadSafe;
import org.apache.hc.core5.concurrent.Cancellable;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.RequestLine;
import org.apache.hc.core5.http.message.AbstractHttpMessage;
import org.apache.hc.core5.http.message.BasicRequestLine;
import org.apache.hc.core5.util.Args;
@NotThreadSafe
class InternalHttpRequest extends AbstractHttpMessage
implements HttpUriRequest, HttpExecutionAware, Configurable {
private static final long serialVersionUID = 1L;
private final String method;
private ProtocolVersion version;
private URI uri;
private RequestConfig config;
private final AtomicBoolean aborted;
private final AtomicReference<Cancellable> cancellableRef;
InternalHttpRequest(final String method, final URI requestURI) {
Args.notBlank(method, "Method");
Args.notNull(requestURI, "Request URI");
this.method = method;
this.uri = requestURI;
this.aborted = new AtomicBoolean(false);
this.cancellableRef = new AtomicReference<>(null);
}
public void setProtocolVersion(final ProtocolVersion version) {
this.version = version;
}
@Override
public ProtocolVersion getProtocolVersion() {
return version != null ? version : HttpVersion.HTTP_1_1;
}
@Override
public String getMethod() {
return this.method;
}
@Override
public URI getURI() {
return this.uri;
}
@Override
public void abort() throws UnsupportedOperationException {
if (this.aborted.compareAndSet(false, true)) {
final Cancellable cancellable = this.cancellableRef.getAndSet(null);
if (cancellable != null) {
cancellable.cancel();
}
}
}
@Override
public boolean isAborted() {
return this.aborted.get();
}
@Override
public void setCancellable(final Cancellable cancellable) {
if (!this.aborted.get()) {
this.cancellableRef.set(cancellable);
}
}
@Override
public RequestLine getRequestLine() {
final ProtocolVersion ver = getProtocolVersion();
final URI uriCopy = getURI();
String uritext = null;
if (uriCopy != null) {
uritext = uriCopy.toASCIIString();
}
if (uritext == null || uritext.isEmpty()) {
uritext = "/";
}
return new BasicRequestLine(getMethod(), uritext, ver);
}
@Override
public RequestConfig getConfig() {
return config;
}
public void setConfig(final RequestConfig config) {
this.config = config;
}
public void setURI(final URI uri) {
this.uri = uri;
}
@Override
public String toString() {
return getMethod() + " " + getURI() + " " + getProtocolVersion();
}
}

View File

@ -1,98 +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.fluent;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.hc.core5.http.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.entity.ContentType;
import org.apache.hc.core5.util.Args;
class InternalInputStreamEntity extends AbstractHttpEntity {
private final InputStream content;
private final long length;
public InternalInputStreamEntity(final InputStream instream, final long length, final ContentType contentType) {
super();
this.content = Args.notNull(instream, "Source input stream");
this.length = length;
if (contentType != null) {
setContentType(contentType.toString());
}
}
@Override
public boolean isRepeatable() {
return false;
}
@Override
public long getContentLength() {
return this.length;
}
@Override
public InputStream getContent() throws IOException {
return this.content;
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
Args.notNull(outstream, "Output stream");
try (InputStream instream = this.content) {
final byte[] buffer = new byte[4096];
int l;
if (this.length < 0) {
// consume until EOF
while ((l = instream.read(buffer)) != -1) {
outstream.write(buffer, 0, l);
}
} else {
// consume no more than length
long remaining = this.length;
while (remaining > 0) {
l = instream.read(buffer, 0, (int) Math.min(4096, remaining));
if (l == -1) {
break;
}
outstream.write(buffer, 0, l);
remaining -= l;
}
}
}
}
@Override
public boolean isStreaming() {
return true;
}
}

View File

@ -30,6 +30,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -51,16 +52,20 @@ import org.apache.hc.client5.http.methods.HttpPatch;
import org.apache.hc.client5.http.methods.HttpPost; import org.apache.hc.client5.http.methods.HttpPost;
import org.apache.hc.client5.http.methods.HttpPut; import org.apache.hc.client5.http.methods.HttpPut;
import org.apache.hc.client5.http.methods.HttpTrace; import org.apache.hc.client5.http.methods.HttpTrace;
import org.apache.hc.client5.http.utils.URLEncodedUtils; import org.apache.hc.client5.http.methods.HttpUriRequestBase;
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.Header;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.NameValuePair; import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.io.entity.FileEntity;
import org.apache.hc.core5.http.io.entity.InputStreamEntity;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.net.URLEncodedUtils;
public class Request { public class Request {
@ -68,7 +73,7 @@ public class Request {
public static final Locale DATE_LOCALE = Locale.US; public static final Locale DATE_LOCALE = Locale.US;
public static final TimeZone TIME_ZONE = TimeZone.getTimeZone("GMT"); public static final TimeZone TIME_ZONE = TimeZone.getTimeZone("GMT");
private final InternalHttpRequest request; private final HttpUriRequestBase request;
private Boolean useExpectContinue; private Boolean useExpectContinue;
private Integer socketTmeout; private Integer socketTmeout;
private Integer connectTimeout; private Integer connectTimeout;
@ -77,83 +82,83 @@ public class Request {
private SimpleDateFormat dateFormatter; private SimpleDateFormat dateFormatter;
public static Request create(final String methodName, final String uri) { public static Request create(final String methodName, final String uri) {
return new Request(new InternalHttpRequest(methodName, URI.create(uri))); return new Request(new HttpUriRequestBase(methodName, URI.create(uri)));
} }
public static Request create(final String methodName, final URI uri) { public static Request create(final String methodName, final URI uri) {
return new Request(new InternalHttpRequest(methodName, uri)); return new Request(new HttpUriRequestBase(methodName, uri));
} }
public static Request Get(final URI uri) { public static Request Get(final URI uri) {
return new Request(new InternalHttpRequest(HttpGet.METHOD_NAME, uri)); return new Request(new HttpUriRequestBase(HttpGet.METHOD_NAME, uri));
} }
public static Request Get(final String uri) { public static Request Get(final String uri) {
return new Request(new InternalHttpRequest(HttpGet.METHOD_NAME, URI.create(uri))); return new Request(new HttpUriRequestBase(HttpGet.METHOD_NAME, URI.create(uri)));
} }
public static Request Head(final URI uri) { public static Request Head(final URI uri) {
return new Request(new InternalHttpRequest(HttpHead.METHOD_NAME, uri)); return new Request(new HttpUriRequestBase(HttpHead.METHOD_NAME, uri));
} }
public static Request Head(final String uri) { public static Request Head(final String uri) {
return new Request(new InternalHttpRequest(HttpHead.METHOD_NAME, URI.create(uri))); return new Request(new HttpUriRequestBase(HttpHead.METHOD_NAME, URI.create(uri)));
} }
public static Request Post(final URI uri) { public static Request Post(final URI uri) {
return new Request(new InternalHttpRequest(HttpPost.METHOD_NAME, uri)); return new Request(new HttpUriRequestBase(HttpPost.METHOD_NAME, uri));
} }
public static Request Post(final String uri) { public static Request Post(final String uri) {
return new Request(new InternalHttpRequest(HttpPost.METHOD_NAME, URI.create(uri))); return new Request(new HttpUriRequestBase(HttpPost.METHOD_NAME, URI.create(uri)));
} }
public static Request Patch(final URI uri) { public static Request Patch(final URI uri) {
return new Request(new InternalHttpRequest(HttpPatch.METHOD_NAME, uri)); return new Request(new HttpUriRequestBase(HttpPatch.METHOD_NAME, uri));
} }
public static Request Patch(final String uri) { public static Request Patch(final String uri) {
return new Request(new InternalHttpRequest(HttpPatch.METHOD_NAME, URI.create(uri))); return new Request(new HttpUriRequestBase(HttpPatch.METHOD_NAME, URI.create(uri)));
} }
public static Request Put(final URI uri) { public static Request Put(final URI uri) {
return new Request(new InternalHttpRequest(HttpPut.METHOD_NAME, uri)); return new Request(new HttpUriRequestBase(HttpPut.METHOD_NAME, uri));
} }
public static Request Put(final String uri) { public static Request Put(final String uri) {
return new Request(new InternalHttpRequest(HttpPut.METHOD_NAME, URI.create(uri))); return new Request(new HttpUriRequestBase(HttpPut.METHOD_NAME, URI.create(uri)));
} }
public static Request Trace(final URI uri) { public static Request Trace(final URI uri) {
return new Request(new InternalHttpRequest(HttpTrace.METHOD_NAME, uri)); return new Request(new HttpUriRequestBase(HttpTrace.METHOD_NAME, uri));
} }
public static Request Trace(final String uri) { public static Request Trace(final String uri) {
return new Request(new InternalHttpRequest(HttpTrace.METHOD_NAME, URI.create(uri))); return new Request(new HttpUriRequestBase(HttpTrace.METHOD_NAME, URI.create(uri)));
} }
public static Request Delete(final URI uri) { public static Request Delete(final URI uri) {
return new Request(new InternalHttpRequest(HttpDelete.METHOD_NAME, uri)); return new Request(new HttpUriRequestBase(HttpDelete.METHOD_NAME, uri));
} }
public static Request Delete(final String uri) { public static Request Delete(final String uri) {
return new Request(new InternalHttpRequest(HttpDelete.METHOD_NAME, URI.create(uri))); return new Request(new HttpUriRequestBase(HttpDelete.METHOD_NAME, URI.create(uri)));
} }
public static Request Options(final URI uri) { public static Request Options(final URI uri) {
return new Request(new InternalHttpRequest(HttpOptions.METHOD_NAME, uri)); return new Request(new HttpUriRequestBase(HttpOptions.METHOD_NAME, uri));
} }
public static Request Options(final String uri) { public static Request Options(final String uri) {
return new Request(new InternalHttpRequest(HttpOptions.METHOD_NAME, URI.create(uri))); return new Request(new HttpUriRequestBase(HttpOptions.METHOD_NAME, URI.create(uri)));
} }
Request(final InternalHttpRequest request) { Request(final HttpUriRequestBase request) {
super(); super();
this.request = request; this.request = request;
} }
HttpResponse internalExecute( ClassicHttpResponse internalExecute(
final CloseableHttpClient client, final CloseableHttpClient client,
final HttpContext localContext) throws IOException { final HttpContext localContext) throws IOException {
final RequestConfig.Builder builder; final RequestConfig.Builder builder;
@ -261,7 +266,7 @@ public class Request {
//// HTTP protocol parameter operations //// HTTP protocol parameter operations
public Request version(final HttpVersion version) { public Request version(final HttpVersion version) {
this.request.setProtocolVersion(version); this.request.setVersion(version);
return this; return this;
} }
@ -298,7 +303,11 @@ public class Request {
* @since 4.4 * @since 4.4
*/ */
public Request viaProxy(final String proxy) { public Request viaProxy(final String proxy) {
this.proxy = HttpHost.create(proxy); try {
this.proxy = HttpHost.create(proxy);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid host");
}
return this; return this;
} }
@ -330,46 +339,46 @@ public class Request {
public Request bodyString(final String s, final ContentType contentType) { public Request bodyString(final String s, final ContentType contentType) {
final Charset charset = contentType != null ? contentType.getCharset() : null; final Charset charset = contentType != null ? contentType.getCharset() : null;
final byte[] raw = charset != null ? s.getBytes(charset) : s.getBytes(); final byte[] raw = charset != null ? s.getBytes(charset) : s.getBytes();
return body(new InternalByteArrayEntity(raw, contentType)); return body(new ByteArrayEntity(raw, contentType));
} }
public Request bodyFile(final File file, final ContentType contentType) { public Request bodyFile(final File file, final ContentType contentType) {
return body(new InternalFileEntity(file, contentType)); return body(new FileEntity(file, contentType));
} }
public Request bodyByteArray(final byte[] b) { public Request bodyByteArray(final byte[] b) {
return body(new InternalByteArrayEntity(b)); return body(new ByteArrayEntity(b));
} }
/** /**
* @since 4.4 * @since 4.4
*/ */
public Request bodyByteArray(final byte[] b, final ContentType contentType) { public Request bodyByteArray(final byte[] b, final ContentType contentType) {
return body(new InternalByteArrayEntity(b, contentType)); return body(new ByteArrayEntity(b, contentType));
} }
public Request bodyByteArray(final byte[] b, final int off, final int len) { public Request bodyByteArray(final byte[] b, final int off, final int len) {
return body(new InternalByteArrayEntity(b, off, len)); return body(new ByteArrayEntity(b, off, len));
} }
/** /**
* @since 4.4 * @since 4.4
*/ */
public Request bodyByteArray(final byte[] b, final int off, final int len, final ContentType contentType) { public Request bodyByteArray(final byte[] b, final int off, final int len, final ContentType contentType) {
return body(new InternalByteArrayEntity(b, off, len, contentType)); return body(new ByteArrayEntity(b, off, len, contentType));
} }
public Request bodyStream(final InputStream instream) { public Request bodyStream(final InputStream instream) {
return body(new InternalInputStreamEntity(instream, -1, null)); return body(new InputStreamEntity(instream, -1, null));
} }
public Request bodyStream(final InputStream instream, final ContentType contentType) { public Request bodyStream(final InputStream instream, final ContentType contentType) {
return body(new InternalInputStreamEntity(instream, -1, contentType)); return body(new InputStreamEntity(instream, -1, contentType));
} }
@Override @Override
public String toString() { public String toString() {
return this.request.getRequestLine().toString(); return this.request.toString();
} }
} }

View File

@ -31,21 +31,24 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.apache.hc.client5.http.protocol.ClientProtocolException;
import org.apache.hc.client5.http.protocol.HttpResponseException; import org.apache.hc.client5.http.protocol.HttpResponseException;
import org.apache.hc.client5.http.sync.ResponseHandler; import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.StatusLine; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.entity.ByteArrayEntity; import org.apache.hc.core5.http.io.ResponseHandler;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.EntityUtils;
public class Response { public class Response {
private final HttpResponse response; private final ClassicHttpResponse response;
private boolean consumed; private boolean consumed;
Response(final HttpResponse response) { Response(final ClassicHttpResponse response) {
super(); super();
this.response = response; this.response = response;
} }
@ -87,6 +90,8 @@ public class Response {
assertNotConsumed(); assertNotConsumed();
try { try {
return handler.handleResponse(this.response); return handler.handleResponse(this.response);
} catch (HttpException ex) {
throw new ClientProtocolException(ex);
} finally { } finally {
dispose(); dispose();
} }
@ -103,7 +108,7 @@ public class Response {
if (entity != null) { if (entity != null) {
final ByteArrayEntity byteArrayEntity = new ByteArrayEntity( final ByteArrayEntity byteArrayEntity = new ByteArrayEntity(
EntityUtils.toByteArray(entity)); EntityUtils.toByteArray(entity));
final ContentType contentType = ContentType.getOrDefault(entity); final ContentType contentType = EntityUtils.getContentTypeOrDefault(entity);
byteArrayEntity.setContentType(contentType.toString()); byteArrayEntity.setContentType(contentType.toString());
this.response.setEntity(byteArrayEntity); this.response.setEntity(byteArrayEntity);
} }
@ -115,10 +120,9 @@ public class Response {
public void saveContent(final File file) throws IOException { public void saveContent(final File file) throws IOException {
assertNotConsumed(); assertNotConsumed();
final StatusLine statusLine = response.getStatusLine(); final int status = response.getCode();
if (statusLine.getStatusCode() >= 300) { if (status >= HttpStatus.SC_REDIRECTION) {
throw new HttpResponseException(statusLine.getStatusCode(), throw new HttpResponseException(status, response.getReasonPhrase());
statusLine.getReasonPhrase());
} }
try (FileOutputStream out = new FileOutputStream(file)) { try (FileOutputStream out = new FileOutputStream(file)) {
final HttpEntity entity = this.response.getEntity(); final HttpEntity entity = this.response.getEntity();

View File

@ -33,16 +33,16 @@ import java.nio.charset.Charset;
import org.apache.hc.client5.http.localserver.LocalServerTestBase; import org.apache.hc.client5.http.localserver.LocalServerTestBase;
import org.apache.hc.client5.http.protocol.ClientProtocolException; import org.apache.hc.client5.http.protocol.ClientProtocolException;
import org.apache.hc.client5.http.sync.ResponseHandler; 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.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHost; 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.entity.ContentType;
import org.apache.hc.core5.http.entity.EntityUtils;
import org.apache.hc.core5.http.entity.StringEntity;
import org.apache.hc.core5.http.io.HttpRequestHandler; import org.apache.hc.core5.http.io.HttpRequestHandler;
import org.apache.hc.core5.http.io.ResponseHandler;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
@ -58,8 +58,8 @@ public class TestFluent extends LocalServerTestBase {
@Override @Override
public void handle( public void handle(
final HttpRequest request, final ClassicHttpRequest request,
final HttpResponse response, final ClassicHttpResponse response,
final HttpContext context) throws HttpException, IOException { final HttpContext context) throws HttpException, IOException {
response.setEntity(new StringEntity("All is well", ContentType.TEXT_PLAIN)); response.setEntity(new StringEntity("All is well", ContentType.TEXT_PLAIN));
} }
@ -69,13 +69,13 @@ public class TestFluent extends LocalServerTestBase {
@Override @Override
public void handle( public void handle(
final HttpRequest request, final ClassicHttpRequest request,
final HttpResponse response, final ClassicHttpResponse response,
final HttpContext context) throws HttpException, IOException { final HttpContext context) throws HttpException, IOException {
HttpEntity responseEntity = null; HttpEntity responseEntity = null;
final HttpEntity requestEntity = request.getEntity(); final HttpEntity requestEntity = request.getEntity();
if (requestEntity != null) { if (requestEntity != null) {
final ContentType contentType = ContentType.getOrDefault(requestEntity); final ContentType contentType = EntityUtils.getContentTypeOrDefault(requestEntity);
if (ContentType.TEXT_PLAIN.getMimeType().equals(contentType.getMimeType())) { if (ContentType.TEXT_PLAIN.getMimeType().equals(contentType.getMimeType())) {
responseEntity = new StringEntity( responseEntity = new StringEntity(
EntityUtils.toString(requestEntity), ContentType.TEXT_PLAIN); EntityUtils.toString(requestEntity), ContentType.TEXT_PLAIN);
@ -164,7 +164,7 @@ public class TestFluent extends LocalServerTestBase {
@Override @Override
public Object handleResponse( public Object handleResponse(
final HttpResponse response) throws IOException { final ClassicHttpResponse response) throws IOException {
return null; return null;
} }

View File

@ -40,7 +40,7 @@
<packaging>bundle</packaging> <packaging>bundle</packaging>
<properties> <properties>
<httpcore.osgi.import.version>"5.0-alpha1"</httpcore.osgi.import.version> <httpcore.osgi.import.version>"5.0-alpha2"</httpcore.osgi.import.version>
<log4j.osgi.import.version>"2.7"</log4j.osgi.import.version> <log4j.osgi.import.version>"2.7"</log4j.osgi.import.version>
<pax.url.version>2.4.1</pax.url.version> <pax.url.version>2.4.1</pax.url.version>
<pax.exam.version>4.5.0</pax.exam.version> <pax.exam.version>4.5.0</pax.exam.version>
@ -198,17 +198,7 @@
org.osgi.framework, org.osgi.framework,
org.osgi.service.cm, org.osgi.service.cm,
org.apache.logging.log4j;version=${log4j.osgi.import.version}, org.apache.logging.log4j;version=${log4j.osgi.import.version},
org.apache.hc.core5.concurrent;version=${httpcore.osgi.import.version}, org.apache.hc.core5.*;version=${httpcore.osgi.import.version},
org.apache.hc.core5.pool;version=${httpcore.osgi.import.version},
org.apache.hc.core5.ssl;version=${httpcore.osgi.import.version},
org.apache.hc.core5.util;version=${httpcore.osgi.import.version},
org.apache.hc.core5.http;version=${httpcore.osgi.import.version},
org.apache.hc.core5.http.config;version=${httpcore.osgi.import.version},
org.apache.hc.core5.http.entity;version=${httpcore.osgi.import.version},
org.apache.hc.core5.http.message;version=${httpcore.osgi.import.version},
org.apache.hc.core5.http.io;version=${httpcore.osgi.import.version},
org.apache.hc.core5.http.protocol;version=${httpcore.osgi.import.version},
org.apache.hc.core5.http.impl.io;version=${httpcore.osgi.import.version},
net.sf.ehcache.*;resolution:=optional, net.sf.ehcache.*;resolution:=optional,
net.spy.memcached.*;resolution:=optional net.spy.memcached.*;resolution:=optional
</Import-Package> </Import-Package>

View File

@ -43,7 +43,7 @@ import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.entity.mime.StringBody; import org.apache.hc.client5.http.entity.mime.StringBody;
import org.apache.hc.client5.http.methods.HttpPost; import org.apache.hc.client5.http.methods.HttpPost;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.ContentType;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Configuration;

View File

@ -31,7 +31,7 @@ import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.win.WinHttpClients; import org.apache.hc.client5.http.impl.win.WinHttpClients;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.client5.http.methods.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.core5.http.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.EntityUtils;
/** /**
* This example demonstrates how to create HttpClient pre-configured * This example demonstrates how to create HttpClient pre-configured
@ -52,11 +52,11 @@ public class ClientWinAuth {
try { try {
HttpGet httpget = new HttpGet("http://winhost/"); HttpGet httpget = new HttpGet("http://winhost/");
System.out.println("Executing request " + httpget.getRequestLine()); System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
CloseableHttpResponse response = httpclient.execute(httpget); CloseableHttpResponse response = httpclient.execute(httpget);
try { try {
System.out.println("----------------------------------------"); System.out.println("----------------------------------------");
System.out.println(response.getStatusLine()); System.out.println(response.getCode() + " " + response.getReasonPhrase());
EntityUtils.consume(response.getEntity()); EntityUtils.consume(response.getEntity());
} finally { } finally {
response.close(); response.close();

View File

@ -30,7 +30,8 @@ package org.apache.hc.client5.http.impl.win;
import org.apache.hc.client5.http.auth.AuthScheme; import org.apache.hc.client5.http.auth.AuthScheme;
import org.apache.hc.client5.http.auth.AuthSchemeProvider; import org.apache.hc.client5.http.auth.AuthSchemeProvider;
import org.apache.hc.client5.http.config.AuthSchemes; import org.apache.hc.client5.http.config.AuthSchemes;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
/** /**
@ -42,7 +43,7 @@ import org.apache.hc.core5.http.protocol.HttpContext;
* *
* @since 4.4 * @since 4.4
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class WindowsNTLMSchemeFactory implements AuthSchemeProvider { public class WindowsNTLMSchemeFactory implements AuthSchemeProvider {
private final String servicePrincipalName; private final String servicePrincipalName;

View File

@ -29,7 +29,6 @@ package org.apache.hc.client5.http.impl.win;
import java.security.Principal; import java.security.Principal;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.hc.client5.http.RouteInfo;
import org.apache.hc.client5.http.auth.AuthChallenge; import org.apache.hc.client5.http.auth.AuthChallenge;
import org.apache.hc.client5.http.auth.AuthScheme; import org.apache.hc.client5.http.auth.AuthScheme;
import org.apache.hc.client5.http.auth.AuthenticationException; import org.apache.hc.client5.http.auth.AuthenticationException;
@ -37,11 +36,10 @@ import org.apache.hc.client5.http.auth.BasicUserPrincipal;
import org.apache.hc.client5.http.auth.CredentialsProvider; import org.apache.hc.client5.http.auth.CredentialsProvider;
import org.apache.hc.client5.http.auth.MalformedChallengeException; import org.apache.hc.client5.http.auth.MalformedChallengeException;
import org.apache.hc.client5.http.config.AuthSchemes; import org.apache.hc.client5.http.config.AuthSchemes;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.annotation.NotThreadSafe;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.net.URIAuthority;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -68,7 +66,6 @@ import com.sun.jna.ptr.IntByReference;
* *
* @since 4.4 * @since 4.4
*/ */
@NotThreadSafe
public class WindowsNegotiateScheme implements AuthScheme { public class WindowsNegotiateScheme implements AuthScheme {
private final Logger log = LogManager.getLogger(getClass()); private final Logger log = LogManager.getLogger(getClass());
@ -196,7 +193,7 @@ public class WindowsNegotiateScheme implements AuthScheme {
throw new Win32Exception(rc); throw new Win32Exception(rc);
} }
final String targetName = getServicePrincipalName(context); final String targetName = getServicePrincipalName(request);
response = getToken(null, null, targetName); response = getToken(null, null, targetName);
} catch (final RuntimeException ex) { } catch (final RuntimeException ex) {
failAuthCleanup(); failAuthCleanup();
@ -213,7 +210,7 @@ public class WindowsNegotiateScheme implements AuthScheme {
final byte[] continueTokenBytes = Base64.decodeBase64(challenge); final byte[] continueTokenBytes = Base64.decodeBase64(challenge);
final SecBufferDesc continueTokenBuffer = new SecBufferDesc( final SecBufferDesc continueTokenBuffer = new SecBufferDesc(
Sspi.SECBUFFER_TOKEN, continueTokenBytes); Sspi.SECBUFFER_TOKEN, continueTokenBytes);
final String targetName = getServicePrincipalName(context); final String targetName = getServicePrincipalName(request);
response = getToken(this.sspiContext, continueTokenBuffer, targetName); response = getToken(this.sspiContext, continueTokenBuffer, targetName);
} catch (final RuntimeException ex) { } catch (final RuntimeException ex) {
failAuthCleanup(); failAuthCleanup();
@ -236,23 +233,14 @@ public class WindowsNegotiateScheme implements AuthScheme {
// at http://www.chromium.org/developers/design-documents/http-authentication). Here, // at http://www.chromium.org/developers/design-documents/http-authentication). Here,
// I've chosen to use the host that has been provided in HttpHost so that I don't incur // I've chosen to use the host that has been provided in HttpHost so that I don't incur
// any additional DNS lookup cost. // any additional DNS lookup cost.
private String getServicePrincipalName(final HttpContext context) { private String getServicePrincipalName(final HttpRequest request) {
final String spn; String spn = null;
if (this.servicePrincipalName != null) { if (this.servicePrincipalName != null) {
spn = this.servicePrincipalName; spn = this.servicePrincipalName;
} else { } else {
final HttpClientContext clientContext = HttpClientContext.adapt(context); final URIAuthority authority = request.getAuthority();
final HttpHost target = clientContext.getTargetHost(); if (authority != null) {
if (target != null) { spn = "HTTP/" + authority.getHostName();
spn = "HTTP/" + target.getHostName();
} else {
final RouteInfo route = clientContext.getHttpRoute();
if (route != null) {
spn = "HTTP/" + route.getTargetHost().getHostName();
} else {
// Should not happen
spn = null;
}
} }
} }
if (this.log.isDebugEnabled()) { if (this.log.isDebugEnabled()) {

View File

@ -30,7 +30,8 @@ package org.apache.hc.client5.http.impl.win;
import org.apache.hc.client5.http.auth.AuthScheme; import org.apache.hc.client5.http.auth.AuthScheme;
import org.apache.hc.client5.http.auth.AuthSchemeProvider; import org.apache.hc.client5.http.auth.AuthSchemeProvider;
import org.apache.hc.client5.http.config.AuthSchemes; import org.apache.hc.client5.http.config.AuthSchemes;
import org.apache.hc.core5.annotation.Immutable; import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
/** /**
@ -42,7 +43,7 @@ import org.apache.hc.core5.http.protocol.HttpContext;
* *
* @since 4.4 * @since 4.4
*/ */
@Immutable @Contract(threading = ThreadingBehavior.IMMUTABLE)
public class WindowsNegotiateSchemeFactory implements AuthSchemeProvider { public class WindowsNegotiateSchemeFactory implements AuthSchemeProvider {
private final String servicePrincipalName; private final String servicePrincipalName;

View File

@ -34,18 +34,18 @@ import org.apache.hc.client5.http.config.AuthSchemes;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient; import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.sync.HttpClientBuilder; import org.apache.hc.client5.http.impl.sync.HttpClientBuilder;
import org.apache.hc.client5.http.localserver.LocalServerTestBase; import org.apache.hc.client5.http.localserver.LocalServerTestBase;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.client5.http.impl.sync.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost; 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.HttpStatus;
import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.entity.EntityUtils;
import org.apache.hc.core5.http.io.HttpRequestHandler; import org.apache.hc.core5.http.io.HttpRequestHandler;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpContext;
import org.junit.After; import org.junit.After;
import org.junit.Assume; import org.junit.Assume;
@ -69,11 +69,11 @@ public class TestWindowsNegotiateScheme extends LocalServerTestBase {
@Override @Override
public void handle( public void handle(
final HttpRequest request, final ClassicHttpRequest request,
final HttpResponse response, final ClassicHttpResponse response,
final HttpContext context) throws HttpException, IOException { final HttpContext context) throws HttpException, IOException {
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, AuthSchemes.SPNEGO); response.addHeader(HttpHeaders.WWW_AUTHENTICATE, AuthSchemes.SPNEGO);
response.setStatusCode(HttpStatus.SC_UNAUTHORIZED); response.setCode(HttpStatus.SC_UNAUTHORIZED);
} }
}); });

View File

@ -29,7 +29,7 @@ package org.apache.hc.client5.http.examples;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient; import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.sync.HttpClients; import org.apache.hc.client5.http.impl.sync.HttpClients;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.client5.http.impl.sync.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
/** /**
@ -41,10 +41,10 @@ public class ClientAbortMethod {
try (CloseableHttpClient httpclient = HttpClients.createDefault()) { try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
HttpGet httpget = new HttpGet("http://httpbin.org/get"); HttpGet httpget = new HttpGet("http://httpbin.org/get");
System.out.println("Executing request " + httpget.getURI()); System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
try (CloseableHttpResponse response = httpclient.execute(httpget)) { try (CloseableHttpResponse response = httpclient.execute(httpget)) {
System.out.println("----------------------------------------"); System.out.println("----------------------------------------");
System.out.println(response.getStatusLine()); System.out.println(response.getCode() + " " + response.getReasonPhrase());
// Do not feel like reading the response body // Do not feel like reading the response body
// Call abort on the request object // Call abort on the request object
httpget.abort(); httpget.abort();

View File

@ -31,9 +31,9 @@ import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.impl.sync.BasicCredentialsProvider; import org.apache.hc.client5.http.impl.sync.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient; import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.sync.HttpClients; import org.apache.hc.client5.http.impl.sync.HttpClients;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.client5.http.impl.sync.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.core5.http.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.EntityUtils;
/** /**
* A simple example that uses HttpClient to execute an HTTP request against * A simple example that uses HttpClient to execute an HTTP request against
@ -51,10 +51,10 @@ public class ClientAuthentication {
.build()) { .build()) {
HttpGet httpget = new HttpGet("http://httpbin.org/basic-auth/user/passwd"); HttpGet httpget = new HttpGet("http://httpbin.org/basic-auth/user/passwd");
System.out.println("Executing request " + httpget.getRequestLine()); System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
try (CloseableHttpResponse response = httpclient.execute(httpget)) { try (CloseableHttpResponse response = httpclient.execute(httpget)) {
System.out.println("----------------------------------------"); System.out.println("----------------------------------------");
System.out.println(response.getStatusLine()); System.out.println(response.getCode() + " " + response.getReasonPhrase());
System.out.println(EntityUtils.toString(response.getEntity())); System.out.println(EntityUtils.toString(response.getEntity()));
} }
} }

View File

@ -31,11 +31,11 @@ import java.io.FileInputStream;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient; import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.sync.HttpClients; import org.apache.hc.client5.http.impl.sync.HttpClients;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.client5.http.impl.sync.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpPost; import org.apache.hc.client5.http.methods.HttpPost;
import org.apache.hc.core5.http.entity.ContentType; import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.entity.InputStreamEntity; import org.apache.hc.core5.http.io.entity.InputStreamEntity;
/** /**
* Example how to use unbuffered chunk-encoded POST request. * Example how to use unbuffered chunk-encoded POST request.
@ -63,10 +63,10 @@ public class ClientChunkEncodedPost {
httppost.setEntity(reqEntity); httppost.setEntity(reqEntity);
System.out.println("Executing request: " + httppost.getRequestLine()); System.out.println("Executing request " + httppost.getMethod() + " " + httppost.getUri());
try (CloseableHttpResponse response = httpclient.execute(httppost)) { try (CloseableHttpResponse response = httpclient.execute(httppost)) {
System.out.println("----------------------------------------"); System.out.println("----------------------------------------");
System.out.println(response.getStatusLine()); System.out.println(response.getCode() + " " + response.getReasonPhrase());
System.out.println(EntityUtils.toString(response.getEntity())); System.out.println(EntityUtils.toString(response.getEntity()));
} }
} }

View File

@ -53,29 +53,28 @@ import org.apache.hc.client5.http.impl.sync.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient; import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.sync.HttpClients; import org.apache.hc.client5.http.impl.sync.HttpClients;
import org.apache.hc.client5.http.io.ManagedHttpClientConnection; import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.client5.http.impl.sync.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory; import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
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.Header;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost; 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.ParseException; import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.config.ConnectionConfig; import org.apache.hc.core5.http.config.ConnectionConfig;
import org.apache.hc.core5.http.config.MessageConstraints; import org.apache.hc.core5.http.config.H1Config;
import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.config.SocketConfig; import org.apache.hc.core5.http.config.SocketConfig;
import org.apache.hc.core5.http.entity.EntityUtils; import org.apache.hc.core5.http.impl.io.DefaultClassicHttpResponseFactory;
import org.apache.hc.core5.http.impl.DefaultHttpResponseFactory;
import org.apache.hc.core5.http.impl.io.DefaultHttpRequestWriterFactory; import org.apache.hc.core5.http.impl.io.DefaultHttpRequestWriterFactory;
import org.apache.hc.core5.http.io.HttpMessageParser; import org.apache.hc.core5.http.io.HttpMessageParser;
import org.apache.hc.core5.http.io.HttpMessageParserFactory; import org.apache.hc.core5.http.io.HttpMessageParserFactory;
import org.apache.hc.core5.http.io.HttpMessageWriterFactory; import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicLineParser; import org.apache.hc.core5.http.message.BasicLineParser;
import org.apache.hc.core5.http.message.LineParser; import org.apache.hc.core5.http.message.LineParser;
@ -92,10 +91,10 @@ public class ClientConfiguration {
// Use custom message parser / writer to customize the way HTTP // Use custom message parser / writer to customize the way HTTP
// messages are parsed from and written out to the data stream. // messages are parsed from and written out to the data stream.
HttpMessageParserFactory<HttpResponse> responseParserFactory = new DefaultHttpResponseParserFactory() { HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory = new DefaultHttpResponseParserFactory() {
@Override @Override
public HttpMessageParser<HttpResponse> create(MessageConstraints constraints) { public HttpMessageParser<ClassicHttpResponse> create(H1Config h1Config) {
LineParser lineParser = new BasicLineParser() { LineParser lineParser = new BasicLineParser() {
@Override @Override
@ -108,18 +107,18 @@ public class ClientConfiguration {
} }
}; };
return new LenientHttpResponseParser(lineParser, DefaultHttpResponseFactory.INSTANCE, constraints); return new LenientHttpResponseParser(lineParser, DefaultClassicHttpResponseFactory.INSTANCE, h1Config);
} }
}; };
HttpMessageWriterFactory<HttpRequest> requestWriterFactory = new DefaultHttpRequestWriterFactory(); HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory = new DefaultHttpRequestWriterFactory();
// Use a custom connection factory to customize the process of // Use a custom connection factory to customize the process of
// initialization of outgoing HTTP connections. Beside standard connection // initialization of outgoing HTTP connections. Beside standard connection
// configuration parameters HTTP connection factory can define message // configuration parameters HTTP connection factory can define message
// parser / writer routines to be employed by individual connections. // parser / writer routines to be employed by individual connections.
HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory( HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory(
requestWriterFactory, responseParserFactory); H1Config.DEFAULT, requestWriterFactory, responseParserFactory);
// Client HTTP connection objects when fully initialized can be bound to // Client HTTP connection objects when fully initialized can be bound to
// an arbitrary network socket. The process of network socket initialization, // an arbitrary network socket. The process of network socket initialization,
@ -167,7 +166,7 @@ public class ClientConfiguration {
connManager.setValidateAfterInactivity(1000); connManager.setValidateAfterInactivity(1000);
// Create message constraints // Create message constraints
MessageConstraints messageConstraints = MessageConstraints.custom() H1Config messageConstraints = H1Config.custom()
.setMaxHeaderCount(200) .setMaxHeaderCount(200)
.setMaxLineLength(2000) .setMaxLineLength(2000)
.build(); .build();
@ -176,7 +175,6 @@ public class ClientConfiguration {
.setMalformedInputAction(CodingErrorAction.IGNORE) .setMalformedInputAction(CodingErrorAction.IGNORE)
.setUnmappableInputAction(CodingErrorAction.IGNORE) .setUnmappableInputAction(CodingErrorAction.IGNORE)
.setCharset(StandardCharsets.UTF_8) .setCharset(StandardCharsets.UTF_8)
.setMessageConstraints(messageConstraints)
.build(); .build();
// Configure the connection manager to use connection configuration either // Configure the connection manager to use connection configuration either
// by default or for a specific host. // by default or for a specific host.
@ -228,12 +226,10 @@ public class ClientConfiguration {
context.setCookieStore(cookieStore); context.setCookieStore(cookieStore);
context.setCredentialsProvider(credentialsProvider); context.setCredentialsProvider(credentialsProvider);
System.out.println("executing request " + httpget.getURI()); System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
try (CloseableHttpResponse response = httpclient.execute(httpget, context)) { try (CloseableHttpResponse response = httpclient.execute(httpget, context)) {
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------"); System.out.println("----------------------------------------");
System.out.println(response.getStatusLine()); System.out.println(response.getCode() + " " + response.getReasonPhrase());
System.out.println(EntityUtils.toString(response.getEntity())); System.out.println(EntityUtils.toString(response.getEntity()));
// Once the request has been executed the local context can // Once the request has been executed the local context can

View File

@ -32,7 +32,7 @@ import java.io.InputStream;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient; import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.sync.HttpClients; import org.apache.hc.client5.http.impl.sync.HttpClients;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.client5.http.impl.sync.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpEntity;
@ -46,10 +46,10 @@ public class ClientConnectionRelease {
try (CloseableHttpClient httpclient = HttpClients.createDefault()) { try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
HttpGet httpget = new HttpGet("http://httpbin.org/get"); HttpGet httpget = new HttpGet("http://httpbin.org/get");
System.out.println("Executing request " + httpget.getRequestLine()); System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
try (CloseableHttpResponse response = httpclient.execute(httpget)) { try (CloseableHttpResponse response = httpclient.execute(httpget)) {
System.out.println("----------------------------------------"); System.out.println("----------------------------------------");
System.out.println(response.getStatusLine()); System.out.println(response.getCode() + " " + response.getReasonPhrase());
// Get hold of the response entity // Get hold of the response entity
HttpEntity entity = response.getEntity(); HttpEntity entity = response.getEntity();

View File

@ -34,10 +34,10 @@ import org.apache.hc.client5.http.cookie.Cookie;
import org.apache.hc.client5.http.cookie.CookieStore; import org.apache.hc.client5.http.cookie.CookieStore;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient; import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.impl.sync.HttpClients; import org.apache.hc.client5.http.impl.sync.HttpClients;
import org.apache.hc.client5.http.methods.CloseableHttpResponse; import org.apache.hc.client5.http.impl.sync.CloseableHttpResponse;
import org.apache.hc.client5.http.methods.HttpGet; import org.apache.hc.client5.http.methods.HttpGet;
import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.EntityUtils;
/** /**
* This example demonstrates the use of a local HTTP context populated with * This example demonstrates the use of a local HTTP context populated with
@ -56,12 +56,12 @@ public class ClientCustomContext {
localContext.setCookieStore(cookieStore); localContext.setCookieStore(cookieStore);
HttpGet httpget = new HttpGet("http://httpbin.org/cookies"); HttpGet httpget = new HttpGet("http://httpbin.org/cookies");
System.out.println("Executing request " + httpget.getRequestLine()); System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
// Pass local context as a parameter // Pass local context as a parameter
try (CloseableHttpResponse response = httpclient.execute(httpget, localContext)) { try (CloseableHttpResponse response = httpclient.execute(httpget, localContext)) {
System.out.println("----------------------------------------"); System.out.println("----------------------------------------");
System.out.println(response.getStatusLine()); System.out.println(response.getCode() + " " + response.getReasonPhrase());
List<Cookie> cookies = cookieStore.getCookies(); List<Cookie> cookies = cookieStore.getCookies();
for (int i = 0; i < cookies.size(); i++) { for (int i = 0; i < cookies.size(); i++) {
System.out.println("Local cookie: " + cookies.get(i)); System.out.println("Local cookie: " + cookies.get(i));

Some files were not shown because too many files have changed in this diff Show More