anchor.diff:          challenge != null && challenge.length == 1;
     }
   
  -  Future<HttpClientResponse> _authenticate() {
  -    Future<HttpClientResponse> retryWithCredentials(_Credentials cr) {
  -      if (cr != null && cr.scheme != _AuthenticationScheme.UNKNOWN) {
  -        // Drain body and retry.
  -        return fold(null, (x, y) {}).then((_) {
  -            return _httpClient._openUrlFromRequest(_httpRequest.method,
  -                                                   _httpRequest.uri,
  -                                                   _httpRequest)
  -                .then((request) => request.close());
  +  Future<HttpClientResponse> _authenticate(bool proxyAuth) {
  +    Future<HttpClientResponse> retry() {
  +      // Drain body and retry.
  +      return fold(null, (x, y) {}).then((_) {
  +          return _httpClient._openUrlFromRequest(_httpRequest.method,
  +                                                 _httpRequest.uri,
  +                                                 _httpRequest)
  +              .then((request) => request.close());
             });
  -      }
   
         // Fall through to here to perform normal response handling if
         // there is no sensible authorization handling.
         return new Future.value(this);
       }
   
  -    List<String> challenge = headers[HttpHeaders.WWW_AUTHENTICATE];
  +    List<String> authChallenge() {
  +      if (proxyAuth) {
  +        return headers[HttpHeaders.PROXY_AUTHENTICATE];
  +      } else {
  +        return headers[HttpHeaders.WWW_AUTHENTICATE];
  +      }
  +    }
  +
  +    _Credentials findCredentials(_AuthenticationScheme scheme) {
  +      if (proxyAuth) {
  +        return  _httpClient._findProxyCredentials(_httpRequest._proxy, scheme);
  +      } else {
  +        return _httpClient._findCredentials(_httpRequest.uri, scheme);
  +      }
  +    }
  +
  +    void removeCredentials(_Credentials cr) {
  +      if (proxyAuth) {
  +        _httpClient._removeProxyCredentials(cr);
  +      } else {
  +        _httpClient._removeCredentials(cr);
  +      }
  +    }
  +
  +    Future requestAuthentication(_AuthenticationScheme scheme, String realm) {
  +      if (proxyAuth) {
  +        if (_httpClient._authenticateProxy == null) {
  +          return new Future.value(false);
  +        }
  +        var proxy = _httpRequest._proxy;
  +        return _httpClient._authenticateProxy(proxy.host,
  +                                              proxy.port,
  +                                              scheme.toString(),
  +                                              realm);
  +      } else {
  +        if (_httpClient._authenticate == null) {
  +          return new Future.value(false);
  +        }
  +        return _httpClient._authenticate(_httpRequest.uri,
  +                                         scheme.toString(),
  +                                         realm);
  +      }
  +    }
  +
  +    List<String> challenge = authChallenge();
       assert(challenge != null || challenge.length == 1);
       _HeaderValue header =
           _HeaderValue.parse(challenge[0], parameterSeparator: ",");
  
positive.code:     return cr;
    }
  
    _ProxyCredentials _findProxyCredentials(_Proxy proxy) {
      // Look for credentials.
      var it = _proxyCredentials.iterator;
      while (it.moveNext()) {
        if (it.current.applies(proxy, _AuthenticationScheme.BASIC)) {
          return it.current;
        }
      }
  
negative.code:                 new RedirectLimitExceededException(response.redirects)));
        }
      } else if (response._shouldAuthenticateProxy) {
        future = response._authenticate(true);
      } else if (response._shouldAuthenticate) {
        future = response._authenticate(false);
      } else {
        future = new Future<HttpClientResponse>.value(response);
      }
  