Beispiel #1
0
        private void ConfigureRequest(HttpWebRequest request)
        {
            request.Proxy = _proxyCache.GetProxy(request.RequestUri);
            if (request.Proxy != null && request.Proxy.Credentials == null)
            {
                request.Proxy.Credentials = CredentialCache.DefaultCredentials;
            }

            if (_previousResponse == null || ShouldKeepAliveBeUsedInRequest(_previousRequest, _previousResponse))
            {
                // Try to use the cached credentials (if any, for the first request)
                request.Credentials = _credentialCache.GetCredentials(request.RequestUri);

                // If there are no cached credentials, use the default ones
                if (request.Credentials == null)
                {
                    request.UseDefaultCredentials = true;
                }
            }
            else if (_previousStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
            {
                request.Proxy.Credentials = _credentialProvider.GetCredentials(
                    request, CredentialType.ProxyCredentials, retrying: _proxyCredentialsRetryCount > 0);
                _continueIfFailed = request.Proxy.Credentials != null;
                _proxyCredentialsRetryCount++;
            }
            else if (_previousStatusCode == HttpStatusCode.Unauthorized)
            {
                SetCredentialsOnAuthorizationError(request);
            }

            SetKeepAliveHeaders(request, _previousResponse);
            if (_usingSTSAuth)
            {
                // Add request headers if the server requires STS based auth.
                STSAuthHelper.PrepareSTSRequest(request);
            }

            // Wrap the credentials in a CredentialCache in case there is a redirect
            // and credentials need to be kept around.
            request.Credentials = request.Credentials.AsCredentialCache(request.RequestUri);
        }
Beispiel #2
0
        public HttpWebResponse GetResponse(CancellationToken token)
        {
            _previousRequest            = null;
            _previousResponse           = null;
            _previousStatusCode         = null;
            _usingSTSAuth               = false;
            _continueIfFailed           = true;
            _proxyCredentialsRetryCount = 0;
            _credentialsRetryCount      = 0;
            int       failureCount    = 0;
            const int MaxFailureCount = 10;

            while (true)
            {
                // Create the request
                var request = (HttpWebRequest)_createRequest();
                MakeCancelable(request, token);
                ConfigureRequest(request);

                try
                {
                    var auth = request.Headers["Authorization"];
                    _basicAuthIsUsedInPreviousRequest = (auth != null) &&
                                                        auth.StartsWith("Basic ", StringComparison.Ordinal);

                    // Prepare the request, we do something like write to the request stream
                    // which needs to happen last before the request goes out
                    _prepareRequest(request);

                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                    // Cache the proxy and credentials
                    _proxyCache.Add(request.Proxy);

                    ICredentials credentials = request.Credentials;
                    _credentialCache.Add(request.RequestUri, credentials);
                    _credentialCache.Add(response.ResponseUri, credentials);

                    return(response);
                }
                catch (WebException ex)
                {
                    ++failureCount;
                    if (failureCount >= MaxFailureCount)
                    {
                        throw;
                    }

                    using (IHttpWebResponse response = GetResponse(ex.Response))
                    {
                        if (response == null &&
                            ex.Status != WebExceptionStatus.SecureChannelFailure)
                        {
                            // No response, something went wrong so just rethrow
                            throw;
                        }

                        // Special case https connections that might require authentication
                        if (ex.Status == WebExceptionStatus.SecureChannelFailure)
                        {
                            if (_continueIfFailed)
                            {
                                // Act like we got a 401 so that we prompt for credentials on the next request
                                _previousStatusCode = HttpStatusCode.Unauthorized;
                                continue;
                            }
                            throw;
                        }

                        // If we were trying to authenticate the proxy or the request and succeeded, cache the result.
                        if (_previousStatusCode == HttpStatusCode.ProxyAuthenticationRequired &&
                            response.StatusCode != HttpStatusCode.ProxyAuthenticationRequired)
                        {
                            _proxyCache.Add(request.Proxy);
                        }
                        else if (_previousStatusCode == HttpStatusCode.Unauthorized &&
                                 response.StatusCode != HttpStatusCode.Unauthorized)
                        {
                            _credentialCache.Add(request.RequestUri, request.Credentials);
                            _credentialCache.Add(response.ResponseUri, request.Credentials);
                        }

                        _usingSTSAuth = STSAuthHelper.TryRetrieveSTSToken(request.RequestUri, response);

                        if (!IsAuthenticationResponse(response) || !_continueIfFailed)
                        {
                            throw;
                        }

                        _previousRequest    = request;
                        _previousResponse   = response;
                        _previousStatusCode = _previousResponse.StatusCode;
                    }
                }
            }
        }