| File: HttpConnectionFactory.cs | Web Access |
| Project: src\aspnetcore\src\SignalR\clients\csharp\Http.Connections.Client\src\Microsoft.AspNetCore.Http.Connections.Client.csproj (Microsoft.AspNetCore.Http.Connections.Client) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Net; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Shared; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Http.Connections.Client; /// <summary> /// A factory for creating <see cref="HttpConnection"/> instances. /// </summary> public class HttpConnectionFactory : IConnectionFactory { private readonly HttpConnectionOptions _httpConnectionOptions; private readonly ILoggerFactory _loggerFactory; /// <summary> /// Initializes a new instance of the <see cref="HttpConnectionFactory"/> class. /// </summary> /// <param name="options">The connection options.</param> /// <param name="loggerFactory">The logger factory.</param> public HttpConnectionFactory(IOptions<HttpConnectionOptions> options, ILoggerFactory loggerFactory) { ArgumentNullThrowHelper.ThrowIfNull(options); _httpConnectionOptions = options.Value; _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); } /// <summary> /// Creates a new connection to an <see cref="UriEndPoint"/>. /// </summary> /// <param name="endPoint">The <see cref="UriEndPoint"/> to connect to.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param> /// <returns> /// A <see cref="ValueTask{TResult}" /> that represents the asynchronous connect, yielding the <see cref="ConnectionContext" /> for the new connection when completed. /// </returns> public async ValueTask<ConnectionContext> ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken = default) { ArgumentNullThrowHelper.ThrowIfNull(endPoint); if (!(endPoint is UriEndPoint uriEndPoint)) { throw new NotSupportedException($"The provided {nameof(EndPoint)} must be of type {nameof(UriEndPoint)}."); } if (_httpConnectionOptions.Url != null && _httpConnectionOptions.Url != uriEndPoint.Uri) { throw new InvalidOperationException($"If {nameof(HttpConnectionOptions)}.{nameof(HttpConnectionOptions.Url)} was set, it must match the {nameof(UriEndPoint)}.{nameof(UriEndPoint.Uri)} passed to {nameof(ConnectAsync)}."); } // Shallow copy before setting the Url property so we don't mutate the user-defined options object. var shallowCopiedOptions = ShallowCopyHttpConnectionOptions(_httpConnectionOptions); shallowCopiedOptions.Url = uriEndPoint.Uri; var connection = new HttpConnection(shallowCopiedOptions, _loggerFactory); try { await connection.StartAsync(cancellationToken).ConfigureAwait(false); return connection; } catch { // Make sure the connection is disposed, in case it allocated any resources before failing. await connection.DisposeAsync().ConfigureAwait(false); throw; } } // Internal for testing internal static HttpConnectionOptions ShallowCopyHttpConnectionOptions(HttpConnectionOptions options) { var newOptions = new HttpConnectionOptions { HttpMessageHandlerFactory = options.HttpMessageHandlerFactory, Headers = options.Headers, Url = options.Url, Transports = options.Transports, SkipNegotiation = options.SkipNegotiation, AccessTokenProvider = options.AccessTokenProvider, CloseTimeout = options.CloseTimeout, DefaultTransferFormat = options.DefaultTransferFormat, ApplicationMaxBufferSize = options.ApplicationMaxBufferSize, TransportMaxBufferSize = options.TransportMaxBufferSize, UseStatefulReconnect = options.UseStatefulReconnect, WebSocketFactory = options.WebSocketFactory, }; if (!OperatingSystem.IsBrowser()) { newOptions.Cookies = options.Cookies; newOptions.ClientCertificates = options.ClientCertificates; newOptions.Credentials = options.Credentials; newOptions.Proxy = options.Proxy; newOptions.UseDefaultCredentials = options.UseDefaultCredentials; newOptions.WebSocketConfiguration = options.WebSocketConfiguration; } return newOptions; } }