Example #1
0
        protected virtual Task <Stream> CreateContentReadStreamAsync()
        {
            TaskCompletionSource <Stream> tcs = new TaskCompletionSource <Stream>();

            // By default just buffer the content to a memory stream. Derived classes can override this behavior
            // if there is a better way to retrieve the content as stream (e.g. byte array/string use a more efficient
            // way, like wrapping a read-only MemoryStream around the bytes/string)
            LoadIntoBufferAsync().ContinueWithStandard(task =>
            {
                if (!HttpUtilities.HandleFaultsAndCancelation(task, tcs))
                {
                    tcs.TrySetResult(bufferedContent);
                }
            });

            return(tcs.Task);
        }
Example #2
0
        private static void CheckBaseAddress(Uri baseAddress, string parameterName)
        {
            if (baseAddress == null)
            {
                return; // It's OK to not have a base address specified.
            }

            if (!baseAddress.IsAbsoluteUri)
            {
                throw new ArgumentException("The base address must be an absolute URI.", parameterName);
            }

            if (!HttpUtilities.IsHttpUri(baseAddress))
            {
                throw new ArgumentException("Only 'http' and 'https' schemes are allowed.", parameterName);
            }
        }
Example #3
0
        private Task <Stream> ReadAsStreamAsyncCore()
        {
            TaskCompletionSource <Stream> tcs = new TaskCompletionSource <Stream>(this);

            CreateContentReadStreamAsync().ContinueWithStandard(tcs, (task, state) =>
            {
                var innerTcs  = (TaskCompletionSource <Stream>)state;
                var innerThis = (HttpContent)innerTcs.Task.AsyncState;
                if (!HttpUtilities.HandleFaultsAndCancelation(task, innerTcs))
                {
                    innerThis._contentReadStream = task.Result;
                    innerTcs.TrySetResult(innerThis._contentReadStream);
                }
            });

            return(tcs.Task);
        }
Example #4
0
        private static void CheckBaseAddress(Uri baseAddress, string parameterName)
        {
            if (baseAddress == null)
            {
                return; // It's OK to not have a base address specified.
            }

            if (!baseAddress.IsAbsoluteUri)
            {
                throw new ArgumentException(SR.net_http_client_absolute_baseaddress_required, parameterName);
            }

            if (!HttpUtilities.IsHttpUri(baseAddress))
            {
                throw new ArgumentException(SR.net_http_client_http_baseaddress_required, parameterName);
            }
        }
Example #5
0
        private static string GetSslHostName(HttpRequestMessage request)
        {
            Uri uri = request.RequestUri;

            if (!HttpUtilities.IsSupportedSecureScheme(uri.Scheme))
            {
                // Not using SSL.
                return(null);
            }

            string hostHeader = request.Headers.Host;

            if (hostHeader == null)
            {
                // No explicit Host header.  Use host from uri.
                return(request.RequestUri.IdnHost);
            }

            // There is a host header.  Use it, but first see if we need to trim off a port.
            int colonPos = hostHeader.IndexOf(':');

            if (colonPos >= 0)
            {
                // There is colon, which could either be a port separator or a separator in
                // an IPv6 address.  See if this is an IPv6 address; if it's not, use everything
                // before the colon as the host name, and if it is, use everything before the last
                // colon iff the last colon is after the end of the IPv6 address (otherwise it's a
                // part of the address).
                int ipV6AddressEnd = hostHeader.IndexOf(']');
                if (ipV6AddressEnd == -1)
                {
                    return(hostHeader.Substring(0, colonPos));
                }
                else
                {
                    colonPos = hostHeader.LastIndexOf(':');
                    if (colonPos > ipV6AddressEnd)
                    {
                        return(hostHeader.Substring(0, colonPos));
                    }
                }
            }

            return(hostHeader);
        }
Example #6
0
        public Task <byte[]> ReadAsByteArrayAsync()
        {
            CheckDisposed();

            var tcs = new TaskCompletionSource <byte[]>(this);

            LoadIntoBufferAsync().ContinueWithStandard(tcs, (task, state) =>
            {
                var innerTcs  = (TaskCompletionSource <byte[]>)state;
                var innerThis = (HttpContent)innerTcs.Task.AsyncState;
                if (!HttpUtilities.HandleFaultsAndCancelation(task, innerTcs))
                {
                    innerTcs.TrySetResult(innerThis._bufferedContent.ToArray());
                }
            });

            return(tcs.Task);
        }
Example #7
0
        private async ValueTask <HttpConnection> CreateConnection(HttpRequestMessage request, HttpConnectionKey key, HttpConnectionPool pool)
        {
            Uri uri = request.RequestUri;

            Stream stream = await ConnectHelper.ConnectAsync(uri.IdnHost, uri.Port).ConfigureAwait(false);

            TransportContext transportContext = null;

            if (HttpUtilities.IsSupportedSecureScheme(uri.Scheme))
            {
                SslStream sslStream = await EstablishSslConnection(uri.IdnHost, request, stream).ConfigureAwait(false);

                stream           = sslStream;
                transportContext = sslStream.TransportContext;
            }

            return(new HttpConnection(pool, key, uri.IdnHost, stream, transportContext, false));
        }
Example #8
0
        private Uri GetUriForRedirect(Uri requestUri, HttpResponseMessage response)
        {
            switch (response.StatusCode)
            {
            case HttpStatusCode.Moved:
            case HttpStatusCode.Found:
            case HttpStatusCode.SeeOther:
            case HttpStatusCode.TemporaryRedirect:
            case HttpStatusCode.MultipleChoices:
                break;

            default:
                return(null);
            }

            Uri location = response.Headers.Location;

            if (location == null)
            {
                return(null);
            }

            if (!location.IsAbsoluteUri)
            {
                location = new Uri(requestUri, location);
            }

            // Disallow automatic redirection from secure to non-secure schemes
            if (HttpUtilities.IsSupportedSecureScheme(requestUri.Scheme) && !HttpUtilities.IsSupportedSecureScheme(location.Scheme))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, $"Insecure https to http redirect from {requestUri} to {location} blocked.");
                }

                return(null);
            }

            return(location);
        }
Example #9
0
        private Task <T> GetContentAsync <T>(Uri requestUri, HttpCompletionOption completionOption, T defaultValue,
                                             Func <HttpContent, Task <T> > readAs)
        {
            TaskCompletionSource <T> tcs = new TaskCompletionSource <T>();

            GetAsync(requestUri, completionOption).ContinueWithStandard(requestTask =>
            {
                if (HandleRequestFaultsAndCancelation(requestTask, tcs))
                {
                    return;
                }
                HttpResponseMessage response = requestTask.Result;
                if (response.Content == null)
                {
                    tcs.TrySetResult(defaultValue);
                    return;
                }

                try
                {
                    readAs(response.Content).ContinueWithStandard(contentTask =>
                    {
                        if (!HttpUtilities.HandleFaultsAndCancelation(contentTask, tcs))
                        {
                            tcs.TrySetResult(contentTask.Result);
                        }
                    });
                }
                catch (Exception ex)
                {
                    tcs.TrySetException(ex);
                }
            });

            return(tcs.Task);
        }
Example #10
0
        public Task <Stream> ReadAsStreamAsync()
        {
            CheckDisposed();

            TaskCompletionSource <Stream> tcs = new TaskCompletionSource <Stream>(this);

            if (_contentReadStream == null && IsBuffered)
            {
                byte[] data = this.GetDataBuffer(_bufferedContent);

                // We can cast bufferedContent.Length to 'int' since the length will always be in the 'int' range
                // The .NET Framework doesn't support array lengths > int.MaxValue.
                Debug.Assert(_bufferedContent.Length <= (long)int.MaxValue);
                _contentReadStream = new MemoryStream(data, 0,
                                                      (int)_bufferedContent.Length, false);
            }

            if (_contentReadStream != null)
            {
                tcs.TrySetResult(_contentReadStream);
                return(tcs.Task);
            }

            CreateContentReadStreamAsync().ContinueWithStandard(tcs, (task, state) =>
            {
                var innerTcs  = (TaskCompletionSource <Stream>)state;
                var innerThis = (HttpContent)innerTcs.Task.AsyncState;
                if (!HttpUtilities.HandleFaultsAndCancelation(task, innerTcs))
                {
                    innerThis._contentReadStream = task.Result;
                    innerTcs.TrySetResult(innerThis._contentReadStream);
                }
            });

            return(tcs.Task);
        }
Example #11
0
        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);
        }
Example #12
0
        protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpResponseMessage response;
            uint redirectCount = 0;

            while (true)
            {
                // Just as with WinHttpHandler and CurlHandler, for security reasons, we drop the server credential if it is
                // anything other than a CredentialCache on redirection. We allow credentials in a CredentialCache since they
                // are specifically tied to URIs.
                ICredentials currentCredential = redirectCount > 0 ? _credentials as CredentialCache : _credentials;

                if (currentCredential != null && _preAuthenticate)
                {
                    // Try using previous digest response WWWAuthenticate header
                    if (_digestResponse != null)
                    {
                        await AuthenticationHelper.TrySetDigestAuthToken(request, currentCredential, _digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false);
                    }
                    else
                    {
                        AuthenticationHelper.TrySetBasicAuthToken(request, currentCredential);
                    }
                }

                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

                if (currentCredential != null && !_preAuthenticate && response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    AuthenticationHeaderValue selectedAuth = GetSupportedAuthScheme(response.Headers.WwwAuthenticate);
                    if (selectedAuth != null)
                    {
                        switch (selectedAuth.Scheme)
                        {
                        case AuthenticationHelper.Digest:
                            // Update digest response with new parameter from WWWAuthenticate
                            _digestResponse = new AuthenticationHelper.DigestResponse(selectedAuth.Parameter);
                            if (await AuthenticationHelper.TrySetDigestAuthToken(request, currentCredential, _digestResponse, HttpKnownHeaderNames.Authorization).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.WwwAuthenticate)
                                    {
                                        if (ahv.Scheme == AuthenticationHelper.Digest)
                                        {
                                            _digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter);
                                            if (AuthenticationHelper.IsServerNonceStale(_digestResponse) &&
                                                await AuthenticationHelper.TrySetDigestAuthToken(request, currentCredential, _digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false))
                                            {
                                                response.Dispose();
                                                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                                            }

                                            break;
                                        }
                                    }
                                }
                            }
                            break;

                        case AuthenticationHelper.Basic:
                            if (AuthenticationHelper.TrySetBasicAuthToken(request, currentCredential))
                            {
                                response.Dispose();
                                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                            }
                            break;
                        }
                    }
                }

                if (!RequestNeedsRedirect(response))
                {
                    break;
                }

                // Clear the authorization header, if the request requires redirect.
                request.Headers.Authorization = null;

                Uri location = response.Headers.Location;
                if (location == null)
                {
                    // No location header. Nothing to redirect to.
                    break;
                }

                if (!location.IsAbsoluteUri)
                {
                    location = new Uri(request.RequestUri, location);
                }

                // Disallow automatic redirection from secure to non-secure schemes
                bool allowed =
                    (HttpUtilities.IsSupportedNonSecureScheme(request.RequestUri.Scheme) && HttpUtilities.IsSupportedScheme(location.Scheme)) ||
                    (HttpUtilities.IsSupportedSecureScheme(request.RequestUri.Scheme) && HttpUtilities.IsSupportedSecureScheme(location.Scheme));
                if (!allowed)
                {
                    break;
                }

                redirectCount++;
                if (redirectCount > _maxAutomaticRedirections)
                {
                    throw new HttpRequestException(SR.net_http_max_redirects);
                }

                // Set up for the automatic redirect
                request.RequestUri = location;

                if (RequestRequiresForceGet(response.StatusCode, request.Method))
                {
                    request.Method  = HttpMethod.Get;
                    request.Content = null;
                }

                // Do the redirect.
                response.Dispose();
            }

            return(response);
        }
        private Uri GetUriForRedirect(Uri requestUri, HttpResponseMessage response)
        {
            switch (response.StatusCode)
            {
            case HttpStatusCode.Moved:
            case HttpStatusCode.Found:
            case HttpStatusCode.SeeOther:
            case HttpStatusCode.TemporaryRedirect:
            case HttpStatusCode.MultipleChoices:
            case (HttpStatusCode)308:     // HttpStatusCode.PermanentRedirect
                break;

            default:
                return(null);
            }

            Uri location = response.Headers.Location;

            if (location == null)
            {
                return(null);
            }

            // Ensure the redirect location is an absolute URI.
            if (!location.IsAbsoluteUri)
            {
                location = new Uri(requestUri, location);
            }

            // Per https://tools.ietf.org/html/rfc7231#section-7.1.2, a redirect location without a
            // fragment should inherit the fragment from the original URI.
            string requestFragment = requestUri.Fragment;

            if (!string.IsNullOrEmpty(requestFragment))
            {
                string redirectFragment = location.Fragment;
                if (string.IsNullOrEmpty(redirectFragment))
                {
#if NETSTANDARD2_0
                    // .NET Framework 4.7.2 / 4.8 UriBuilder will always append the fragment marker ('#') to fragment starting with '#',
                    // while .NET Core will only append the fragment marker if not already present.
                    if (requestFragment.StartsWith("#"))
                    {
                        requestFragment = requestFragment.Substring(1);
                    }
#endif
                    location = new UriBuilder(location)
                    {
                        Fragment = requestFragment
                    }.Uri;
                }
            }

            // Disallow automatic redirection from secure to non-secure schemes
            if (HttpUtilities.IsSupportedSecureScheme(requestUri.Scheme) && !HttpUtilities.IsSupportedSecureScheme(location.Scheme))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Error(this, $"Insecure https to http redirect from '{requestUri}' to '{location}' blocked.");
                }

                return(null);
            }

            return(location);
        }
Example #14
0
        public Task <string> ReadAsStringAsync()
        {
            CheckDisposed();

            var tcs = new TaskCompletionSource <string>(this);

            LoadIntoBufferAsync().ContinueWithStandard(tcs, (task, state) =>
            {
                var innerTcs  = (TaskCompletionSource <string>)state;
                var innerThis = (HttpContent)innerTcs.Task.AsyncState;
                if (HttpUtilities.HandleFaultsAndCancelation(task, innerTcs))
                {
                    return;
                }

                if (innerThis._bufferedContent.Length == 0)
                {
                    innerTcs.TrySetResult(string.Empty);
                    return;
                }

                // We don't validate the Content-Encoding header: If the content was encoded, it's the caller's
                // responsibility to make sure to only call ReadAsString() on already decoded content. E.g. if the
                // Content-Encoding is 'gzip' the user should set HttpClientHandler.AutomaticDecompression to get a
                // decoded response stream.

                Encoding encoding = null;
                int bomLength     = -1;

                byte[] data = innerThis.GetDataBuffer(innerThis._bufferedContent);

                int dataLength = (int)innerThis._bufferedContent.Length; // Data is the raw buffer, it may not be full.

                // If we do have encoding information in the 'Content-Type' header, use that information to convert
                // the content to a string.
                if ((innerThis.Headers.ContentType != null) && (innerThis.Headers.ContentType.CharSet != null))
                {
                    try
                    {
                        encoding = Encoding.GetEncoding(innerThis.Headers.ContentType.CharSet);
                    }
                    catch (ArgumentException e)
                    {
                        innerTcs.TrySetException(new InvalidOperationException(SR.net_http_content_invalid_charset, e));
                        return;
                    }
                }

                // If no content encoding is listed in the ContentType HTTP header, or no Content-Type header present,
                // then check for a byte-order-mark (BOM) in the data to figure out the encoding.
                if (encoding == null)
                {
                    byte[] preamble;
                    foreach (Encoding testEncoding in s_encodingsWithBom)
                    {
                        preamble = testEncoding.GetPreamble();
                        if (ByteArrayHasPrefix(data, dataLength, preamble))
                        {
                            encoding  = testEncoding;
                            bomLength = preamble.Length;
                            break;
                        }
                    }
                }

                // Use the default encoding if we couldn't detect one.
                encoding = encoding ?? DefaultStringEncoding;

                // BOM characters may be present even if a charset was specified.
                if (bomLength == -1)
                {
                    byte[] preamble = encoding.GetPreamble();
                    if (ByteArrayHasPrefix(data, dataLength, preamble))
                    {
                        bomLength = preamble.Length;
                    }
                    else
                    {
                        bomLength = 0;
                    }
                }

                try
                {
                    // Drop the BOM when decoding the data.
                    string result = encoding.GetString(data, bomLength, dataLength - bomLength);
                    innerTcs.TrySetResult(result);
                }
                catch (Exception ex)
                {
                    innerTcs.TrySetException(ex);
                }
            });

            return(tcs.Task);
        }
Example #15
0
        protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpResponseMessage response;
            uint redirectCount = 0;

            while (true)
            {
                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

                if (!RequestNeedsRedirect(response))
                {
                    break;
                }

                Uri location = response.Headers.Location;
                if (location == null)
                {
                    // No location header. Nothing to redirect to.
                    break;
                }

                if (!location.IsAbsoluteUri)
                {
                    location = new Uri(request.RequestUri, location);
                }

                // Disallow automatic redirection from secure to non-secure schemes
                bool allowed =
                    (HttpUtilities.IsSupportedNonSecureScheme(request.RequestUri.Scheme) && HttpUtilities.IsSupportedScheme(location.Scheme)) ||
                    (HttpUtilities.IsSupportedSecureScheme(request.RequestUri.Scheme) && HttpUtilities.IsSupportedSecureScheme(location.Scheme));
                if (!allowed)
                {
                    break;
                }

                redirectCount++;
                if (redirectCount > _maxAutomaticRedirections)
                {
                    throw new HttpRequestException(SR.net_http_max_redirects);
                }

                // Set up for the automatic redirect
                request.RequestUri = location;

                if (RequestRequiresForceGet(response.StatusCode, request.Method))
                {
                    request.Method  = HttpMethod.Get;
                    request.Content = null;
                }

                // Do the redirect.
                response.Dispose();
            }

            return(response);
        }
Example #16
0
        private HttpConnectionKey GetConnectionKey(HttpRequestMessage request, Uri?proxyUri, bool isProxyConnect)
        {
            Uri?uri = request.RequestUri;

            Debug.Assert(uri != null);

            if (isProxyConnect)
            {
                Debug.Assert(uri == proxyUri);
                return(new HttpConnectionKey(HttpConnectionKind.ProxyConnect, uri.IdnHost, uri.Port, null, proxyUri, GetIdentityIfDefaultCredentialsUsed(_settings._defaultCredentialsUsedForProxy)));
            }

            string?sslHostName = null;

            if (HttpUtilities.IsSupportedSecureScheme(uri.Scheme))
            {
                string?hostHeader = request.Headers.Host;
                if (hostHeader != null)
                {
                    sslHostName = ParseHostNameFromHeader(hostHeader);
                }
                else
                {
                    // No explicit Host header.  Use host from uri.
                    sslHostName = uri.IdnHost;
                }
            }

            string identity = GetIdentityIfDefaultCredentialsUsed(proxyUri != null ? _settings._defaultCredentialsUsedForProxy : _settings._defaultCredentialsUsedForServer);

            if (proxyUri != null)
            {
                Debug.Assert(HttpUtilities.IsSupportedNonSecureScheme(proxyUri.Scheme));
                if (sslHostName == null)
                {
                    if (HttpUtilities.IsNonSecureWebSocketScheme(uri.Scheme))
                    {
                        // Non-secure websocket connection through proxy to the destination.
                        return(new HttpConnectionKey(HttpConnectionKind.ProxyTunnel, uri.IdnHost, uri.Port, null, proxyUri, identity));
                    }
                    else
                    {
                        // Standard HTTP proxy usage for non-secure requests
                        // The destination host and port are ignored here, since these connections
                        // will be shared across any requests that use the proxy.
                        return(new HttpConnectionKey(HttpConnectionKind.Proxy, null, 0, null, proxyUri, identity));
                    }
                }
                else
                {
                    // Tunnel SSL connection through proxy to the destination.
                    return(new HttpConnectionKey(HttpConnectionKind.SslProxyTunnel, uri.IdnHost, uri.Port, sslHostName, proxyUri, identity));
                }
            }
            else if (sslHostName != null)
            {
                return(new HttpConnectionKey(HttpConnectionKind.Https, uri.IdnHost, uri.Port, sslHostName, null, identity));
            }
            else
            {
                return(new HttpConnectionKey(HttpConnectionKind.Http, uri.IdnHost, uri.Port, null, null, identity));
            }
        }
Example #17
0
 static bool IsAllowedAbsoluteUri(Uri requestUri)
 {
     return(!requestUri.IsAbsoluteUri || HttpUtilities.IsHttpUri(requestUri));
 }
 /// <summary>
 /// Gets the proxy URI. (iWebProxy interface)
 /// </summary>
 public Uri?GetProxy(Uri uri)
 {
     return(HttpUtilities.IsSupportedNonSecureScheme(uri.Scheme) ? _httpProxyUri : _httpsProxyUri);
 }
        private static HttpConnectionKey GetConnectionKey(HttpRequestMessage request, Uri proxyUri, bool isProxyConnect)
        {
            Uri uri = request.RequestUri;

            // If the hostname is an IPv6 address, uri.IdnHost will return the address without enclosing [].
            // In this case, use uri.Host instead, which will correctly enclose with [].
            // Note we don't need punycode encoding if it's an IP address, so using uri.Host is fine.
            bool isIPv6Address = uri.HostNameType == UriHostNameType.IPv6;

            if (isProxyConnect)
            {
                Debug.Assert(uri == proxyUri);
                return(new HttpConnectionKey(HttpConnectionKind.ProxyConnect, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, null, proxyUri));
            }

            string sslHostName = null;

            if (HttpUtilities.IsSupportedSecureScheme(uri.Scheme))
            {
                string hostHeader = request.Headers.Host;
                if (hostHeader != null)
                {
                    sslHostName = ParseHostNameFromHeader(hostHeader);
                }
                else
                {
                    // No explicit Host header.  Use host from uri.
                    sslHostName = uri.IdnHost;
                }
            }

            if (proxyUri != null)
            {
                Debug.Assert(HttpUtilities.IsSupportedNonSecureScheme(proxyUri.Scheme));
                if (sslHostName == null)
                {
                    if (HttpUtilities.IsNonSecureWebSocketScheme(uri.Scheme))
                    {
                        // Non-secure websocket connection through proxy to the destination.
                        return(new HttpConnectionKey(HttpConnectionKind.ProxyTunnel, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, null, proxyUri));
                    }
                    else
                    {
                        // Standard HTTP proxy usage for non-secure requests
                        // The destination host and port are ignored here, since these connections
                        // will be shared across any requests that use the proxy.
                        return(new HttpConnectionKey(HttpConnectionKind.Proxy, null, 0, null, proxyUri));
                    }
                }
                else
                {
                    // Tunnel SSL connection through proxy to the destination.
                    return(new HttpConnectionKey(HttpConnectionKind.SslProxyTunnel, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, sslHostName, proxyUri));
                }
            }
            else if (sslHostName != null)
            {
                return(new HttpConnectionKey(HttpConnectionKind.Https, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, sslHostName, null));
            }
            else
            {
                return(new HttpConnectionKey(HttpConnectionKind.Http, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, null, null));
            }
        }