private async Task <HttpResponseMessage> SendWithProxyAsync( Uri proxyUri, HttpRequestMessage request, CancellationToken cancellationToken) { if (proxyUri.Scheme != UriScheme.Http) { throw new NotSupportedException(SR.net_http_invalid_proxy_scheme); } HttpResponseMessage response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false); // Handle proxy authentication if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired) { foreach (AuthenticationHeaderValue h in response.Headers.ProxyAuthenticate) { if (h.Scheme == AuthenticationHelper.Basic) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Basic) ?? _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Basic); if (credential != null) { // TODO #23156: Drain response before disposing. response.Dispose(); request.Headers.ProxyAuthorization = new AuthenticationHeaderValue(AuthenticationHelper.Basic, AuthenticationHelper.GetBasicTokenForCredential(credential)); response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false); } break; } else if (h.Scheme == AuthenticationHelper.Digest) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Digest) ?? _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Digest); if (credential != null) { // Update digest response with new parameter from Proxy-Authenticate AuthenticationHelper.DigestResponse digestResponse = new AuthenticationHelper.DigestResponse(h.Parameter); if (await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false)) { // TODO #23156: Drain response before disposing. response.Dispose(); response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false); // Retry in case of nonce timeout in server. if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired) { foreach (AuthenticationHeaderValue ahv in response.Headers.ProxyAuthenticate) { if (ahv.Scheme == AuthenticationHelper.Digest) { digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter); if (AuthenticationHelper.IsServerNonceStale(digestResponse) && await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } } } } break; } } } } return(response); }
private async Task <HttpResponseMessage> SendWithProxyAsync( Uri proxyUri, HttpRequestMessage request, CancellationToken cancellationToken) { if (proxyUri.Scheme != UriScheme.Http) { throw new InvalidOperationException(SR.net_http_invalid_proxy_scheme); } if (!HttpUtilities.IsSupportedNonSecureScheme(request.RequestUri.Scheme)) { // TODO #23136: Implement SSL tunneling through proxy throw new NotImplementedException("no support for SSL tunneling through proxy"); } HttpConnection connection = await GetOrCreateConnection(request, proxyUri, cancellationToken).ConfigureAwait(false); HttpResponseMessage response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false); // Handle proxy authentication if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired) { foreach (AuthenticationHeaderValue h in response.Headers.ProxyAuthenticate) { // We only support Basic auth, ignore others if (h.Scheme == AuthenticationHelper.Basic) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Basic) ?? _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Basic); if (credential != null) { response.Dispose(); request.Headers.ProxyAuthorization = new AuthenticationHeaderValue(AuthenticationHelper.Basic, AuthenticationHelper.GetBasicTokenForCredential(credential)); connection = await GetOrCreateConnection(request, proxyUri, cancellationToken).ConfigureAwait(false); response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } else if (h.Scheme == AuthenticationHelper.Digest) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Digest) ?? _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Digest); if (credential != null) { // Update digest response with new parameter from Proxy-Authenticate AuthenticationHelper.DigestResponse digestResponse = new AuthenticationHelper.DigestResponse(h.Parameter); if (await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); // Retry in case of nonce timeout in server. if (response.StatusCode == HttpStatusCode.Unauthorized) { foreach (AuthenticationHeaderValue ahv in response.Headers.ProxyAuthenticate) { if (ahv.Scheme == AuthenticationHelper.Digest) { digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter); if (AuthenticationHelper.IsServerNonceStale(digestResponse) && await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false)) { response.Dispose(); response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } } } } break; } } } } return(response); }
private async Task <HttpResponseMessage> SendWithProxyAsync( Uri proxyUri, HttpRequestMessage request, CancellationToken cancellationToken) { if (proxyUri.Scheme != UriScheme.Http) { throw new InvalidOperationException($"invalid scheme {proxyUri.Scheme} for proxy"); } if (request.RequestUri.Scheme == UriScheme.Https) { // TODO #21452: Implement SSL tunneling through proxy throw new NotImplementedException("no support for SSL tunneling through proxy"); } HttpConnection connection = await GetOrCreateConnection(request, proxyUri).ConfigureAwait(false); HttpResponseMessage response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false); // Handle proxy authentication if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired) { foreach (AuthenticationHeaderValue h in response.Headers.ProxyAuthenticate) { // We only support Basic auth, ignore others const string Basic = "Basic"; if (h.Scheme == Basic) { NetworkCredential credential = _proxy.Credentials?.GetCredential(proxyUri, Basic) ?? _defaultCredentials?.GetCredential(proxyUri, Basic); if (credential != null) { response.Dispose(); request.Headers.ProxyAuthorization = new AuthenticationHeaderValue(Basic, AuthenticationHelper.GetBasicTokenForCredential(credential)); connection = await GetOrCreateConnection(request, proxyUri).ConfigureAwait(false); response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false); } break; } } } return(response); }