private void internalExecute()

in httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncRedirectExec.java [101:251]


    private void internalExecute(
            final State state,
            final AsyncExecChain chain,
            final AsyncExecCallback asyncExecCallback) throws HttpException, IOException {

        final HttpRequest request = state.currentRequest;
        final AsyncEntityProducer entityProducer = state.currentEntityProducer;
        final AsyncExecChain.Scope scope = state.currentScope;
        final HttpClientContext clientContext = scope.clientContext;
        final String exchangeId = scope.exchangeId;
        final HttpRoute currentRoute = scope.route;
        chain.proceed(request, entityProducer, scope, new AsyncExecCallback() {

            @Override
            public AsyncDataConsumer handleResponse(
                    final HttpResponse response,
                    final EntityDetails entityDetails) throws HttpException, IOException {

                state.redirectURI = null;
                final RequestConfig config = clientContext.getRequestConfig();
                if (config.isRedirectsEnabled() && redirectStrategy.isRedirected(request, response, clientContext)) {
                    if (state.redirectCount >= state.maxRedirects) {
                        throw new RedirectException("Maximum redirects (" + state.maxRedirects + ") exceeded");
                    }

                    state.redirectCount++;

                    final URI redirectUri = redirectStrategy.getLocationURI(request, response, clientContext);
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("{} redirect requested to location '{}'", exchangeId, redirectUri);
                    }
                    if (!config.isCircularRedirectsAllowed()) {
                        if (state.redirectLocations.contains(redirectUri)) {
                            throw new CircularRedirectException("Circular redirect to '" + redirectUri + "'");
                        }
                    }
                    state.redirectLocations.add(redirectUri);

                    final HttpHost newTarget = URIUtils.extractHost(redirectUri);
                    if (newTarget == null) {
                        throw new ProtocolException("Redirect URI does not specify a valid host name: " + redirectUri);
                    }

                    final int statusCode = response.getCode();
                    final BasicRequestBuilder redirectBuilder;
                    switch (statusCode) {
                        case HttpStatus.SC_MOVED_PERMANENTLY:
                        case HttpStatus.SC_MOVED_TEMPORARILY:
                            if (Method.POST.isSame(request.getMethod())) {
                                redirectBuilder = BasicRequestBuilder.get();
                                state.currentEntityProducer = null;
                            } else {
                                redirectBuilder = BasicRequestBuilder.copy(scope.originalRequest);
                            }
                            break;
                        case HttpStatus.SC_SEE_OTHER:
                            if (!Method.GET.isSame(request.getMethod()) && !Method.HEAD.isSame(request.getMethod())) {
                                redirectBuilder = BasicRequestBuilder.get();
                                state.currentEntityProducer = null;
                            } else {
                                redirectBuilder = BasicRequestBuilder.copy(scope.originalRequest);
                            }
                            break;
                        default:
                            redirectBuilder = BasicRequestBuilder.copy(scope.originalRequest);
                    }
                    redirectBuilder.setUri(redirectUri);
                    state.reroute = false;
                    state.redirectURI = redirectUri;
                    state.currentRequest = redirectBuilder.build();

                    if (!Objects.equals(currentRoute.getTargetHost(), newTarget)) {
                        final HttpRoute newRoute = routePlanner.determineRoute(newTarget, clientContext);
                        if (!Objects.equals(currentRoute, newRoute)) {
                            state.reroute = true;
                            final AuthExchange targetAuthExchange = clientContext.getAuthExchange(currentRoute.getTargetHost());
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("{} resetting target auth state", exchangeId);
                            }
                            targetAuthExchange.reset();
                            if (currentRoute.getProxyHost() != null) {
                                final AuthExchange proxyAuthExchange = clientContext.getAuthExchange(currentRoute.getProxyHost());
                                if (proxyAuthExchange.isConnectionBased()) {
                                    if (LOG.isDebugEnabled()) {
                                        LOG.debug("{} resetting proxy auth state", exchangeId);
                                    }
                                    proxyAuthExchange.reset();
                                }
                            }
                            state.currentScope = new AsyncExecChain.Scope(
                                    scope.exchangeId,
                                    newRoute,
                                    scope.originalRequest,
                                    scope.cancellableDependency,
                                    scope.clientContext,
                                    scope.execRuntime,
                                    scope.scheduler,
                                    scope.execCount);
                        }
                    }
                }
                if (state.redirectURI != null) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("{} redirecting to '{}' via {}", exchangeId, state.redirectURI, currentRoute);
                    }
                    return null;
                }
                return asyncExecCallback.handleResponse(response, entityDetails);
            }

            @Override
            public void handleInformationResponse(
                    final HttpResponse response) throws HttpException, IOException {
                asyncExecCallback.handleInformationResponse(response);
            }

            @Override
            public void completed() {
                if (state.redirectURI == null) {
                    asyncExecCallback.completed();
                } else {
                    final AsyncEntityProducer entityProducer = state.currentEntityProducer;
                    if (entityProducer != null) {
                        entityProducer.releaseResources();
                    }
                    if (entityProducer != null && !entityProducer.isRepeatable()) {
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("{} cannot redirect non-repeatable request", exchangeId);
                        }
                        asyncExecCallback.completed();
                    } else {
                        try {
                            if (state.reroute) {
                                scope.execRuntime.releaseEndpoint();
                            }
                            internalExecute(state, chain, asyncExecCallback);
                        } catch (final IOException | HttpException ex) {
                            asyncExecCallback.failed(ex);
                        }
                    }
                }
            }

            @Override
            public void failed(final Exception cause) {
                asyncExecCallback.failed(cause);
            }

        });

    }