in httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncProtocolExec.java [178:301]
private void internalExecute(
final HttpHost target,
final String pathPrefix,
final AuthExchange targetAuthExchange,
final AuthExchange proxyAuthExchange,
final AtomicBoolean challenged,
final HttpRequest request,
final AsyncEntityProducer entityProducer,
final AsyncExecChain.Scope scope,
final AsyncExecChain chain,
final AsyncExecCallback asyncExecCallback) throws HttpException, IOException {
final String exchangeId = scope.exchangeId;
final HttpRoute route = scope.route;
final HttpClientContext clientContext = scope.clientContext;
final AsyncExecRuntime execRuntime = scope.execRuntime;
final HttpHost proxy = route.getProxyHost();
if (!request.containsHeader(HttpHeaders.AUTHORIZATION)) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} target auth state: {}", exchangeId, targetAuthExchange.getState());
}
authenticator.addAuthResponse(target, ChallengeType.TARGET, request, targetAuthExchange, clientContext);
}
if (!request.containsHeader(HttpHeaders.PROXY_AUTHORIZATION) && !route.isTunnelled()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} proxy auth state: {}", exchangeId, proxyAuthExchange.getState());
}
authenticator.addAuthResponse(proxy, ChallengeType.PROXY, request, proxyAuthExchange, clientContext);
}
chain.proceed(request, entityProducer, scope, new AsyncExecCallback() {
@Override
public AsyncDataConsumer handleResponse(
final HttpResponse response,
final EntityDetails entityDetails) throws HttpException, IOException {
if (Method.TRACE.isSame(request.getMethod())) {
// Do not perform authentication for TRACE request
return asyncExecCallback.handleResponse(response, entityDetails);
}
if (needAuthentication(
targetAuthExchange,
proxyAuthExchange,
proxy != null ? proxy : target,
target,
pathPrefix,
response,
clientContext)) {
challenged.set(true);
return null;
}
challenged.set(false);
return asyncExecCallback.handleResponse(response, entityDetails);
}
@Override
public void handleInformationResponse(
final HttpResponse response) throws HttpException, IOException {
asyncExecCallback.handleInformationResponse(response);
}
@Override
public void completed() {
if (!execRuntime.isEndpointConnected()) {
if (proxyAuthExchange.getState() == AuthExchange.State.SUCCESS
&& proxyAuthExchange.isConnectionBased()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} resetting proxy auth state", exchangeId);
}
proxyAuthExchange.reset();
}
if (targetAuthExchange.getState() == AuthExchange.State.SUCCESS
&& targetAuthExchange.isConnectionBased()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} resetting target auth state", exchangeId);
}
targetAuthExchange.reset();
}
}
if (challenged.get()) {
if (entityProducer != null && !entityProducer.isRepeatable()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} cannot retry non-repeatable request", exchangeId);
}
asyncExecCallback.completed();
} else {
// Reset request headers
final HttpRequest original = scope.originalRequest;
request.setHeaders();
for (final Iterator<Header> it = original.headerIterator(); it.hasNext(); ) {
request.addHeader(it.next());
}
try {
if (entityProducer != null) {
entityProducer.releaseResources();
}
internalExecute(target, pathPrefix, targetAuthExchange, proxyAuthExchange,
challenged, request, entityProducer, scope, chain, asyncExecCallback);
} catch (final HttpException | IOException ex) {
asyncExecCallback.failed(ex);
}
}
} else {
asyncExecCallback.completed();
}
}
@Override
public void failed(final Exception cause) {
if (cause instanceof IOException || cause instanceof RuntimeException) {
for (final AuthExchange authExchange : clientContext.getAuthExchanges().values()) {
if (authExchange.isConnectionBased()) {
authExchange.reset();
}
}
}
asyncExecCallback.failed(cause);
}
});
}