HttpClientContext and HttpCacheContext to use instance variables for standard attributes

This commit is contained in:
Oleg Kalnichevski 2024-02-22 11:56:56 +01:00
parent 762b18fe69
commit eb6fd6b1c2
42 changed files with 884 additions and 248 deletions

View File

@ -28,10 +28,7 @@ package org.apache.hc.client5.http.cache;
/**
* This enumeration represents the various ways a response can be generated
* by the caching {@link org.apache.hc.client5.http.classic.HttpClient};
* if a request is executed with an {@link HttpCacheContext}
* then a parameter with one of these values will be registered in the
* context under the key {@link HttpCacheContext#CACHE_RESPONSE_STATUS}.
* by an HTTP cache.
*/
public enum CacheResponseStatus {

View File

@ -26,51 +26,103 @@
*/
package org.apache.hc.client5.http.cache;
import java.util.Map;
import javax.net.ssl.SSLSession;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.RouteInfo;
import org.apache.hc.client5.http.auth.AuthCache;
import org.apache.hc.client5.http.auth.AuthExchange;
import org.apache.hc.client5.http.auth.AuthScheme;
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
import org.apache.hc.client5.http.auth.CredentialsProvider;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.CookieOrigin;
import org.apache.hc.client5.http.cookie.CookieSpec;
import org.apache.hc.client5.http.cookie.CookieSpecFactory;
import org.apache.hc.client5.http.cookie.CookieStore;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.protocol.RedirectLocations;
import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.http.EndpointDetails;
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.ProtocolVersion;
import org.apache.hc.core5.http.config.Lookup;
import org.apache.hc.core5.http.protocol.HttpContext;
/**
* Adaptor class that provides convenience type safe setters and getters
* for caching {@link HttpContext} attributes.
* Cache execution {@link HttpContext}. This class can be re-used for
* multiple consecutive logically related request executions that represent
* a single communication session. This context may not be used concurrently.
* <p>
* IMPORTANT: This class is NOT thread-safe and MUST NOT be used concurrently by
* multiple message exchanges.
*
* @since 4.3
*/
public class HttpCacheContext extends HttpClientContext {
/**
* This is the name under which the {@link CacheResponseStatus} of a request
* (for example, whether it resulted in a cache hit) will be recorded if an
* {@link HttpContext} is provided during execution.
* @deprecated Use getter methods
*/
@Deprecated
public static final String CACHE_RESPONSE_STATUS = "http.cache.response.status";
static final String REQUEST_CACHE_CONTROL = "http.cache.request-control";
static final String RESPONSE_CACHE_CONTROL = "http.cache.response-control";
static final String CACHE_ENTRY = "http.cache.entry";
/**
* @since 5.4
* @deprecated Use {@link #castOrCreate(HttpContext)}.
*/
public static final String CACHE_ENTRY = "http.cache.entry";
/**
* @since 5.4
*/
public static final String CACHE_REQUEST_CONTROL = "http.cache.request.control";
/**
* @since 5.4
*/
public static final String CACHE_RESPONSE_CONTROL = "http.cache.response.control";
@Deprecated
public static HttpCacheContext adapt(final HttpContext context) {
if (context instanceof HttpCacheContext) {
return (HttpCacheContext) context;
} else {
return new HttpCacheContext(context);
}
return new Delegate(HttpClientContext.castOrCreate(context));
}
/**
* Casts the given generic {@link HttpContext} as {@link HttpCacheContext} or
* throws an {@link IllegalStateException} if the given context is not suitable.
*
* @since 5.4
*/
public static HttpCacheContext cast(final HttpContext context) {
if (context == null) {
return null;
}
if (context instanceof HttpCacheContext) {
return (HttpCacheContext) context;
} else if (context instanceof HttpClientContext) {
return new Delegate((HttpClientContext) context);
} else {
return new Delegate(HttpClientContext.cast(context));
}
}
/**
* Casts the given generic {@link HttpContext} as {@link HttpCacheContext} or
* creates new {@link HttpCacheContext} if the given context is null..
*
* @since 5.4
*/
public static HttpCacheContext castOrCreate(final HttpContext context) {
return context != null ? cast(context) : create();
}
public static HttpCacheContext create() {
return new HttpCacheContext();
}
private CacheResponseStatus responseStatus;
private RequestCacheControl requestCacheControl;
private ResponseCacheControl responseCacheControl;
private HttpCacheEntry cacheEntry;
public HttpCacheContext(final HttpContext context) {
super(context);
}
@ -79,59 +131,377 @@ public class HttpCacheContext extends HttpClientContext {
super();
}
/**
* Represents an outcome of the cache operation and the way the response has been
* generated.
* <p>
* This context attribute is expected to be populated by the protocol handler.
*/
public CacheResponseStatus getCacheResponseStatus() {
return getAttribute(CACHE_RESPONSE_STATUS, CacheResponseStatus.class);
return responseStatus;
}
/**
* @since 5.4
*/
public void setCacheResponseStatus(final CacheResponseStatus status) {
setAttribute(CACHE_RESPONSE_STATUS, status);
@Internal
public void setCacheResponseStatus(final CacheResponseStatus responseStatus) {
this.responseStatus = responseStatus;
}
/**
* Represents cache control requested by the client.
* <p>
* This context attribute is expected to be set by the caller.
*
* @since 5.4
*/
public RequestCacheControl getRequestCacheControl() {
final RequestCacheControl cacheControl = getAttribute(CACHE_REQUEST_CONTROL, RequestCacheControl.class);
return requestCacheControl;
}
/**
* Returns cache control requested by the client or {@link RequestCacheControl#DEFAULT}
* if not explicitly set in the context.
*
* @since 5.4
*/
public final RequestCacheControl getRequestCacheControlOrDefault() {
final RequestCacheControl cacheControl = getRequestCacheControl();
return cacheControl != null ? cacheControl : RequestCacheControl.DEFAULT;
}
/**
* @since 5.4
*/
@Internal
public void setRequestCacheControl(final RequestCacheControl requestCacheControl) {
setAttribute(CACHE_REQUEST_CONTROL, requestCacheControl);
this.requestCacheControl = requestCacheControl;
}
/**
* Represents cache control enforced by the server.
* <p>
* This context attribute is expected to be populated by the protocol handler.
*
* @since 5.4
*/
public ResponseCacheControl getResponseCacheControl() {
final ResponseCacheControl cacheControl = getAttribute(CACHE_RESPONSE_CONTROL, ResponseCacheControl.class);
return responseCacheControl;
}
/**
* Represents cache control enforced by the server or {@link ResponseCacheControl#DEFAULT}
* if not explicitly set in the context.
*
* @since 5.4
*/
public final ResponseCacheControl getResponseCacheControlOrDefault() {
final ResponseCacheControl cacheControl = getResponseCacheControl();
return cacheControl != null ? cacheControl : ResponseCacheControl.DEFAULT;
}
/**
* @since 5.4
*/
@Internal
public void setResponseCacheControl(final ResponseCacheControl responseCacheControl) {
setAttribute(CACHE_RESPONSE_CONTROL, responseCacheControl);
this.responseCacheControl = responseCacheControl;
}
/**
* Represents the cache entry the resource of which has been used to generate the response.
* <p>
* This context attribute is expected to be populated by the protocol handler.
*
* @since 5.4
*/
public HttpCacheEntry getCacheEntry() {
return getAttribute(CACHE_ENTRY, HttpCacheEntry.class);
return cacheEntry;
}
/**
* @since 5.4
*/
public void setCacheEntry(final HttpCacheEntry entry) {
setAttribute(CACHE_ENTRY, entry);
@Internal
public void setCacheEntry(final HttpCacheEntry cacheEntry) {
this.cacheEntry = cacheEntry;
}
}
/**
* Internal adaptor class that delegates all its method calls to {@link HttpClientContext}.
* To be removed in the future.
*/
@SuppressWarnings("deprecation")
@Internal
static class Delegate extends HttpCacheContext {
private final HttpClientContext clientContext;
Delegate(final HttpClientContext clientContext) {
super(null);
this.clientContext = clientContext;
}
@Override
public CacheResponseStatus getCacheResponseStatus() {
return clientContext.getAttribute(CACHE_RESPONSE_STATUS, CacheResponseStatus.class);
}
@Override
public void setCacheResponseStatus(final CacheResponseStatus responseStatus) {
clientContext.setAttribute(CACHE_RESPONSE_STATUS, responseStatus);
}
@Override
public RequestCacheControl getRequestCacheControl() {
return clientContext.getAttribute(REQUEST_CACHE_CONTROL, RequestCacheControl.class);
}
@Override
public void setRequestCacheControl(final RequestCacheControl requestCacheControl) {
clientContext.setAttribute(REQUEST_CACHE_CONTROL, requestCacheControl);
}
@Override
public ResponseCacheControl getResponseCacheControl() {
return clientContext.getAttribute(RESPONSE_CACHE_CONTROL, ResponseCacheControl.class);
}
@Override
public void setResponseCacheControl(final ResponseCacheControl responseCacheControl) {
clientContext.setAttribute(RESPONSE_CACHE_CONTROL, responseCacheControl);
}
@Override
public HttpCacheEntry getCacheEntry() {
return clientContext.getAttribute(CACHE_ENTRY, HttpCacheEntry.class);
}
@Override
public void setCacheEntry(final HttpCacheEntry cacheEntry) {
clientContext.setAttribute(CACHE_ENTRY, cacheEntry);
}
@Override
public RouteInfo getHttpRoute() {
return clientContext.getHttpRoute();
}
@Override
@Internal
public void setRoute(final HttpRoute route) {
clientContext.setRoute(route);
}
@Override
public RedirectLocations getRedirectLocations() {
return clientContext.getRedirectLocations();
}
@Override
@Internal
public void setRedirectLocations(final RedirectLocations redirectLocations) {
clientContext.setRedirectLocations(redirectLocations);
}
@Override
public CookieStore getCookieStore() {
return clientContext.getCookieStore();
}
@Override
public void setCookieStore(final CookieStore cookieStore) {
clientContext.setCookieStore(cookieStore);
}
@Override
public CookieSpec getCookieSpec() {
return clientContext.getCookieSpec();
}
@Override
@Internal
public void setCookieSpec(final CookieSpec cookieSpec) {
clientContext.setCookieSpec(cookieSpec);
}
@Override
public CookieOrigin getCookieOrigin() {
return clientContext.getCookieOrigin();
}
@Override
@Internal
public void setCookieOrigin(final CookieOrigin cookieOrigin) {
clientContext.setCookieOrigin(cookieOrigin);
}
@Override
public Lookup<CookieSpecFactory> getCookieSpecRegistry() {
return clientContext.getCookieSpecRegistry();
}
@Override
public void setCookieSpecRegistry(final Lookup<CookieSpecFactory> lookup) {
clientContext.setCookieSpecRegistry(lookup);
}
@Override
public Lookup<AuthSchemeFactory> getAuthSchemeRegistry() {
return clientContext.getAuthSchemeRegistry();
}
@Override
public void setAuthSchemeRegistry(final Lookup<AuthSchemeFactory> lookup) {
clientContext.setAuthSchemeRegistry(lookup);
}
@Override
public CredentialsProvider getCredentialsProvider() {
return clientContext.getCredentialsProvider();
}
@Override
public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
clientContext.setCredentialsProvider(credentialsProvider);
}
@Override
public AuthCache getAuthCache() {
return clientContext.getAuthCache();
}
@Override
public void setAuthCache(final AuthCache authCache) {
clientContext.setAuthCache(authCache);
}
@Override
public Map<HttpHost, AuthExchange> getAuthExchanges() {
return clientContext.getAuthExchanges();
}
@Override
public AuthExchange getAuthExchange(final HttpHost host) {
return clientContext.getAuthExchange(host);
}
@Override
public void setAuthExchange(final HttpHost host, final AuthExchange authExchange) {
clientContext.setAuthExchange(host, authExchange);
}
@Override
public void resetAuthExchange(final HttpHost host, final AuthScheme authScheme) {
clientContext.resetAuthExchange(host, authScheme);
}
@Override
public Object getUserToken() {
return clientContext.getUserToken();
}
@Override
public void setUserToken(final Object userToken) {
clientContext.setUserToken(userToken);
}
@Override
public RequestConfig getRequestConfig() {
return clientContext.getRequestConfig();
}
@Override
public void setRequestConfig(final RequestConfig requestConfig) {
clientContext.setRequestConfig(requestConfig);
}
@Override
public String getExchangeId() {
return clientContext.getExchangeId();
}
@Override
public void setExchangeId(final String exchangeId) {
clientContext.setExchangeId(exchangeId);
}
@Override
public HttpRequest getRequest() {
return clientContext.getRequest();
}
@Override
public void setRequest(final HttpRequest request) {
clientContext.setRequest(request);
}
@Override
public HttpResponse getResponse() {
return clientContext.getResponse();
}
@Override
public void setResponse(final HttpResponse response) {
clientContext.setResponse(response);
}
@Override
public EndpointDetails getEndpointDetails() {
return clientContext.getEndpointDetails();
}
@Override
public void setEndpointDetails(final EndpointDetails endpointDetails) {
clientContext.setEndpointDetails(endpointDetails);
}
@Override
public SSLSession getSSLSession() {
return clientContext.getSSLSession();
}
@Override
public void setSSLSession(final SSLSession sslSession) {
clientContext.setSSLSession(sslSession);
}
@Override
public ProtocolVersion getProtocolVersion() {
return clientContext.getProtocolVersion();
}
@Override
public void setProtocolVersion(final ProtocolVersion version) {
clientContext.setProtocolVersion(version);
}
@Override
public Object getAttribute(final String id) {
return clientContext.getAttribute(id);
}
@Override
public Object setAttribute(final String id, final Object obj) {
return clientContext.setAttribute(id, obj);
}
@Override
public Object removeAttribute(final String id) {
return clientContext.removeAttribute(id);
}
@Override
public <T> T getAttribute(final String id, final Class<T> clazz) {
return clientContext.getAttribute(id, clazz);
}
@Override
public String toString() {
return clientContext.toString();
}
}
}

View File

@ -238,18 +238,18 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
final AsyncExecCallback asyncExecCallback) throws HttpException, IOException {
final String exchangeId = scope.exchangeId;
final HttpCacheContext context = HttpCacheContext.adapt(scope.clientContext);
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
final CancellableDependency operation = scope.cancellableDependency;
if (LOG.isDebugEnabled()) {
LOG.debug("{} request via cache: {}", exchangeId, new RequestLine(request));
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MISS);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, null);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MISS);
context.setCacheEntry(null);
if (clientRequestsOurOptions(request)) {
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
triggerResponse(SimpleHttpResponse.create(HttpStatus.SC_NOT_IMPLEMENTED), scope, asyncExecCallback);
return;
}
@ -259,7 +259,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
requestCacheControl = CacheControlHeaderParser.INSTANCE.parse(request);
context.setRequestCacheControl(requestCacheControl);
} else {
requestCacheControl = context.getRequestCacheControl();
requestCacheControl = context.getRequestCacheControlOrDefault();
CacheControlHeaderGenerator.INSTANCE.generate(requestCacheControl, request);
}
@ -549,7 +549,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
void triggerNewCacheEntryResponse(final HttpResponse backendResponse, final Instant responseDate, final ByteArrayBuffer buffer) {
final String exchangeId = scope.exchangeId;
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
final CancellableDependency operation = scope.cancellableDependency;
operation.setDependency(responseCache.store(
target,
@ -567,7 +567,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
}
try {
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, hit.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} catch (final ResourceIOException ex) {
asyncExecCallback.failed(ex);
@ -589,10 +589,10 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
}
void triggerCachedResponse(final HttpCacheEntry entry) {
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
try {
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, entry);
context.setCacheEntry(entry);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} catch (final ResourceIOException ex) {
asyncExecCallback.failed(ex);
@ -722,14 +722,14 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
final AsyncExecChain.Scope scope,
final AsyncExecChain chain,
final AsyncExecCallback asyncExecCallback) {
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
final String exchangeId = scope.exchangeId;
if (LOG.isDebugEnabled()) {
LOG.debug("{} cache hit: {}", exchangeId, new RequestLine(request));
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_HIT);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_HIT);
cacheHits.getAndIncrement();
final Instant now = getCurrentDate();
@ -744,18 +744,18 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
}
try {
final SimpleHttpResponse cacheResponse = generateCachedResponse(request, hit.entry, now);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} catch (final ResourceIOException ex) {
if (requestCacheControl.isOnlyIfCached()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} request marked only-if-cached", exchangeId);
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
final SimpleHttpResponse cacheResponse = generateGatewayTimeout();
triggerResponse(cacheResponse, scope, asyncExecCallback);
} else {
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.FAILURE);
context.setCacheResponseStatus(CacheResponseStatus.FAILURE);
try {
chain.proceed(request, entityProducer, scope, asyncExecCallback);
} catch (final HttpException | IOException ex2) {
@ -768,7 +768,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
if (LOG.isDebugEnabled()) {
LOG.debug("{} cache entry not is not fresh and only-if-cached requested", exchangeId);
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
final SimpleHttpResponse cacheResponse = generateGatewayTimeout();
triggerResponse(cacheResponse, scope, asyncExecCallback);
} else if (cacheSuitability == CacheSuitability.MISMATCH) {
@ -815,9 +815,9 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
hit.getEntryKey(),
asyncExecCallback,
c -> revalidateCacheEntry(responseCacheControl, hit, target, request, entityProducer, fork, chain, c));
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, hit.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} catch (final IOException ex) {
asyncExecCallback.failed(ex);
@ -856,7 +856,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
responseCacheControl,
BasicRequestBuilder.copy(request).build(),
hit.entry);
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
chainProceed(conditionalRequest, entityProducer, scope, chain, new AsyncExecCallback() {
final AtomicReference<AsyncExecCallback> callbackRef = new AtomicReference<>();
@ -876,7 +876,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
public void completed(final CacheHit updated) {
try {
final SimpleHttpResponse cacheResponse = generateCachedResponse(request, updated.entry, responseDate);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} catch (final ResourceIOException ex) {
asyncExecCallback.failed(ex);
@ -899,7 +899,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
AsyncExecCallback evaluateResponse(final HttpResponse backendResponse, final Instant responseDate) {
final int statusCode = backendResponse.getCode();
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.VALIDATED);
context.setCacheResponseStatus(CacheResponseStatus.VALIDATED);
cacheUpdates.getAndIncrement();
}
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
@ -1015,7 +1015,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
final AsyncExecChain chain,
final AsyncExecCallback asyncExecCallback) {
final String exchangeId = scope.exchangeId;
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
revalidateCacheEntry(responseCacheControl, hit, target, request, entityProducer, scope, chain, new AsyncExecCallback() {
private final AtomicBoolean committed = new AtomicBoolean();
@ -1044,7 +1044,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
LOG.debug("{} I/O error while revalidating cache entry", exchangeId, cause);
}
final SimpleHttpResponse cacheResponse = generateGatewayTimeout();
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} else {
asyncExecCallback.failed(cause);
@ -1065,7 +1065,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
final AsyncExecChain chain,
final AsyncExecCallback asyncExecCallback) {
final String exchangeId = scope.exchangeId;
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
revalidateCacheEntry(responseCacheControl, hit, target, request, entityProducer, scope, chain, new AsyncExecCallback() {
private final AtomicReference<HttpResponse> committed = new AtomicReference<>();
@ -1095,9 +1095,9 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
final HttpResponse response = committed.get();
if (response == null) {
try {
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, hit.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} catch (final IOException ex) {
asyncExecCallback.failed(ex);
@ -1114,7 +1114,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
if (LOG.isDebugEnabled()) {
LOG.debug("{} I/O error while revalidating cache entry", exchangeId, cause);
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
if (cause instanceof IOException &&
suitabilityChecker.isSuitableIfError(requestCacheControl, responseCacheControl, hit.entry, getCurrentDate())) {
if (LOG.isDebugEnabled()) {
@ -1122,7 +1122,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
}
try {
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, hit.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} catch (final IOException ex) {
asyncExecCallback.failed(cause);
@ -1159,8 +1159,8 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
if (LOG.isDebugEnabled()) {
LOG.debug("{} request marked only-if-cached", exchangeId);
}
final HttpClientContext context = scope.clientContext;
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
final SimpleHttpResponse cacheResponse = generateGatewayTimeout();
triggerResponse(cacheResponse, scope, asyncExecCallback);
}
@ -1223,8 +1223,8 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
final AtomicReference<AsyncExecCallback> callbackRef = new AtomicReference<>();
void updateVariantCacheEntry(final HttpResponse backendResponse, final Instant responseDate, final CacheHit match) {
final HttpClientContext context = scope.clientContext;
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.VALIDATED);
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
context.setCacheResponseStatus(CacheResponseStatus.VALIDATED);
cacheUpdates.getAndIncrement();
operation.setDependency(responseCache.storeFromNegotiated(
@ -1240,7 +1240,7 @@ class AsyncCachingExec extends CachingExecBase implements AsyncExecChainHandler
public void completed(final CacheHit hit) {
try {
final SimpleHttpResponse cacheResponse = generateCachedResponse(request, hit.entry, responseDate);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
triggerResponse(cacheResponse, scope, asyncExecCallback);
} catch (final ResourceIOException ex) {
asyncExecCallback.failed(ex);

View File

@ -144,17 +144,17 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
final ExecChain.Scope scope,
final ExecChain chain) throws IOException, HttpException {
final String exchangeId = scope.exchangeId;
final HttpCacheContext context = HttpCacheContext.adapt(scope.clientContext);
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
if (LOG.isDebugEnabled()) {
LOG.debug("{} request via cache: {}", exchangeId, new RequestLine(request));
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MISS);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, null);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MISS);
context.setCacheEntry(null);
if (clientRequestsOurOptions(request)) {
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
return new BasicClassicHttpResponse(HttpStatus.SC_NOT_IMPLEMENTED);
}
@ -162,7 +162,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
if (request.containsHeader(HttpHeaders.CACHE_CONTROL)) {
requestCacheControl = CacheControlHeaderParser.INSTANCE.parse(request);
} else {
requestCacheControl = context.getRequestCacheControl();
requestCacheControl = context.getRequestCacheControlOrDefault();
CacheControlHeaderGenerator.INSTANCE.generate(requestCacheControl, request);
}
@ -245,13 +245,13 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
final ExecChain.Scope scope,
final ExecChain chain) throws IOException, HttpException {
final String exchangeId = scope.exchangeId;
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
if (LOG.isDebugEnabled()) {
LOG.debug("{} cache hit: {}", exchangeId, new RequestLine(request));
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_HIT);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_HIT);
cacheHits.getAndIncrement();
final Instant now = getCurrentDate();
@ -266,17 +266,17 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
}
try {
final SimpleHttpResponse cacheResponse = generateCachedResponse(request, hit.entry, now);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
return convert(cacheResponse);
} catch (final ResourceIOException ex) {
if (requestCacheControl.isOnlyIfCached()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} request marked only-if-cached", exchangeId);
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
return convert(generateGatewayTimeout());
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.FAILURE);
context.setCacheResponseStatus(CacheResponseStatus.FAILURE);
return chain.proceed(request, scope);
}
} else {
@ -284,7 +284,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
if (LOG.isDebugEnabled()) {
LOG.debug("{} cache entry not is not fresh and only-if-cached requested", exchangeId);
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
return convert(generateGatewayTimeout());
} else if (cacheSuitability == CacheSuitability.MISMATCH) {
if (LOG.isDebugEnabled()) {
@ -325,9 +325,9 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
cacheRevalidator.revalidateCacheEntry(
hit.getEntryKey(),
() -> revalidateCacheEntry(responseCacheControl, hit, target, request, fork, chain));
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, hit.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
return convert(cacheResponse);
} else {
if (LOG.isDebugEnabled()) {
@ -356,7 +356,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
final ClassicHttpRequest request,
final ExecChain.Scope scope,
final ExecChain chain) throws IOException, HttpException {
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
Instant requestDate = getCurrentDate();
final ClassicHttpRequest conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(
responseCacheControl, request, hit.entry);
@ -376,13 +376,13 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
final int statusCode = backendResponse.getCode();
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.VALIDATED);
context.setCacheResponseStatus(CacheResponseStatus.VALIDATED);
cacheUpdates.getAndIncrement();
}
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
final CacheHit updated = responseCache.update(hit, target, request, backendResponse, requestDate, responseDate);
final SimpleHttpResponse cacheResponse = generateCachedResponse(request, updated.entry, responseDate);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, updated.entry);
context.setCacheEntry(updated.entry);
return convert(cacheResponse);
}
return handleBackendResponse(target, conditionalRequest, scope, requestDate, responseDate, backendResponse);
@ -400,14 +400,14 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
final ExecChain.Scope scope,
final ExecChain chain) throws HttpException {
final String exchangeId = scope.exchangeId;
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
try {
return revalidateCacheEntry(responseCacheControl, hit, target, request, scope, chain);
} catch (final IOException ex) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} I/O error while revalidating cache entry", exchangeId, ex);
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
return convert(generateGatewayTimeout());
}
}
@ -421,7 +421,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
final ExecChain.Scope scope,
final ExecChain chain) throws HttpException, IOException {
final String exchangeId = scope.exchangeId;
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
final ClassicHttpResponse response;
try {
response = revalidateCacheEntry(responseCacheControl, hit, target, request, scope, chain);
@ -429,13 +429,13 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
if (LOG.isDebugEnabled()) {
LOG.debug("{} I/O error while revalidating cache entry", exchangeId, ex);
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
if (suitabilityChecker.isSuitableIfError(requestCacheControl, responseCacheControl, hit.entry, getCurrentDate())) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} serving stale response due to IOException and stale-if-error enabled", exchangeId);
}
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, hit.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
return convert(cacheResponse);
} else {
return convert(generateGatewayTimeout());
@ -448,9 +448,9 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
LOG.debug("{} serving stale response due to {} status and stale-if-error enabled", exchangeId, status);
}
EntityUtils.consume(response.getEntity());
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, hit.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
return convert(cacheResponse);
}
return response;
@ -495,7 +495,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
final Instant requestSent,
final Instant responseReceived) throws IOException {
final String exchangeId = scope.exchangeId;
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
final int statusCode = backendResponse.getCode();
// handle 304 Not Modified responses
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
@ -510,7 +510,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
requestSent,
responseReceived);
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, updated.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
return convert(cacheResponse);
}
}
@ -560,7 +560,7 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
}
}
final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, hit.entry);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
return convert(cacheResponse);
}
@ -578,12 +578,12 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
}
cacheMisses.getAndIncrement();
final HttpClientContext context = scope.clientContext;
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
if (requestCacheControl.isOnlyIfCached()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} request marked only-if-cached", exchangeId);
}
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.CACHE_MODULE_RESPONSE);
context.setCacheResponseStatus(CacheResponseStatus.CACHE_MODULE_RESPONSE);
return convert(generateGatewayTimeout());
}
if (partialMatch != null && partialMatch.entry.hasVariants() && request.getEntity() == null) {
@ -649,13 +649,13 @@ class CachingExec extends CachingExecBase implements ExecChainHandler {
return callBackend(target, unconditional, scope, chain);
}
final HttpClientContext context = scope.clientContext;
context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, CacheResponseStatus.VALIDATED);
final HttpCacheContext context = HttpCacheContext.cast(scope.clientContext);
context.setCacheResponseStatus(CacheResponseStatus.VALIDATED);
cacheUpdates.getAndIncrement();
final CacheHit hit = responseCache.storeFromNegotiated(match, target, request, backendResponse, requestDate, responseDate);
final SimpleHttpResponse cacheResponse = generateCachedResponse(request, hit.entry, responseDate);
context.setAttribute(HttpCacheContext.CACHE_ENTRY, hit.entry);
context.setCacheEntry(hit.entry);
return convert(cacheResponse);
} catch (final IOException | RuntimeException ex) {
backendResponse.close();

View File

@ -29,19 +29,23 @@ package org.apache.hc.client5.http.impl.cache;
import java.io.File;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.function.Function;
import org.apache.hc.client5.http.async.AsyncExecChainHandler;
import org.apache.hc.client5.http.cache.HttpAsyncCacheStorage;
import org.apache.hc.client5.http.cache.HttpAsyncCacheStorageAdaptor;
import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.cache.HttpCacheEntryFactory;
import org.apache.hc.client5.http.cache.HttpCacheStorage;
import org.apache.hc.client5.http.cache.ResourceFactory;
import org.apache.hc.client5.http.impl.ChainElement;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
import org.apache.hc.client5.http.impl.schedule.ImmediateSchedulingStrategy;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.schedule.SchedulingStrategy;
import org.apache.hc.core5.annotation.Experimental;
import org.apache.hc.core5.http.config.NamedElementChain;
import org.apache.hc.core5.http.protocol.HttpContext;
/**
* Builder for {@link org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient}
@ -162,4 +166,9 @@ public class CachingHttpAsyncClientBuilder extends HttpAsyncClientBuilder {
execChainDefinition.addBefore(ChainElement.PROTOCOL.name(), cachingExec, ChainElement.CACHING.name());
}
@Override
protected Function<HttpContext, HttpClientContext> contextAdaptor() {
return HttpCacheContext::castOrCreate;
}
}

View File

@ -29,7 +29,9 @@ package org.apache.hc.client5.http.impl.cache;
import java.io.File;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.function.Function;
import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.cache.HttpCacheEntryFactory;
import org.apache.hc.client5.http.cache.HttpCacheStorage;
import org.apache.hc.client5.http.cache.ResourceFactory;
@ -37,8 +39,10 @@ import org.apache.hc.client5.http.classic.ExecChainHandler;
import org.apache.hc.client5.http.impl.ChainElement;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.schedule.ImmediateSchedulingStrategy;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.schedule.SchedulingStrategy;
import org.apache.hc.core5.http.config.NamedElementChain;
import org.apache.hc.core5.http.protocol.HttpContext;
/**
* Builder for {@link org.apache.hc.client5.http.impl.classic.CloseableHttpClient}
@ -153,4 +157,9 @@ public class CachingHttpClientBuilder extends HttpClientBuilder {
execChainDefinition.addBefore(ChainElement.PROTOCOL.name(), cachingExec, ChainElement.CACHING.name());
}
@Override
protected Function<HttpContext, HttpClientContext> contextAdaptor() {
return HttpCacheContext::castOrCreate;
}
}

View File

@ -87,8 +87,8 @@ public class AsyncClientCacheControl {
public void completed(final SimpleHttpResponse response) {
System.out.println(httpget1 + "->" + new StatusLine(response));
System.out.println("Cache status: " + context.getCacheResponseStatus());
System.out.println("Request cache control: " + context.getRequestCacheControl());
System.out.println("Response cache control: " + context.getResponseCacheControl());
System.out.println("Request cache control: " + context.getRequestCacheControlOrDefault());
System.out.println("Response cache control: " + context.getResponseCacheControlOrDefault());
final HttpCacheEntry cacheEntry = context.getCacheEntry();
if (cacheEntry != null) {
System.out.println("Cache entry resource: " + cacheEntry.getResource());
@ -132,8 +132,8 @@ public class AsyncClientCacheControl {
public void completed(final SimpleHttpResponse response) {
System.out.println(httpget2 + "->" + new StatusLine(response));
System.out.println("Cache status: " + context.getCacheResponseStatus());
System.out.println("Request cache control: " + context.getRequestCacheControl());
System.out.println("Response cache control: " + context.getResponseCacheControl());
System.out.println("Request cache control: " + context.getRequestCacheControlOrDefault());
System.out.println("Response cache control: " + context.getResponseCacheControlOrDefault());
final HttpCacheEntry cacheEntry = context.getCacheEntry();
if (cacheEntry != null) {
System.out.println("Cache entry resource: " + cacheEntry.getResource());
@ -179,8 +179,8 @@ public class AsyncClientCacheControl {
public void completed(final SimpleHttpResponse response) {
System.out.println(httpget3 + "->" + new StatusLine(response));
System.out.println("Cache status: " + context.getCacheResponseStatus());
System.out.println("Request cache control: " + context.getRequestCacheControl());
System.out.println("Response cache control: " + context.getResponseCacheControl());
System.out.println("Request cache control: " + context.getRequestCacheControlOrDefault());
System.out.println("Response cache control: " + context.getResponseCacheControlOrDefault());
final HttpCacheEntry cacheEntry = context.getCacheEntry();
if (cacheEntry != null) {
System.out.println("Cache entry resource: " + cacheEntry.getResource());

View File

@ -74,8 +74,8 @@ public class ClientCacheControl {
System.out.println(httpget1 + "->" + new StatusLine(response));
EntityUtils.consume(response.getEntity());
System.out.println("Cache status: " + context.getCacheResponseStatus());
System.out.println("Request cache control: " + context.getRequestCacheControl());
System.out.println("Response cache control: " + context.getResponseCacheControl());
System.out.println("Request cache control: " + context.getRequestCacheControlOrDefault());
System.out.println("Response cache control: " + context.getResponseCacheControlOrDefault());
final HttpCacheEntry cacheEntry = context.getCacheEntry();
if (cacheEntry != null) {
System.out.println("Cache entry resource: " + cacheEntry.getResource());
@ -102,8 +102,8 @@ public class ClientCacheControl {
System.out.println(httpget2 + "->" + new StatusLine(response));
EntityUtils.consume(response.getEntity());
System.out.println("Cache status: " + context.getCacheResponseStatus());
System.out.println("Request cache control: " + context.getRequestCacheControl());
System.out.println("Response cache control: " + context.getResponseCacheControl());
System.out.println("Request cache control: " + context.getRequestCacheControlOrDefault());
System.out.println("Response cache control: " + context.getResponseCacheControlOrDefault());
final HttpCacheEntry cacheEntry = context.getCacheEntry();
if (cacheEntry != null) {
System.out.println("Cache entry resource: " + cacheEntry.getResource());
@ -132,8 +132,8 @@ public class ClientCacheControl {
System.out.println(httpget3 + "->" + new StatusLine(response));
EntityUtils.consume(response.getEntity());
System.out.println("Cache status: " + context.getCacheResponseStatus());
System.out.println("Request cache control: " + context.getRequestCacheControl());
System.out.println("Response cache control: " + context.getResponseCacheControl());
System.out.println("Request cache control: " + context.getRequestCacheControlOrDefault());
System.out.println("Response cache control: " + context.getResponseCacheControlOrDefault());
final HttpCacheEntry cacheEntry = context.getCacheEntry();
if (cacheEntry != null) {
System.out.println("Cache entry resource: " + cacheEntry.getResource());

View File

@ -29,9 +29,9 @@ package org.apache.hc.client5.http.impl.cache;
import java.io.IOException;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.classic.ExecChain;
import org.apache.hc.client5.http.classic.ExecRuntime;
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;
@ -59,7 +59,7 @@ public class TestProtocolAllowedBehavior {
HttpHost host;
HttpRoute route;
HttpClientContext context;
HttpCacheContext context;
@Mock
ExecChain mockExecChain;
@Mock
@ -81,7 +81,7 @@ public class TestProtocolAllowedBehavior {
request = new BasicClassicHttpRequest("GET", "/foo");
context = HttpClientContext.create();
context = HttpCacheContext.create();
originResponse = HttpTestUtils.make200Response();

View File

@ -38,9 +38,9 @@ import java.util.Iterator;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.auth.StandardAuthScheme;
import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.classic.ExecChain;
import org.apache.hc.client5.http.classic.ExecRuntime;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
@ -77,7 +77,7 @@ public class TestProtocolRecommendations {
HttpHost host;
HttpRoute route;
HttpEntity body;
HttpClientContext context;
HttpCacheContext context;
@Mock
ExecChain mockExecChain;
@Mock
@ -102,7 +102,7 @@ public class TestProtocolRecommendations {
request = new BasicClassicHttpRequest("GET", "/foo");
context = HttpClientContext.create();
context = HttpCacheContext.create();
originResponse = HttpTestUtils.make200Response();

View File

@ -39,10 +39,10 @@ import java.util.Random;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.auth.StandardAuthScheme;
import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.classic.ExecChain;
import org.apache.hc.client5.http.classic.ExecRuntime;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
@ -81,7 +81,7 @@ public class TestProtocolRequirements {
HttpHost host;
HttpRoute route;
HttpEntity body;
HttpClientContext context;
HttpCacheContext context;
@Mock
ExecChain mockExecChain;
@Mock
@ -105,7 +105,7 @@ public class TestProtocolRequirements {
request = new BasicClassicHttpRequest("GET", "/");
context = HttpClientContext.create();
context = HttpCacheContext.create();
originResponse = HttpTestUtils.make200Response();

View File

@ -37,9 +37,9 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.cache.HttpCacheContext;
import org.apache.hc.client5.http.classic.ExecChain;
import org.apache.hc.client5.http.classic.ExecRuntime;
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.HttpEntity;
@ -70,7 +70,7 @@ public class TestRFC5861Compliance {
HttpHost host;
HttpRoute route;
HttpEntity body;
HttpClientContext context;
HttpCacheContext context;
@Mock
ExecChain mockExecChain;
@Mock
@ -94,7 +94,7 @@ public class TestRFC5861Compliance {
request = new BasicClassicHttpRequest("GET", "/foo");
context = HttpClientContext.create();
context = HttpCacheContext.create();
originResponse = HttpTestUtils.make200Response();

View File

@ -206,7 +206,7 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes
connManager.setDefaultMaxPerRoute(maxConn);
// Bottom of the pool : a *keep alive* connection to Route 1.
final HttpContext context1 = new HttpClientContext();
final HttpContext context1 = HttpClientContext.create();
context1.setAttribute("user", "stuff");
final SimpleHttpRequest request1 = SimpleRequestBuilder.get()
@ -226,7 +226,7 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes
// Send a very simple HTTP get (it MUST be simple, no auth, no proxy, no 302, no 401, ...)
// Send it to another route. Must be a keepalive.
final HttpContext context2 = new HttpClientContext();
final HttpContext context2 = HttpClientContext.create();
final SimpleHttpRequest request2 = SimpleRequestBuilder.get()
.setScheme(target.getSchemeName())
@ -249,7 +249,7 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes
// So the ConnPoolByRoute will need to kill one connection (it is maxed out globally).
// The killed conn is the oldest, which means the first HTTPGet ([localhost][stuff]).
// When this happens, the RouteSpecificPool becomes empty.
final HttpContext context3 = new HttpClientContext();
final HttpContext context3 = HttpClientContext.create();
final SimpleHttpRequest request3 = SimpleRequestBuilder.get()
.setHttpHost(target)

View File

@ -128,7 +128,7 @@ public class TestConnectionManagement {
final String uri = "/random/" + rsplen;
final ClassicHttpRequest request = new BasicClassicHttpRequest("GET", target, uri);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final LeaseRequest leaseRequest1 = connManager.lease("id1", route, null);
final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS);
@ -192,7 +192,7 @@ public class TestConnectionManagement {
final String uri = "/random/" + rsplen;
final ClassicHttpRequest request = new BasicClassicHttpRequest("GET", target, uri);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final LeaseRequest leaseRequest1 = connManager.lease("id1", route, null);
final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS);
@ -258,7 +258,7 @@ public class TestConnectionManagement {
connManager.setMaxTotal(1);
final HttpRoute route = new HttpRoute(target, null, false);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final LeaseRequest leaseRequest1 = connManager.lease("id1", route, null);
final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS);
@ -311,7 +311,7 @@ public class TestConnectionManagement {
connManager.setMaxTotal(1);
final HttpRoute route = new HttpRoute(target, null, false);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final LeaseRequest leaseRequest1 = connManager.lease("id1", route, null);
final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS);

View File

@ -104,7 +104,7 @@ public class TestDefaultClientTlsStrategy {
// @formatter:on
this.server.start();
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final TestX509HostnameVerifier hostVerifier = new TestX509HostnameVerifier();
final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy(
SSLTestContexts.createClientSSLContext(), hostVerifier);
@ -133,7 +133,7 @@ public class TestDefaultClientTlsStrategy {
// @formatter:on
this.server.start();
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext());
final HttpHost target = new HttpHost("https", "localhost", server.getLocalPort());
try (final Socket socket = new Socket(target.getHostName(), target.getPort())) {
@ -159,7 +159,7 @@ public class TestDefaultClientTlsStrategy {
// @formatter:on
this.server.start();
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final TestX509HostnameVerifier hostVerifier = new TestX509HostnameVerifier();
final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy(
SSLTestContexts.createClientSSLContext(), hostVerifier);
@ -189,7 +189,7 @@ public class TestDefaultClientTlsStrategy {
// @formatter:on
this.server.start();
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final TestX509HostnameVerifier hostVerifier = new TestX509HostnameVerifier();
final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy(
SSLTestContexts.createClientSSLContext(), hostVerifier);
@ -221,7 +221,7 @@ public class TestDefaultClientTlsStrategy {
// @formatter:on
this.server.start();
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
// Use default SSL context
final SSLContext defaultSslContext = SSLContexts.createDefault();
@ -254,7 +254,7 @@ public class TestDefaultClientTlsStrategy {
// @formatter:on
this.server.start();
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
// @formatter:off
final SSLContext sslContext = SSLContexts.custom()
@ -287,7 +287,7 @@ public class TestDefaultClientTlsStrategy {
// @formatter:on
this.server.start();
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy(
SSLTestContexts.createClientSSLContext());
final HttpHost target = new HttpHost("https", "localhost", server.getLocalPort());
@ -339,7 +339,7 @@ public class TestDefaultClientTlsStrategy {
// @formatter:on
this.server.start();
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy(
SSLTestContexts.createClientSSLContext());
final HttpHost target = new HttpHost("https", "localhost", server.getLocalPort());
@ -369,7 +369,7 @@ public class TestDefaultClientTlsStrategy {
SSLTestContexts.createClientSSLContext(),
HostnameVerificationPolicy.CLIENT,
HttpsSupport.getDefaultHostnameVerifier());
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final SSLSocket upgradedSocket = tlsStrategy.upgrade(
socket,
target1.getHostName(),
@ -387,7 +387,7 @@ public class TestDefaultClientTlsStrategy {
SSLTestContexts.createClientSSLContext(),
HostnameVerificationPolicy.CLIENT,
HttpsSupport.getDefaultHostnameVerifier());
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
Assertions.assertThrows(SSLPeerUnverifiedException.class, () ->
tlsStrategy.upgrade(
socket,
@ -402,7 +402,7 @@ public class TestDefaultClientTlsStrategy {
SSLTestContexts.createClientSSLContext(),
HostnameVerificationPolicy.CLIENT,
NoopHostnameVerifier.INSTANCE);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final SSLSocket upgradedSocket = tlsStrategy.upgrade(
socket,
target1.getHostName(),
@ -430,7 +430,7 @@ public class TestDefaultClientTlsStrategy {
SSLTestContexts.createClientSSLContext(),
HostnameVerificationPolicy.BUILTIN,
NoopHostnameVerifier.INSTANCE);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final SSLSocket upgradedSocket = tlsStrategy.upgrade(
socket,
target1.getHostName(),
@ -448,7 +448,7 @@ public class TestDefaultClientTlsStrategy {
SSLTestContexts.createClientSSLContext(),
HostnameVerificationPolicy.BUILTIN,
NoopHostnameVerifier.INSTANCE);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
Assertions.assertThrows(SSLHandshakeException.class, () ->
tlsStrategy.upgrade(
socket,

View File

@ -216,7 +216,7 @@ public class TestStatefulConnManagement {
);
// Bottom of the pool : a *keep alive* connection to Route 1.
final HttpContext context1 = new HttpClientContext();
final HttpContext context1 = HttpClientContext.create();
context1.setAttribute("user", "stuff");
client.execute(target, new HttpGet("/"), context1, response -> {
EntityUtils.consume(response.getEntity());
@ -231,7 +231,7 @@ public class TestStatefulConnManagement {
// Send a very simple HTTP get (it MUST be simple, no auth, no proxy, no 302, no 401, ...)
// Send it to another route. Must be a keepalive.
final HttpContext context2 = new HttpClientContext();
final HttpContext context2 = HttpClientContext.create();
client.execute(new HttpHost("127.0.0.1", server.getPort()), new HttpGet("/"), context2, response -> {
EntityUtils.consume(response.getEntity());
return null;
@ -247,7 +247,7 @@ public class TestStatefulConnManagement {
// So the ConnPoolByRoute will need to kill one connection (it is maxed out globally).
// The killed conn is the oldest, which means the first HTTPGet ([localhost][stuff]).
// When this happens, the RouteSpecificPool becomes empty.
final HttpContext context3 = new HttpClientContext();
final HttpContext context3 = HttpClientContext.create();
client.execute(target, new HttpGet("/"), context3, response -> {
EntityUtils.consume(response.getEntity());
return null;

View File

@ -36,6 +36,7 @@ import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ThreadFactory;
import java.util.function.Function;
import org.apache.hc.client5.http.AuthenticationStrategy;
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
@ -72,6 +73,7 @@ import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner;
import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner;
import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.protocol.RedirectStrategy;
import org.apache.hc.client5.http.protocol.RequestAddCookies;
import org.apache.hc.client5.http.protocol.RequestDefaultHeaders;
@ -96,6 +98,7 @@ import org.apache.hc.core5.http.config.NamedElementChain;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.nio.command.ShutdownCommand;
import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpProcessor;
import org.apache.hc.core5.http.protocol.HttpProcessorBuilder;
import org.apache.hc.core5.http.protocol.RequestTargetHost;
@ -777,6 +780,12 @@ public class HttpAsyncClientBuilder {
}
closeables.add(closeable);
}
@Internal
protected Function<HttpContext, HttpClientContext> contextAdaptor() {
return HttpClientContext::castOrCreate;
}
@SuppressWarnings("deprecated")
public CloseableHttpAsyncClient build() {
AsyncClientConnectionManager connManagerCopy = this.connManager;
@ -1047,6 +1056,7 @@ public class HttpAsyncClientBuilder {
authSchemeRegistryCopy,
cookieStoreCopy,
credentialsProviderCopy,
contextAdaptor(),
defaultRequestConfig,
closeablesCopy);
}

View File

@ -38,6 +38,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.async.AsyncExecCallback;
@ -90,6 +91,7 @@ abstract class InternalAbstractHttpAsyncClient extends AbstractHttpAsyncClientBa
private final Lookup<AuthSchemeFactory> authSchemeRegistry;
private final CookieStore cookieStore;
private final CredentialsProvider credentialsProvider;
private final Function<HttpContext, HttpClientContext> contextAdaptor;
private final RequestConfig defaultConfig;
private final ConcurrentLinkedQueue<Closeable> closeables;
private final ScheduledExecutorService scheduledExecutorService;
@ -104,6 +106,7 @@ abstract class InternalAbstractHttpAsyncClient extends AbstractHttpAsyncClientBa
final Lookup<AuthSchemeFactory> authSchemeRegistry,
final CookieStore cookieStore,
final CredentialsProvider credentialsProvider,
final Function<HttpContext, HttpClientContext> contextAdaptor,
final RequestConfig defaultConfig,
final List<Closeable> closeables) {
super(ioReactor, pushConsumerRegistry, threadFactory);
@ -112,6 +115,7 @@ abstract class InternalAbstractHttpAsyncClient extends AbstractHttpAsyncClientBa
this.authSchemeRegistry = authSchemeRegistry;
this.cookieStore = cookieStore;
this.credentialsProvider = credentialsProvider;
this.contextAdaptor = contextAdaptor;
this.defaultConfig = defaultConfig;
this.closeables = closeables != null ? new ConcurrentLinkedQueue<>(closeables) : null;
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(SCHEDULER_THREAD_FACTORY);
@ -200,7 +204,7 @@ abstract class InternalAbstractHttpAsyncClient extends AbstractHttpAsyncClientBa
if (!isRunning()) {
throw new CancellationException("Request execution cancelled");
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final HttpClientContext clientContext = contextAdaptor.apply(context);
requestProducer.sendRequest((request, entityDetails, c) -> {
RequestConfig requestConfig = null;

View File

@ -84,7 +84,8 @@ public final class InternalH2AsyncClient extends InternalAbstractHttpAsyncClient
final RequestConfig defaultConfig,
final List<Closeable> closeables) {
super(ioReactor, pushConsumerRegistry, threadFactory, execChain,
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider, defaultConfig, closeables);
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider, HttpClientContext::castOrCreate,
defaultConfig, closeables);
this.connPool = connPool;
this.routePlanner = routePlanner;
}

View File

@ -29,6 +29,7 @@ package org.apache.hc.client5.http.impl.async;
import java.io.Closeable;
import java.util.List;
import java.util.concurrent.ThreadFactory;
import java.util.function.Function;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.async.AsyncExecRuntime;
@ -50,6 +51,7 @@ import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.config.Lookup;
import org.apache.hc.core5.http.nio.AsyncPushConsumer;
import org.apache.hc.core5.http.nio.HandlerFactory;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.reactor.DefaultConnectingIOReactor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -86,10 +88,12 @@ public final class InternalHttpAsyncClient extends InternalAbstractHttpAsyncClie
final Lookup<AuthSchemeFactory> authSchemeRegistry,
final CookieStore cookieStore,
final CredentialsProvider credentialsProvider,
final Function<HttpContext, HttpClientContext> contextAdaptor,
final RequestConfig defaultConfig,
final List<Closeable> closeables) {
super(ioReactor, pushConsumerRegistry, threadFactory, execChain,
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider, defaultConfig, closeables);
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider, contextAdaptor,
defaultConfig, closeables);
this.manager = manager;
this.routePlanner = routePlanner;
this.tlsConfig = tlsConfig;

View File

@ -129,7 +129,7 @@ public final class MinimalH2AsyncClient extends AbstractMinimalHttpAsyncClientBa
if (!isRunning()) {
throw new CancellationException("Request execution cancelled");
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final HttpClientContext clientContext = HttpClientContext.castOrCreate(context);
exchangeHandler.produceRequest((request, entityDetails, context1) -> {
RequestConfig requestConfig = null;
if (request instanceof Configurable) {

View File

@ -218,7 +218,7 @@ public final class MinimalHttpAsyncClient extends AbstractMinimalHttpAsyncClient
future.failed(new CancellationException("Connection lease cancelled"));
return future;
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final HttpClientContext clientContext = HttpClientContext.castOrCreate(context);
final RequestConfig requestConfig = clientContext.getRequestConfigOrDefault();
final Timeout connectionRequestTimeout = requestConfig.getConnectionRequestTimeout();
@SuppressWarnings("deprecation")
@ -259,7 +259,7 @@ public final class MinimalHttpAsyncClient extends AbstractMinimalHttpAsyncClient
if (!isRunning()) {
throw new CancellationException("Request execution cancelled");
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final HttpClientContext clientContext = HttpClientContext.castOrCreate(context);
exchangeHandler.produceRequest((request, entityDetails, context1) -> {
RequestConfig requestConfig = null;
if (request instanceof Configurable) {
@ -455,7 +455,7 @@ public final class MinimalHttpAsyncClient extends AbstractMinimalHttpAsyncClient
final HttpContext context) {
Asserts.check(!released.get(), "Endpoint has already been released");
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final HttpClientContext clientContext = HttpClientContext.castOrCreate(context);
final String exchangeId = ExecSupport.getNextExchangeId();
clientContext.setExchangeId(exchangeId);
if (LOG.isDebugEnabled()) {

View File

@ -37,6 +37,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.apache.hc.client5.http.AuthenticationStrategy;
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
@ -75,6 +76,7 @@ import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner;
import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.protocol.RedirectStrategy;
import org.apache.hc.client5.http.protocol.RequestAddCookies;
import org.apache.hc.client5.http.protocol.RequestClientConnControl;
@ -96,6 +98,7 @@ import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.impl.io.HttpRequestExecutor;
import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpProcessor;
import org.apache.hc.core5.http.protocol.HttpProcessorBuilder;
import org.apache.hc.core5.http.protocol.RequestContent;
@ -742,6 +745,11 @@ public class HttpClientBuilder {
closeables.add(closeable);
}
@Internal
protected Function<HttpContext, HttpClientContext> contextAdaptor() {
return HttpClientContext::castOrCreate;
}
public CloseableHttpClient build() {
// Create main request executor
// We copy the instance fields to avoid changing them, and rename to avoid accidental use of the wrong version
@ -1024,6 +1032,7 @@ public class HttpClientBuilder {
authSchemeRegistryCopy,
defaultCookieStore,
defaultCredentialsProvider,
contextAdaptor(),
defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT,
closeablesCopy);
}

View File

@ -31,6 +31,7 @@ import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Function;
import org.apache.hc.client5.http.ClientProtocolException;
import org.apache.hc.client5.http.HttpRoute;
@ -89,6 +90,7 @@ class InternalHttpClient extends CloseableHttpClient implements Configurable {
private final Lookup<AuthSchemeFactory> authSchemeRegistry;
private final CookieStore cookieStore;
private final CredentialsProvider credentialsProvider;
private final Function<HttpContext, HttpClientContext> contextAdaptor;
private final RequestConfig defaultConfig;
private final ConcurrentLinkedQueue<Closeable> closeables;
@ -101,6 +103,7 @@ class InternalHttpClient extends CloseableHttpClient implements Configurable {
final Lookup<AuthSchemeFactory> authSchemeRegistry,
final CookieStore cookieStore,
final CredentialsProvider credentialsProvider,
final Function<HttpContext, HttpClientContext> contextAdaptor,
final RequestConfig defaultConfig,
final List<Closeable> closeables) {
super();
@ -112,6 +115,7 @@ class InternalHttpClient extends CloseableHttpClient implements Configurable {
this.authSchemeRegistry = authSchemeRegistry;
this.cookieStore = cookieStore;
this.credentialsProvider = credentialsProvider;
this.contextAdaptor = contextAdaptor;
this.defaultConfig = defaultConfig;
this.closeables = closeables != null ? new ConcurrentLinkedQueue<>(closeables) : null;
}
@ -145,7 +149,7 @@ class InternalHttpClient extends CloseableHttpClient implements Configurable {
final HttpContext context) throws IOException {
Args.notNull(request, "HTTP request");
try {
final HttpClientContext localcontext = HttpClientContext.adapt(context);
final HttpClientContext localcontext = contextAdaptor.apply(context);
RequestConfig config = null;
if (request instanceof Configurable) {
config = ((Configurable) request).getConfig();

View File

@ -118,7 +118,7 @@ public class MinimalHttpClient extends CloseableHttpClient {
if (request.getAuthority() == null) {
request.setAuthority(new URIAuthority(target));
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final HttpClientContext clientContext = HttpClientContext.castOrCreate(context);
RequestConfig config = null;
if (request instanceof Configurable) {
config = ((Configurable) request).getConfig();

View File

@ -55,9 +55,12 @@ import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
/**
* Adaptor class that provides convenience type safe setters and getters
* for common {@link HttpContext} attributes used in the course
* of HTTP request execution.
* Client execution {@link HttpContext}. This class can be re-used for
* multiple consecutive logically related request executions that represent
* a single communication session. This context may not be used concurrently.
* <p>
* IMPORTANT: This class is NOT thread-safe and MUST NOT be used concurrently by
* multiple message exchanges.
*
* @since 4.3
*/
@ -141,18 +144,23 @@ public class HttpClientContext extends HttpCoreContext {
@Deprecated
public static final String EXCHANGE_ID = "http.exchange-id";
@SuppressWarnings("deprecation")
/**
* @deprecated Use {@link #castOrCreate(HttpContext)}.
*/
@Deprecated
public static HttpClientContext adapt(final HttpContext context) {
if (context == null) {
return new HttpClientContext();
}
if (context instanceof HttpClientContext) {
return (HttpClientContext) context;
}
return new HttpClientContext.Delegate(HttpCoreContext.adapt(context));
return new HttpClientContext(context);
}
/**
* Casts the given generic {@link HttpContext} as {@link HttpClientContext}
* or creates a new {@link HttpClientContext} with the given {@link HttpContext}
* as a parent.
* Casts the given generic {@link HttpContext} as {@link HttpClientContext} or
* throws an {@link IllegalStateException} if the given context is not suitable.
*
* @since 5.4
*/
@ -163,11 +171,20 @@ public class HttpClientContext extends HttpCoreContext {
if (context instanceof HttpClientContext) {
return (HttpClientContext) context;
} else {
throw new IllegalStateException("Unexpected context type: " + context.getClass().getSimpleName() +
"; required context type: " + HttpClientContext.class.getSimpleName());
return new Delegate(context);
}
}
/**
* Casts the given generic {@link HttpContext} as {@link HttpClientContext} or
* creates new {@link HttpClientContext} if the given context is null..
*
* @since 5.4
*/
public static HttpClientContext castOrCreate(final HttpContext context) {
return context != null ? cast(context) : create();
}
public static HttpClientContext create() {
return new HttpClientContext();
}
@ -198,8 +215,7 @@ public class HttpClientContext extends HttpCoreContext {
/**
* Represents current route used to execute message exchanges.
* <p>
* This context attribute is expected to be populated by the protocol handler
* in the course of request execution.
* This context attribute is expected to be populated by the protocol handler.
*/
public RouteInfo getHttpRoute() {
return route;
@ -214,10 +230,9 @@ public class HttpClientContext extends HttpCoreContext {
}
/**
* Represents a collection of all redirects executed in the course of request execution.
* Represents a collection of all redirects executed in the context of request execution.
* <p>
* This context attribute is expected to be populated by the protocol handler
* in the course of request execution.
* This context attribute is expected to be populated by the protocol handler.
*/
public RedirectLocations getRedirectLocations() {
if (this.redirectLocations == null) {
@ -234,6 +249,11 @@ public class HttpClientContext extends HttpCoreContext {
this.redirectLocations = redirectLocations;
}
/**
* Represents a {@link CookieStore} used in the context of the request execution.
* <p>
* This context attribute can be set by the caller.
*/
public CookieStore getCookieStore() {
return cookieStore;
}
@ -242,6 +262,11 @@ public class HttpClientContext extends HttpCoreContext {
this.cookieStore = cookieStore;
}
/**
* Represents a {@link CookieSpec} chosen in the context of request execution.
* <p>
* This context attribute is expected to be populated by the protocol handler.
*/
public CookieSpec getCookieSpec() {
return cookieSpec;
}
@ -254,6 +279,11 @@ public class HttpClientContext extends HttpCoreContext {
this.cookieSpec = cookieSpec;
}
/**
* Represents a {@link CookieOrigin} produced in the context of request execution.
* <p>
* This context attribute is expected to be populated by the protocol handler.
*/
public CookieOrigin getCookieOrigin() {
return cookieOrigin;
}
@ -266,6 +296,11 @@ public class HttpClientContext extends HttpCoreContext {
this.cookieOrigin = cookieOrigin;
}
/**
* Represents a {@link CookieSpecFactory} registry used in the context of the request execution.
* <p>
* This context attribute can be set by the caller.
*/
public Lookup<CookieSpecFactory> getCookieSpecRegistry() {
return cookieSpecFactoryLookup;
}
@ -274,6 +309,11 @@ public class HttpClientContext extends HttpCoreContext {
this.cookieSpecFactoryLookup = lookup;
}
/**
* Represents a {@link AuthSchemeFactory} registry used in the context of the request execution.
* <p>
* This context attribute can be set by the caller.
*/
public Lookup<AuthSchemeFactory> getAuthSchemeRegistry() {
return authSchemeFactoryLookup;
}
@ -282,6 +322,11 @@ public class HttpClientContext extends HttpCoreContext {
this.authSchemeFactoryLookup = lookup;
}
/**
* Represents a {@link CredentialsProvider} registry used in the context of the request execution.
* <p>
* This context attribute can be set by the caller.
*/
public CredentialsProvider getCredentialsProvider() {
return credentialsProvider;
}
@ -290,6 +335,11 @@ public class HttpClientContext extends HttpCoreContext {
this.credentialsProvider = credentialsProvider;
}
/**
* Represents a {@link AuthCache} used in the context of the request execution.
* <p>
* This context attribute can be set by the caller.
*/
public AuthCache getAuthCache() {
return authCache;
}
@ -299,6 +349,11 @@ public class HttpClientContext extends HttpCoreContext {
}
/**
* Represents a map of {@link AuthExchange}s performed in the context of the request
* execution.
* <p>
* This context attribute is expected to be populated by the protocol handler.
*
* @since 5.0
*/
public Map<HttpHost, AuthExchange> getAuthExchanges() {
@ -340,6 +395,12 @@ public class HttpClientContext extends HttpCoreContext {
return (T) getUserToken();
}
/**
* Represents an arbitrary user token that identifies the user in the context
* of the request execution.
* <p>
* This context attribute can be set by the caller.
*/
public Object getUserToken() {
return userToken;
}
@ -348,13 +409,18 @@ public class HttpClientContext extends HttpCoreContext {
this.userToken = userToken;
}
/**
* Represents an {@link RequestConfig used} in the context of the request execution.
* <p>
* This context attribute can be set by the caller.
*/
public RequestConfig getRequestConfig() {
return requestConfig;
}
/**
* Returns {@link RequestConfig} set in the context or {@link RequestConfig#DEFAULT}
* if not present in the context.
* if not explicitly set in the context.
*
* @since 5.4
*/
@ -368,6 +434,10 @@ public class HttpClientContext extends HttpCoreContext {
}
/**
* Represents an identifier generated for the current message exchange executed
* in the given context.
* <p>
* This context attribute is expected to be populated by the protocol handler.
* @since 5.1
*/
public String getExchangeId() {
@ -381,88 +451,237 @@ public class HttpClientContext extends HttpCoreContext {
this.exchangeId = exchangeId;
}
/**
* Internal adaptor class that delegates all its method calls to a plain {@link HttpContext}.
* To be removed in the future.
*/
@SuppressWarnings("deprecation")
@Internal
static class Delegate extends HttpClientContext {
final private HttpCoreContext parent;
private final HttpContext httpContext;
Delegate(final HttpCoreContext parent) {
super(parent);
this.parent = parent;
Delegate(final HttpContext httpContext) {
super(null);
this.httpContext = httpContext;
}
<T> T getAttr(final String id, final Class<T> clazz) {
final Object obj = httpContext.getAttribute(id);
if (obj == null) {
return null;
}
return clazz.cast(obj);
}
@Override
public ProtocolVersion getProtocolVersion() {
return parent.getProtocolVersion();
public RouteInfo getHttpRoute() {
return getAttr(HTTP_ROUTE, RouteInfo.class);
}
@Override
public void setProtocolVersion(final ProtocolVersion version) {
parent.setProtocolVersion(version);
public void setRoute(final HttpRoute route) {
httpContext.setAttribute(HTTP_ROUTE, route);
}
@Override
public Object getAttribute(final String id) {
return parent.getAttribute(id);
public RedirectLocations getRedirectLocations() {
RedirectLocations redirectLocations = getAttr(REDIRECT_LOCATIONS, RedirectLocations.class);
if (redirectLocations == null) {
redirectLocations = new RedirectLocations();
httpContext.setAttribute(REDIRECT_LOCATIONS, redirectLocations);
}
return redirectLocations;
}
@Override
public Object setAttribute(final String id, final Object obj) {
return parent.setAttribute(id, obj);
public void setRedirectLocations(final RedirectLocations redirectLocations) {
httpContext.setAttribute(REDIRECT_LOCATIONS, redirectLocations);
}
@Override
public Object removeAttribute(final String id) {
return parent.removeAttribute(id);
public CookieStore getCookieStore() {
return getAttr(COOKIE_STORE, CookieStore.class);
}
@Override
public <T> T getAttribute(final String id, final Class<T> clazz) {
return parent.getAttribute(id, clazz);
public void setCookieStore(final CookieStore cookieStore) {
httpContext.setAttribute(COOKIE_STORE, cookieStore);
}
@Override
public CookieSpec getCookieSpec() {
return getAttr(COOKIE_SPEC, CookieSpec.class);
}
@Override
public void setCookieSpec(final CookieSpec cookieSpec) {
httpContext.setAttribute(COOKIE_SPEC, cookieSpec);
}
@Override
public CookieOrigin getCookieOrigin() {
return getAttr(COOKIE_ORIGIN, CookieOrigin.class);
}
@Override
public void setCookieOrigin(final CookieOrigin cookieOrigin) {
httpContext.setAttribute(COOKIE_ORIGIN, cookieOrigin);
}
@Override
public Lookup<CookieSpecFactory> getCookieSpecRegistry() {
return getAttr(COOKIESPEC_REGISTRY, Lookup.class);
}
@Override
public void setCookieSpecRegistry(final Lookup<CookieSpecFactory> lookup) {
httpContext.setAttribute(COOKIESPEC_REGISTRY, lookup);
}
@Override
public Lookup<AuthSchemeFactory> getAuthSchemeRegistry() {
return getAttr(AUTHSCHEME_REGISTRY, Lookup.class);
}
@Override
public void setAuthSchemeRegistry(final Lookup<AuthSchemeFactory> lookup) {
httpContext.setAttribute(AUTHSCHEME_REGISTRY, lookup);
}
@Override
public CredentialsProvider getCredentialsProvider() {
return getAttr(CREDS_PROVIDER, CredentialsProvider.class);
}
@Override
public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
httpContext.setAttribute(CREDS_PROVIDER, credentialsProvider);
}
@Override
public AuthCache getAuthCache() {
return getAttr(AUTH_CACHE, AuthCache.class);
}
@Override
public void setAuthCache(final AuthCache authCache) {
httpContext.setAttribute(AUTH_CACHE, authCache);
}
@Override
public Map<HttpHost, AuthExchange> getAuthExchanges() {
Map<HttpHost, AuthExchange> map = getAttr(AUTH_EXCHANGE_MAP, Map.class);
if (map == null) {
map = new HashMap<>();
httpContext.setAttribute(AUTH_EXCHANGE_MAP, map);
}
return map;
}
@Override
public Object getUserToken() {
return httpContext.getAttribute(USER_TOKEN);
}
@Override
public void setUserToken(final Object userToken) {
httpContext.setAttribute(USER_TOKEN, userToken);
}
@Override
public RequestConfig getRequestConfig() {
return getAttr(REQUEST_CONFIG, RequestConfig.class);
}
@Override
public void setRequestConfig(final RequestConfig requestConfig) {
httpContext.setAttribute(REQUEST_CONFIG, requestConfig);
}
@Override
public String getExchangeId() {
return getAttr(EXCHANGE_ID, String.class);
}
@Override
public void setExchangeId(final String exchangeId) {
httpContext.setAttribute(EXCHANGE_ID, exchangeId);
}
@Override
public HttpRequest getRequest() {
return parent.getRequest();
return getAttr(HttpCoreContext.HTTP_REQUEST, HttpRequest.class);
}
@Override
public void setRequest(final HttpRequest request) {
parent.setRequest(request);
httpContext.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
}
@Override
public HttpResponse getResponse() {
return parent.getResponse();
return getAttr(HttpCoreContext.HTTP_RESPONSE, HttpResponse.class);
}
@Override
public void setResponse(final HttpResponse response) {
parent.setResponse(response);
httpContext.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
}
@Override
public EndpointDetails getEndpointDetails() {
return parent.getEndpointDetails();
return getAttr(HttpCoreContext.CONNECTION_ENDPOINT, EndpointDetails.class);
}
@Override
public void setEndpointDetails(final EndpointDetails endpointDetails) {
parent.setEndpointDetails(endpointDetails);
httpContext.setAttribute(CONNECTION_ENDPOINT, endpointDetails);
}
@Override
public SSLSession getSSLSession() {
return parent.getSSLSession();
return getAttr(HttpCoreContext.SSL_SESSION, SSLSession.class);
}
@Override
public void setSSLSession(final SSLSession sslSession) {
parent.setSSLSession(sslSession);
httpContext.setAttribute(HttpCoreContext.SSL_SESSION, sslSession);
}
@Override
public ProtocolVersion getProtocolVersion() {
return httpContext.getProtocolVersion();
}
@Override
public void setProtocolVersion(final ProtocolVersion version) {
httpContext.setProtocolVersion(version);
}
@Override
public Object getAttribute(final String id) {
return httpContext.getAttribute(id);
}
@Override
public Object setAttribute(final String id, final Object obj) {
return httpContext.setAttribute(id, obj);
}
@Override
public Object removeAttribute(final String id) {
return httpContext.removeAttribute(id);
}
@Override
public <T> T getAttribute(final String id, final Class<T> clazz) {
return getAttr(id, clazz);
}
@Override
public String toString() {
return parent.toString();
return httpContext.toString();
}
}

View File

@ -90,7 +90,7 @@ public class ClientMultiThreadedExecution {
public GetThread(final CloseableHttpClient httpClient, final HttpGet httpget, final int id) {
this.httpClient = httpClient;
this.context = new HttpClientContext();
this.context = HttpClientContext.create();
this.httpget = httpget;
this.id = id;
}

View File

@ -44,7 +44,7 @@ public class ClientRemoteEndpointDetails {
public static void main(final String[] args) throws Exception {
try (final CloseableHttpClient httpclient = HttpClients.createDefault()) {
// Create local HTTP context
final HttpClientContext localContext = new HttpClientContext();
final HttpClientContext localContext = HttpClientContext.create();
final HttpGet httpget = new HttpGet("http://httpbin.org/get");
System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());

View File

@ -43,7 +43,7 @@ public class TestDefaultConnKeepAliveStrategy {
@Test
public void testIllegalResponseArg() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ConnectionKeepAliveStrategy keepAliveStrat = new DefaultConnectionKeepAliveStrategy();
Assertions.assertThrows(NullPointerException.class, () ->
keepAliveStrat.getKeepAliveDuration(null, context));

View File

@ -86,7 +86,7 @@ public class TestHttpAuthenticator {
this.authScheme = Mockito.mock(CacheableAuthState.class, Mockito.withSettings()
.defaultAnswer(Answers.CALLS_REAL_METHODS));
Mockito.when(this.authScheme.isChallengeComplete()).thenReturn(Boolean.TRUE);
this.context = new HttpClientContext();
this.context = HttpClientContext.create();
this.defaultHost = new HttpHost("localhost", 80);
this.credentialsProvider = Mockito.mock(CredentialsProvider.class);
this.context.setCredentialsProvider(this.credentialsProvider);

View File

@ -94,7 +94,7 @@ public class TestSystemDefaultCredentialsProvider {
final URL httpRequestUrl = new URL(TARGET_SCHEME1, TARGET_HOST1, TARGET_PORT1, "/");
final AuthScope authScope = new AuthScope(PROXY_PROTOCOL1, PROXY_HOST1, PROXY_PORT1, PROMPT1, StandardAuthScheme.BASIC);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
context.setRequest(new HttpGet(httpRequestUrl.toURI()));
final Credentials receivedCredentials =

View File

@ -94,7 +94,7 @@ public class TestConnectExec {
@Test
public void testExecAcquireConnection() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
try (final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK")) {
response.setEntity(EntityBuilder.create()
@ -113,7 +113,7 @@ public class TestConnectExec {
@Test
public void testEstablishDirectRoute() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ConnectionState connectionState = new ConnectionState();
@ -133,7 +133,7 @@ public class TestConnectExec {
@Test
public void testEstablishRouteDirectProxy() throws Exception {
final HttpRoute route = new HttpRoute(target, null, proxy, false);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ConnectionState connectionState = new ConnectionState();
@ -153,7 +153,7 @@ public class TestConnectExec {
@Test
public void testEstablishRouteViaProxyTunnel() throws Exception {
final HttpRoute route = new HttpRoute(target, null, proxy, true);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
@ -184,7 +184,7 @@ public class TestConnectExec {
@Test
public void testEstablishRouteViaProxyTunnelUnexpectedResponse() throws Exception {
final HttpRoute route = new HttpRoute(target, null, proxy, true);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response = new BasicClassicHttpResponse(101, "Lost");
@ -204,7 +204,7 @@ public class TestConnectExec {
@Test
public void testEstablishRouteViaProxyTunnelFailure() throws Exception {
final HttpRoute route = new HttpRoute(target, null, proxy, true);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response = new BasicClassicHttpResponse(500, "Boom");
response.setEntity(new StringEntity("Ka-boom"));
@ -228,7 +228,7 @@ public class TestConnectExec {
@Test
public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengePersistentConnection() throws Exception {
final HttpRoute route = new HttpRoute(target, null, proxy, true);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response1 = new BasicClassicHttpResponse(407, "Huh?");
response1.setHeader(HttpHeaders.PROXY_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test");
@ -269,7 +269,7 @@ public class TestConnectExec {
@Test
public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengeNonPersistentConnection() throws Exception {
final HttpRoute route = new HttpRoute(target, null, proxy, true);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response1 = new BasicClassicHttpResponse(407, "Huh?");
response1.setHeader(HttpHeaders.PROXY_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test");
@ -311,7 +311,7 @@ public class TestConnectExec {
final HttpHost proxy2 = new HttpHost("that", 8888);
final HttpRoute route = new HttpRoute(target, null, new HttpHost[] {proxy1, proxy2},
true, RouteInfo.TunnelType.TUNNELLED, RouteInfo.LayerType.LAYERED);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ConnectionState connectionState = new ConnectionState();

View File

@ -89,7 +89,7 @@ public class TestInternalHttpClient {
MockitoAnnotations.openMocks(this);
client = new InternalHttpClient(connManager, requestExecutor, new ExecChainElement(execChain, null), routePlanner,
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider,
defaultConfig, Arrays.asList(closeable1, closeable2));
HttpClientContext::castOrCreate, defaultConfig, Arrays.asList(closeable1, closeable2));
}

View File

@ -114,7 +114,7 @@ public class TestMainClientExec {
@Test
public void testExecRequestNonPersistentConnection() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
response.setEntity(EntityBuilder.create()
@ -145,7 +145,7 @@ public class TestMainClientExec {
@Test
public void testExecRequestNonPersistentConnectionNoResponseEntity() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
response.setEntity(null);
@ -174,7 +174,7 @@ public class TestMainClientExec {
@Test
public void testExecRequestPersistentConnection() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
// The entity is streaming
@ -210,7 +210,7 @@ public class TestMainClientExec {
@Test
public void testExecRequestPersistentConnectionNoResponseEntity() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
@ -240,7 +240,7 @@ public class TestMainClientExec {
@Test
public void testExecRequestConnectionRelease() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
// The entity is streaming
@ -275,7 +275,7 @@ public class TestMainClientExec {
@Test
public void testExecConnectionShutDown() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
Mockito.when(execRuntime.execute(
@ -293,7 +293,7 @@ public class TestMainClientExec {
@Test
public void testExecRuntimeException() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
Mockito.when(execRuntime.execute(
@ -311,7 +311,7 @@ public class TestMainClientExec {
@Test
public void testExecHttpException() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
Mockito.when(execRuntime.execute(
@ -329,7 +329,7 @@ public class TestMainClientExec {
@Test
public void testExecIOException() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://bar/test");
Mockito.when(execRuntime.execute(

View File

@ -151,7 +151,7 @@ public class TestProtocolExec {
@Test
public void testExecRequestRetryOnAuthChallenge() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new HttpGet("http://foo/test");
final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?");
response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test");
@ -204,7 +204,7 @@ public class TestProtocolExec {
.setStream(inStream2)
.build());
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final AuthExchange authExchange = new AuthExchange();
authExchange.setState(AuthExchange.State.SUCCESS);
@ -245,7 +245,7 @@ public class TestProtocolExec {
@Test
public void testExecEntityEnclosingRequest() throws Exception {
final HttpRoute route = new HttpRoute(target);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpPost request = new HttpPost("http://foo/test");
final InputStream inStream0 = new ByteArrayInputStream(new byte[] {1, 2, 3});
request.setEntity(EntityBuilder.create()

View File

@ -83,7 +83,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testConnect() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpHost host = new HttpHost("somehost");
final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 0});
final InetAddress ip1 = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
@ -116,7 +116,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testConnectWithTLSUpgrade() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpHost host = new HttpHost("https", "somehost");
final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 0});
final InetAddress ip1 = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
@ -152,7 +152,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testConnectTimeout() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpHost host = new HttpHost("somehost");
final InetAddress ip1 = InetAddress.getByAddress(new byte[] {10, 0, 0, 1});
final InetAddress ip2 = InetAddress.getByAddress(new byte[] {10, 0, 0, 2});
@ -169,7 +169,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testConnectFailure() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpHost host = new HttpHost("somehost");
final InetAddress ip1 = InetAddress.getByAddress(new byte[] {10, 0, 0, 1});
final InetAddress ip2 = InetAddress.getByAddress(new byte[] {10, 0, 0, 2});
@ -186,7 +186,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testConnectFailover() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpHost host = new HttpHost("somehost");
final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 0});
final InetAddress ip1 = InetAddress.getByAddress(new byte[] {10, 0, 0, 1});
@ -213,7 +213,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testConnectExplicitAddress() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 0});
final InetAddress ip = InetAddress.getByAddress(new byte[] {127, 0, 0, 23});
final HttpHost host = new HttpHost(ip);
@ -235,7 +235,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testUpgrade() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpHost host = new HttpHost("https", "somehost", -1);
Mockito.when(conn.isOpen()).thenReturn(true);
@ -257,7 +257,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testUpgradeUpsupportedScheme() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpHost host = new HttpHost("httpsssss", "somehost", -1);
Mockito.when(conn.isOpen()).thenReturn(true);
@ -269,7 +269,7 @@ public class TestHttpClientConnectionOperator {
@Test
public void testUpgradeNonLayeringScheme() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpHost host = new HttpHost("http", "somehost", -1);
Mockito.when(conn.isOpen()).thenReturn(true);

View File

@ -59,7 +59,7 @@ public class TestDefaultProxyRoutePlanner {
public void testDefaultProxyDirect() throws Exception {
final HttpHost target = new HttpHost("http", "somehost", 80);
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
final HttpRoute route = routePlanner.determineRoute(target, context);
Assertions.assertEquals(target, route.getTargetHost());

View File

@ -60,7 +60,7 @@ public class TestDefaultRoutePlanner {
public void testDirect() throws Exception {
final HttpHost target = new HttpHost("http", "somehost", 80);
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
final HttpRoute route = routePlanner.determineRoute(target, context);
Assertions.assertEquals(target, route.getTargetHost());
@ -74,7 +74,7 @@ public class TestDefaultRoutePlanner {
final HttpHost target = new HttpHost("https", "somehost", -1);
Mockito.when(schemePortResolver.resolve(target)).thenReturn(443);
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
final HttpRoute route = routePlanner.determineRoute(target, context);
Assertions.assertEquals(new HttpHost("https", "somehost", 443), route.getTargetHost());
@ -101,7 +101,7 @@ public class TestDefaultRoutePlanner {
@Test
public void testNullTarget() throws Exception {
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
Assertions.assertThrows(ProtocolException.class, () ->
routePlanner.determineRoute(null, context));
}
@ -112,7 +112,7 @@ public class TestDefaultRoutePlanner {
final URIAuthority virtualHost = new URIAuthority("someotherhost", 443);
final HttpRequest request = new BasicHttpRequest("https", "GET", virtualHost, "/");
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
final HttpRoute route = routePlanner.determineRoute(target, request, context);
Assertions.assertEquals(target, route.getTargetHost());
@ -128,7 +128,7 @@ public class TestDefaultRoutePlanner {
final URIAuthority virtualHost = new URIAuthority("someotherhost", 80);
final HttpRequest request = new BasicHttpRequest("http", "GET", virtualHost, "/");
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
final HttpRoute route = routePlanner.determineRoute(target, request, context);
Assertions.assertEquals(target, route.getTargetHost());

View File

@ -66,7 +66,7 @@ public class TestSystemDefaultRoutePlanner {
public void testDirect() throws Exception {
final HttpHost target = new HttpHost("http", "somehost", 80);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpRoute route = routePlanner.determineRoute(target, context);
Assertions.assertEquals(target, route.getTargetHost());
@ -80,7 +80,7 @@ public class TestSystemDefaultRoutePlanner {
final HttpHost target = new HttpHost("https", "somehost", -1);
Mockito.when(schemePortResolver.resolve(target)).thenReturn(443);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpRoute route = routePlanner.determineRoute(target, context);
Assertions.assertEquals(new HttpHost("https", "somehost", 443), route.getTargetHost());
@ -105,7 +105,7 @@ public class TestSystemDefaultRoutePlanner {
final HttpHost target = new HttpHost("http", "somehost", 80);
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final HttpRoute route = routePlanner.determineRoute(target, context);
Assertions.assertEquals(target, route.getTargetHost());

View File

@ -42,7 +42,7 @@ public class TestRequestDefaultHeaders {
@Test
public void testRequestParameterCheck() throws Exception {
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
final HttpRequestInterceptor interceptor = RequestDefaultHeaders.INSTANCE;
Assertions.assertThrows(NullPointerException.class, () ->
interceptor.process(null, null, context));
@ -53,7 +53,7 @@ public class TestRequestDefaultHeaders {
final HttpRequest request = new BasicHttpRequest("CONNECT", "www.somedomain.com");
final List<Header> defheaders = new ArrayList<>();
defheaders.add(new BasicHeader("custom", "stuff"));
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
final HttpRequestInterceptor interceptor = new RequestDefaultHeaders(defheaders);
interceptor.process(request, null, context);
@ -67,7 +67,7 @@ public class TestRequestDefaultHeaders {
request.addHeader("custom", "stuff");
final List<Header> defheaders = new ArrayList<>();
defheaders.add(new BasicHeader("custom", "other stuff"));
final HttpContext context = new HttpClientContext();
final HttpContext context = HttpClientContext.create();
final HttpRequestInterceptor interceptor = new RequestDefaultHeaders(defheaders);
interceptor.process(request, null, context);

View File

@ -60,7 +60,7 @@ public class TestRequestExpectContinue {
@Test
public void testRequestExpectContinueNotGenerated() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(false).build();
context.setRequestConfig(config);
final ClassicHttpRequest request = new BasicClassicHttpRequest("POST", "/");
@ -75,7 +75,7 @@ public class TestRequestExpectContinue {
@Test
public void testRequestExpectContinueHTTP10() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(true).build();
context.setRequestConfig(config);
final ClassicHttpRequest request = new BasicClassicHttpRequest("POST", "/");
@ -91,7 +91,7 @@ public class TestRequestExpectContinue {
@Test
public void testRequestExpectContinueZeroContent() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(true).build();
context.setRequestConfig(config);
final ClassicHttpRequest request = new BasicClassicHttpRequest("POST", "/");
@ -112,7 +112,7 @@ public class TestRequestExpectContinue {
@Test
public void testRequestExpectContinueIgnoreNonenclosingRequests() throws Exception {
final HttpClientContext context = new HttpClientContext();
final HttpClientContext context = HttpClientContext.create();
final ClassicHttpRequest request = new BasicClassicHttpRequest("POST", "/");
final RequestExpectContinue interceptor = new RequestExpectContinue();
interceptor.process(request, null, context);

View File

@ -53,7 +53,7 @@ class TestRequestValidateTrace {
@BeforeEach
void setUp() {
interceptor = new RequestValidateTrace();
context = new HttpClientContext();
context = HttpClientContext.create();
}
@Test