private Realm kerberosChallenge(
      List<String> proxyAuth,
      Request request,
      ProxyServer proxyServer,
      FluentCaseInsensitiveStringsMap headers,
      Realm realm,
      NettyResponseFuture<?> future)
      throws NTLMEngineException {

    URI uri = request.getURI();
    String host =
        request.getVirtualHost() == null
            ? AsyncHttpProviderUtils.getHost(uri)
            : request.getVirtualHost();
    String server = proxyServer == null ? host : proxyServer.getHost();
    try {
      String challengeHeader = SpnegoEngine.instance().generateToken(server);
      headers.remove(HttpHeaders.Names.AUTHORIZATION);
      headers.add(HttpHeaders.Names.AUTHORIZATION, "Negotiate " + challengeHeader);

      return newRealmBuilder(realm) //
          .setUri(uri.getRawPath()) //
          .setMethodName(request.getMethod()) //
          .setScheme(Realm.AuthScheme.KERBEROS) //
          .build();

    } catch (Throwable throwable) {
      if (isNTLM(proxyAuth)) {
        return ntlmChallenge(proxyAuth, request, proxyServer, headers, realm, future);
      }
      channels.abort(future, throwable);
      return null;
    }
  }
  private Realm ntlmProxyChallenge(
      List<String> wwwAuth,
      Request request,
      ProxyServer proxyServer,
      FluentCaseInsensitiveStringsMap headers,
      Realm realm,
      NettyResponseFuture<?> future)
      throws NTLMEngineException {
    future.getAndSetAuth(false);
    headers.remove(HttpHeaders.Names.PROXY_AUTHORIZATION);

    addType3NTLMAuthorizationHeader(
        wwwAuth,
        headers,
        proxyServer.getPrincipal(),
        proxyServer.getPassword(),
        proxyServer.getNtlmDomain(),
        proxyServer.getHost());

    return newRealmBuilder(realm) //
        // .setScheme(realm.getAuthScheme())
        .setUri(request.getURI().getPath()) //
        .setMethodName(request.getMethod())
        .build();
  }
  private boolean handleConnectOKAndExit(
      int statusCode,
      Realm realm,
      final Request request,
      HttpRequest httpRequest,
      HttpResponse response,
      final NettyResponseFuture<?> future,
      ProxyServer proxyServer,
      final Channel channel)
      throws IOException {
    if (statusCode == OK.code() && httpRequest.getMethod() == HttpMethod.CONNECT) {

      LOGGER.debug("Connected to {}:{}", proxyServer.getHost(), proxyServer.getPort());

      if (future.isKeepAlive()) {
        future.attachChannel(channel, true);
      }

      try {
        LOGGER.debug("Connecting to proxy {} for scheme {}", proxyServer, request.getUrl());
        channels.upgradeProtocol(channel.pipeline(), request.getURI().getScheme());
      } catch (Throwable ex) {
        channels.abort(future, ex);
      }
      future.setReuseChannel(true);
      future.setConnectAllowed(false);
      requestSender.sendNextRequest(new RequestBuilder(future.getRequest()).build(), future);
      return true;
    }

    return false;
  }
  private Realm ntlmChallenge(
      List<String> wwwAuth,
      Request request,
      ProxyServer proxyServer,
      FluentCaseInsensitiveStringsMap headers,
      Realm realm,
      NettyResponseFuture<?> future)
      throws NTLMEngineException {

    boolean useRealm = proxyServer == null && realm != null;

    String ntlmDomain = useRealm ? realm.getNtlmDomain() : proxyServer.getNtlmDomain();
    String ntlmHost = useRealm ? realm.getNtlmHost() : proxyServer.getHost();
    String principal = useRealm ? realm.getPrincipal() : proxyServer.getPrincipal();
    String password = useRealm ? realm.getPassword() : proxyServer.getPassword();

    if (realm != null && !realm.isNtlmMessageType2Received()) {
      String challengeHeader = NTLMEngine.INSTANCE.generateType1Msg(ntlmDomain, ntlmHost);

      URI uri = request.getURI();
      addNTLMAuthorizationHeader(headers, challengeHeader);
      future.getAndSetAuth(false);
      return newRealmBuilder(realm) //
          .setScheme(realm.getAuthScheme()) //
          .setUri(uri.getRawPath()) //
          .setMethodName(request.getMethod()) //
          .setNtlmMessageType2Received(true) //
          .build();

    } else {
      addType3NTLMAuthorizationHeader(wwwAuth, headers, principal, password, ntlmDomain, ntlmHost);
      Realm.AuthScheme authScheme = realm != null ? realm.getAuthScheme() : Realm.AuthScheme.NTLM;
      return newRealmBuilder(realm) //
          .setScheme(authScheme) //
          .setUri(request.getURI().getPath()) //
          .setMethodName(request.getMethod()) //
          .build();
    }
  }