shadows/httpclient/src/main/java/org/robolectric/shadows/httpclient/DefaultRequestDirector.java
protected boolean createTunnelToTarget(HttpRoute route,
                       HttpContext context)
    throws HttpException, IOException {

    HttpHost proxy = route.getProxyHost();
    HttpHost target = route.getTargetHost();
    HttpResponse response = null;

    boolean done = false;
    while (!done) {

      done = true;

      if (!this.managedConn.isOpen()) {
        this.managedConn.open(route, context, this.params);
      }

      HttpRequest connect = createConnectRequest(route, context);
      connect.setParams(this.params);

      // Populate the execution context
      context.setAttribute(ExecutionContext.HTTP_TARGET_HOST,
          target);
      context.setAttribute(ExecutionContext.HTTP_PROXY_HOST,
          proxy);
      context.setAttribute(ExecutionContext.HTTP_CONNECTION,
          managedConn);
      context.setAttribute(ClientContext.TARGET_AUTH_STATE,
          targetAuthState);
      context.setAttribute(ClientContext.PROXY_AUTH_STATE,
          proxyAuthState);
      context.setAttribute(ExecutionContext.HTTP_REQUEST,
          connect);

      this.requestExec.preProcess(connect, this.httpProcessor, context);

      response = this.requestExec.execute(connect, this.managedConn, context);

      response.setParams(this.params);
      this.requestExec.postProcess(response, this.httpProcessor, context);

      int status = response.getStatusLine().getStatusCode();
      if (status < 200) {
        throw new HttpException("Unexpected response to CONNECT request: " +
            response.getStatusLine());
      }

      CredentialsProvider credsProvider = (CredentialsProvider)
        context.getAttribute(ClientContext.CREDS_PROVIDER);

      if (credsProvider != null && HttpClientParams.isAuthenticating(params)) {
        if (this.proxyAuthHandler.isAuthenticationRequested(response, context)) {

          this.log.debug("Proxy requested authentication");
          Map<String, Header> challenges = this.proxyAuthHandler.getChallenges(
              response, context);
          try {
            processChallenges(
                challenges, this.proxyAuthState, this.proxyAuthHandler,
                response, context);
          } catch (AuthenticationException ex) {
            if (this.log.isWarnEnabled()) {
              this.log.warn("Authentication error: " +  ex.getMessage());
              break;
            }
          }
          updateAuthState(this.proxyAuthState, proxy, credsProvider);

          if (this.proxyAuthState.getCredentials() != null) {
            done = false;

            // Retry request
            if (this.reuseStrategy.keepAlive(response, context)) {
              this.log.debug("Connection kept alive");
              // Consume response content
              HttpEntity entity = response.getEntity();
              if (entity != null) {
                entity.consumeContent();
              }
            } else {
              this.managedConn.close();
            }

          }

        } else {
          // Reset proxy auth scope
          this.proxyAuthState.setAuthScope(null);
        }
      }
    }

    int status = response.getStatusLine().getStatusCode(); // can't be null

    if (status > 299) {

      // Buffer response content
      HttpEntity entity = response.getEntity();
      if (entity != null) {
        response.setEntity(new BufferedHttpEntity(entity));
      }

      this.managedConn.close();
      throw new TunnelRefusedException("CONNECT refused by proxy: " +
          response.getStatusLine(), response);
    }

    this.managedConn.markReusable();

    // How to decide on security of the tunnelled connection?
    // The socket factory knows only about the segment to the proxy.
    // Even if that is secure, the hop to the target may be insecure.
    // Leave it to derived classes, consider insecure by default here.
    return false;

  }
protected boolean createTunnelToTarget(HttpRoute route,
                       HttpContext context)
    throws HttpException, IOException {

    HttpHost proxy = route.getProxyHost();
    HttpHost target = route.getTargetHost();
    HttpResponse response = null;

    boolean done = false;
    while (!done) {

      done = true;

      if (!this.managedConn.isOpen()) {
        this.managedConn.open(route, context, this.params);
      }

      HttpRequest connect = createConnectRequest(route, context);
      connect.setParams(this.params);

      // Populate the execution context
      context.setAttribute(ExecutionContext.HTTP_TARGET_HOST,
          target);
      context.setAttribute(ExecutionContext.HTTP_PROXY_HOST,
          proxy);
      context.setAttribute(ExecutionContext.HTTP_CONNECTION,
          managedConn);
      context.setAttribute(ClientContext.TARGET_AUTH_STATE,
          targetAuthState);
      context.setAttribute(ClientContext.PROXY_AUTH_STATE,
          proxyAuthState);
      context.setAttribute(ExecutionContext.HTTP_REQUEST,
          connect);

      this.requestExec.preProcess(connect, this.httpProcessor, context);

      response = this.requestExec.execute(connect, this.managedConn, context);

      response.setParams(this.params);
      this.requestExec.postProcess(response, this.httpProcessor, context);

      int status = response.getStatusLine().getStatusCode();
      if (status < 200) {
        throw new HttpException("Unexpected response to CONNECT request: " +
            response.getStatusLine());
      }

      CredentialsProvider credsProvider = (CredentialsProvider)
        context.getAttribute(ClientContext.CREDS_PROVIDER);

      if (credsProvider != null && HttpClientParams.isAuthenticating(params)) {
        if (this.proxyAuthHandler.isAuthenticationRequested(response, context)) {

          this.log.debug("Proxy requested authentication");
          Map<String, Header> challenges = this.proxyAuthHandler.getChallenges(
              response, context);
          try {
            processChallenges(
                challenges, this.proxyAuthState, this.proxyAuthHandler,
                response, context);
          } catch (AuthenticationException ex) {
            if (this.log.isWarnEnabled()) {
              this.log.warn("Authentication error: " +  ex.getMessage());
              break;
            }
          }
          updateAuthState(this.proxyAuthState, proxy, credsProvider);

          if (this.proxyAuthState.getCredentials() != null) {
            done = false;

            // Retry request
            if (this.reuseStrategy.keepAlive(response, context)) {
              this.log.debug("Connection kept alive");
              // Consume response content
              HttpEntity entity = response.getEntity();
              if (entity != null) {
                entity.consumeContent();
              }
            } else {
              this.managedConn.close();
            }

          }

        } else {
          // Reset proxy auth scope
          this.proxyAuthState.setAuthScope(null);
        }
      }
    }

    int status = response.getStatusLine().getStatusCode(); // can't be null

    if (status > 299) {

      // Buffer response content
      HttpEntity entity = response.getEntity();
      if (entity != null) {
        response.setEntity(new BufferedHttpEntity(entity));
      }

      this.managedConn.close();
      throw new TunnelRefusedException("CONNECT refused by proxy: " +
          response.getStatusLine(), response);
    }

    this.managedConn.markReusable();

    // How to decide on security of the tunnelled connection?
    // The socket factory knows only about the segment to the proxy.
    // Even if that is secure, the hop to the target may be insecure.
    // Leave it to derived classes, consider insecure by default here.
    return false;

  }
Creates a tunnel to the target server.
The connection must be established to the (last) proxy.
A CONNECT request for tunnelling through the proxy will
be created and sent, the response received and checked.
This method does <i>not</i> update the connection with
information about the tunnel, that is left to the caller.

@param route     the route to establish
@param context   the context for request execution

@return  {@code true} if the tunnelled route is secure,
{@code false} otherwise.
The implementation here always returns {@code false},
but derived classes may override.

@throws HttpException    in case of a problem
@throws IOException      in case of an IO problem