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:
parent
b85a51b868
commit
e48091da3d
|
@ -7,3 +7,4 @@ bin
|
||||||
target
|
target
|
||||||
.idea
|
.idea
|
||||||
*.iml
|
*.iml
|
||||||
|
/httpclient5/src/test/resources/log4j2-debug.xml
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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 + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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)) {
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue