diff --git a/samples/ClientSample/RawSample.cs b/samples/ClientSample/RawSample.cs index ca04f50caf..7674740272 100644 --- a/samples/ClientSample/RawSample.cs +++ b/samples/ClientSample/RawSample.cs @@ -33,10 +33,8 @@ namespace ClientSample { baseUrl = string.IsNullOrEmpty(baseUrl) ? "http://localhost:5000/chat" : baseUrl; - var loggerFactory = new LoggerFactory(); - Console.WriteLine($"Connecting to {baseUrl}..."); - var connection = new HttpConnection(new Uri(baseUrl), loggerFactory); + var connection = new HttpConnection(new Uri(baseUrl)); try { await connection.StartAsync(TransferFormat.Text); diff --git a/src/Microsoft.AspNetCore.Http.Connections.Client/DefaultTransportFactory.cs b/src/Microsoft.AspNetCore.Http.Connections.Client/DefaultTransportFactory.cs index afaa72affc..b8f8346da1 100644 --- a/src/Microsoft.AspNetCore.Http.Connections.Client/DefaultTransportFactory.cs +++ b/src/Microsoft.AspNetCore.Http.Connections.Client/DefaultTransportFactory.cs @@ -13,12 +13,12 @@ namespace Microsoft.AspNetCore.Http.Connections.Client public class DefaultTransportFactory : ITransportFactory { private readonly HttpClient _httpClient; - private readonly HttpOptions _httpOptions; + private readonly HttpConnectionOptions _httpConnectionOptions; private readonly HttpTransportType _requestedTransportType; private readonly ILoggerFactory _loggerFactory; private static volatile bool _websocketsSupported = true; - public DefaultTransportFactory(HttpTransportType requestedTransportType, ILoggerFactory loggerFactory, HttpClient httpClient, HttpOptions httpOptions) + public DefaultTransportFactory(HttpTransportType requestedTransportType, ILoggerFactory loggerFactory, HttpClient httpClient, HttpConnectionOptions httpConnectionOptions) { if (httpClient == null && requestedTransportType != HttpTransportType.WebSockets) { @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Client _requestedTransportType = requestedTransportType; _loggerFactory = loggerFactory; _httpClient = httpClient; - _httpOptions = httpOptions; + _httpConnectionOptions = httpConnectionOptions; } public ITransport CreateTransport(HttpTransportType availableServerTransports) @@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Client { try { - return new WebSocketsTransport(_httpOptions, _loggerFactory); + return new WebSocketsTransport(_httpConnectionOptions, _loggerFactory); } catch (PlatformNotSupportedException) { diff --git a/src/Microsoft.AspNetCore.Http.Connections.Client/HttpConnection.cs b/src/Microsoft.AspNetCore.Http.Connections.Client/HttpConnection.cs index e124bc78b7..cc4ad8275e 100644 --- a/src/Microsoft.AspNetCore.Http.Connections.Client/HttpConnection.cs +++ b/src/Microsoft.AspNetCore.Http.Connections.Client/HttpConnection.cs @@ -34,17 +34,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Client private bool _disposed; private readonly HttpClient _httpClient; - private readonly HttpOptions _httpOptions; + private readonly HttpConnectionOptions _httpConnectionOptions; private ITransport _transport; private readonly ITransportFactory _transportFactory; private string _connectionId; - private readonly HttpTransportType _requestedTransports; private readonly ConnectionLogScope _logScope; private readonly IDisposable _scopeDisposable; private readonly ILoggerFactory _loggerFactory; - public Uri Url { get; } - public override IDuplexPipe Transport { get @@ -72,48 +69,49 @@ namespace Microsoft.AspNetCore.Http.Connections.Client { } - public HttpConnection(Uri url, ILoggerFactory loggerFactory) - : this(url, HttpTransports.All, loggerFactory, httpOptions: null) - { - } - public HttpConnection(Uri url, HttpTransportType transports, ILoggerFactory loggerFactory) - : this(url, transports, loggerFactory, httpOptions: null) + : this(CreateHttpOptions(url, transports), loggerFactory) { } - public HttpConnection(Uri url, HttpTransportType transports, ILoggerFactory loggerFactory, HttpOptions httpOptions) + private static HttpConnectionOptions CreateHttpOptions(Uri url, HttpTransportType transports) { - Url = url ?? throw new ArgumentNullException(nameof(url)); + if (url == null) + { + throw new ArgumentNullException(nameof(url)); + } + return new HttpConnectionOptions { Url = url, Transports = transports }; + } + + public HttpConnection(HttpConnectionOptions httpConnectionOptions, ILoggerFactory loggerFactory) + { + if (httpConnectionOptions.Url == null) + { + throw new ArgumentException("Options does not have a URL specified.", nameof(httpConnectionOptions)); + } + _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; _logger = _loggerFactory.CreateLogger(); - _httpOptions = httpOptions; + _httpConnectionOptions = httpConnectionOptions; - _requestedTransports = transports; - if (_requestedTransports != HttpTransportType.WebSockets) + if (httpConnectionOptions.Transports != HttpTransportType.WebSockets) { _httpClient = CreateHttpClient(); } - _transportFactory = new DefaultTransportFactory(transports, _loggerFactory, _httpClient, httpOptions); + _transportFactory = new DefaultTransportFactory(httpConnectionOptions.Transports, _loggerFactory, _httpClient, httpConnectionOptions); _logScope = new ConnectionLogScope(); _scopeDisposable = _logger.BeginScope(_logScope); } - public HttpConnection(Uri url, ITransportFactory transportFactory, ILoggerFactory loggerFactory, HttpOptions httpOptions) + // Used by unit tests + internal HttpConnection(HttpConnectionOptions httpConnectionOptions, ILoggerFactory loggerFactory, ITransportFactory transportFactory) + : this(httpConnectionOptions, loggerFactory) { - Url = url ?? throw new ArgumentNullException(nameof(url)); - _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; - _logger = _loggerFactory.CreateLogger(); - _httpOptions = httpOptions; - _httpClient = CreateHttpClient(); - _requestedTransports = HttpTransports.All; - _transportFactory = transportFactory ?? throw new ArgumentNullException(nameof(transportFactory)); - _logScope = new ConnectionLogScope(); - _scopeDisposable = _logger.BeginScope(_logScope); + _transportFactory = transportFactory; } - + public async Task StartAsync(TransferFormat transferFormat) { await StartAsyncCore(transferFormat).ForceAsync(); @@ -204,17 +202,17 @@ namespace Microsoft.AspNetCore.Http.Connections.Client private async Task SelectAndStartTransport(TransferFormat transferFormat) { - if (_requestedTransports == HttpTransportType.WebSockets) + if (_httpConnectionOptions.Transports == HttpTransportType.WebSockets) { - Log.StartingTransport(_logger, _requestedTransports, Url); - await StartTransport(Url, _requestedTransports, transferFormat); + Log.StartingTransport(_logger, _httpConnectionOptions.Transports, _httpConnectionOptions.Url); + await StartTransport(_httpConnectionOptions.Url, _httpConnectionOptions.Transports, transferFormat); } else { var negotiationResponse = await GetNegotiationResponse(); // This should only need to happen once - var connectUrl = CreateConnectUrl(Url, negotiationResponse.ConnectionId); + var connectUrl = CreateConnectUrl(_httpConnectionOptions.Url, negotiationResponse.ConnectionId); // We're going to search for the transfer format as a string because we don't want to parse // all the transfer formats in the negotiation response, and we want to allow transfer formats @@ -237,7 +235,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Client try { - if ((transportType & _requestedTransports) == 0) + if ((transportType & _httpConnectionOptions.Transports) == 0) { Log.TransportDisabledByClient(_logger, transportType); } @@ -251,7 +249,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Client if (negotiationResponse == null) { negotiationResponse = await GetNegotiationResponse(); - connectUrl = CreateConnectUrl(Url, negotiationResponse.ConnectionId); + connectUrl = CreateConnectUrl(_httpConnectionOptions.Url, negotiationResponse.ConnectionId); } Log.StartingTransport(_logger, transportType, connectUrl); @@ -362,33 +360,33 @@ namespace Microsoft.AspNetCore.Http.Connections.Client var httpClientHandler = new HttpClientHandler(); HttpMessageHandler httpMessageHandler = httpClientHandler; - if (_httpOptions != null) + if (_httpConnectionOptions != null) { - if (_httpOptions.Proxy != null) + if (_httpConnectionOptions.Proxy != null) { - httpClientHandler.Proxy = _httpOptions.Proxy; + httpClientHandler.Proxy = _httpConnectionOptions.Proxy; } - if (_httpOptions.Cookies != null) + if (_httpConnectionOptions.Cookies != null) { - httpClientHandler.CookieContainer = _httpOptions.Cookies; + httpClientHandler.CookieContainer = _httpConnectionOptions.Cookies; } - if (_httpOptions.ClientCertificates != null) + if (_httpConnectionOptions.ClientCertificates != null) { - httpClientHandler.ClientCertificates.AddRange(_httpOptions.ClientCertificates); + httpClientHandler.ClientCertificates.AddRange(_httpConnectionOptions.ClientCertificates); } - if (_httpOptions.UseDefaultCredentials != null) + if (_httpConnectionOptions.UseDefaultCredentials != null) { - httpClientHandler.UseDefaultCredentials = _httpOptions.UseDefaultCredentials.Value; + httpClientHandler.UseDefaultCredentials = _httpConnectionOptions.UseDefaultCredentials.Value; } - if (_httpOptions.Credentials != null) + if (_httpConnectionOptions.Credentials != null) { - httpClientHandler.Credentials = _httpOptions.Credentials; + httpClientHandler.Credentials = _httpConnectionOptions.Credentials; } httpMessageHandler = httpClientHandler; - if (_httpOptions.HttpMessageHandlerFactory != null) + if (_httpConnectionOptions.HttpMessageHandlerFactory != null) { - httpMessageHandler = _httpOptions.HttpMessageHandlerFactory(httpClientHandler); + httpMessageHandler = _httpConnectionOptions.HttpMessageHandlerFactory(httpClientHandler); if (httpMessageHandler == null) { throw new InvalidOperationException("Configured HttpMessageHandlerFactory did not return a value."); @@ -396,9 +394,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Client } // Apply the authorization header in a handler instead of a default header because it can change with each request - if (_httpOptions.AccessTokenFactory != null) + if (_httpConnectionOptions.AccessTokenFactory != null) { - httpMessageHandler = new AccessTokenHttpMessageHandler(httpMessageHandler, _httpOptions.AccessTokenFactory); + httpMessageHandler = new AccessTokenHttpMessageHandler(httpMessageHandler, _httpConnectionOptions.AccessTokenFactory); } } @@ -411,10 +409,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Client // Start with the user agent header httpClient.DefaultRequestHeaders.UserAgent.Add(Constants.UserAgentHeader); - // Apply any headers configured on the HttpOptions - if (_httpOptions?.Headers != null) + // Apply any headers configured on the HttpConnectionOptions + if (_httpConnectionOptions?.Headers != null) { - foreach (var header in _httpOptions.Headers) + foreach (var header in _httpConnectionOptions.Headers) { httpClient.DefaultRequestHeaders.Add(header.Key, header.Value); } @@ -457,7 +455,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Client private async Task GetNegotiationResponse() { - var negotiationResponse = await Negotiate(Url, _httpClient, _logger); + var negotiationResponse = await Negotiate(_httpConnectionOptions.Url, _httpClient, _logger); _connectionId = negotiationResponse.ConnectionId; _logScope.ConnectionId = _connectionId; return negotiationResponse; diff --git a/src/Microsoft.AspNetCore.Http.Connections.Client/HttpOptions.cs b/src/Microsoft.AspNetCore.Http.Connections.Client/HttpConnectionOptions.cs similarity index 56% rename from src/Microsoft.AspNetCore.Http.Connections.Client/HttpOptions.cs rename to src/Microsoft.AspNetCore.Http.Connections.Client/HttpConnectionOptions.cs index 38cea6822c..285cb21dde 100644 --- a/src/Microsoft.AspNetCore.Http.Connections.Client/HttpOptions.cs +++ b/src/Microsoft.AspNetCore.Http.Connections.Client/HttpConnectionOptions.cs @@ -8,23 +8,54 @@ using System.Net.Http; using System.Net.WebSockets; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http.Connections.Internal; namespace Microsoft.AspNetCore.Http.Connections.Client { - public class HttpOptions + public class HttpConnectionOptions { + private IDictionary _headers; + private X509CertificateCollection _clientCertificates; + private CookieContainer _cookies; + + public HttpConnectionOptions() + { + _headers = new Dictionary(); + _clientCertificates = new X509CertificateCollection(); + _cookies = new CookieContainer(); + + Transports = HttpTransports.All; + } + /// /// Gets or sets a delegate for wrapping or replacing the /// that will make HTTP requests the server. /// public Func HttpMessageHandlerFactory { get; set; } - public IReadOnlyCollection> Headers { get; set; } + public IDictionary Headers + { + get => _headers; + set => _headers = value ?? throw new ArgumentNullException(nameof(value)); + } + + public X509CertificateCollection ClientCertificates + { + get => _clientCertificates; + set => _clientCertificates = value ?? throw new ArgumentNullException(nameof(value)); + } + + public CookieContainer Cookies + { + get => _cookies; + set => _cookies = value ?? throw new ArgumentNullException(nameof(value)); + } + + public Uri Url { get; set; } + public HttpTransportType Transports { get; set; } public Func> AccessTokenFactory { get; set; } public TimeSpan CloseTimeout { get; set; } = TimeSpan.FromSeconds(5); public ICredentials Credentials { get; set; } - public X509CertificateCollection ClientCertificates { get; set; } = new X509CertificateCollection(); - public CookieContainer Cookies { get; set; } = new CookieContainer(); public IWebProxy Proxy { get; set; } public bool? UseDefaultCredentials { get; set; } diff --git a/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/WebSocketsTransport.cs b/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/WebSocketsTransport.cs index 4a3930180a..b1ce55b776 100644 --- a/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/WebSocketsTransport.cs +++ b/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/WebSocketsTransport.cs @@ -37,56 +37,56 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal { } - public WebSocketsTransport(HttpOptions httpOptions, ILoggerFactory loggerFactory) + public WebSocketsTransport(HttpConnectionOptions httpConnectionOptions, ILoggerFactory loggerFactory) { _webSocket = new ClientWebSocket(); // Issue in ClientWebSocket prevents user-agent being set - https://github.com/dotnet/corefx/issues/26627 //_webSocket.Options.SetRequestHeader("User-Agent", Constants.UserAgentHeader.ToString()); - if (httpOptions != null) + if (httpConnectionOptions != null) { - if (httpOptions.Headers != null) + if (httpConnectionOptions.Headers != null) { - foreach (var header in httpOptions.Headers) + foreach (var header in httpConnectionOptions.Headers) { _webSocket.Options.SetRequestHeader(header.Key, header.Value); } } - if (httpOptions.Cookies != null) + if (httpConnectionOptions.Cookies != null) { - _webSocket.Options.Cookies = httpOptions.Cookies; + _webSocket.Options.Cookies = httpConnectionOptions.Cookies; } - if (httpOptions.ClientCertificates != null) + if (httpConnectionOptions.ClientCertificates != null) { - _webSocket.Options.ClientCertificates.AddRange(httpOptions.ClientCertificates); + _webSocket.Options.ClientCertificates.AddRange(httpConnectionOptions.ClientCertificates); } - if (httpOptions.Credentials != null) + if (httpConnectionOptions.Credentials != null) { - _webSocket.Options.Credentials = httpOptions.Credentials; + _webSocket.Options.Credentials = httpConnectionOptions.Credentials; } - if (httpOptions.Proxy != null) + if (httpConnectionOptions.Proxy != null) { - _webSocket.Options.Proxy = httpOptions.Proxy; + _webSocket.Options.Proxy = httpConnectionOptions.Proxy; } - if (httpOptions.UseDefaultCredentials != null) + if (httpConnectionOptions.UseDefaultCredentials != null) { - _webSocket.Options.UseDefaultCredentials = httpOptions.UseDefaultCredentials.Value; + _webSocket.Options.UseDefaultCredentials = httpConnectionOptions.UseDefaultCredentials.Value; } - if (httpOptions.AccessTokenFactory != null) + if (httpConnectionOptions.AccessTokenFactory != null) { - _accessTokenFactory = httpOptions.AccessTokenFactory; + _accessTokenFactory = httpConnectionOptions.AccessTokenFactory; } - httpOptions.WebSocketOptions?.Invoke(_webSocket.Options); + httpConnectionOptions.WebSocketOptions?.Invoke(_webSocket.Options); - _closeTimeout = httpOptions.CloseTimeout; + _closeTimeout = httpConnectionOptions.CloseTimeout; } // Set this header so the server auth middleware will set an Unauthorized instead of Redirect status code diff --git a/src/Microsoft.AspNetCore.Http.Connections.Client/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Http.Connections.Client/Properties/AssemblyInfo.cs index 53146da3b6..9befa2be56 100644 --- a/src/Microsoft.AspNetCore.Http.Connections.Client/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.Http.Connections.Client/Properties/AssemblyInfo.cs @@ -3,5 +3,6 @@ using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.SignalR.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.SignalR.Client.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.SignalR.Microbenchmarks, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SignalR.Client/HttpConnectionFactory.cs b/src/Microsoft.AspNetCore.SignalR.Client/HttpConnectionFactory.cs index 0a75164db4..519e82f710 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client/HttpConnectionFactory.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client/HttpConnectionFactory.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.ObjectModel; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections.Client; @@ -13,7 +12,7 @@ namespace Microsoft.AspNetCore.SignalR.Client { public class HttpConnectionFactory : IConnectionFactory { - private readonly HttpConnectionOptions _options; + private readonly HttpConnectionOptions _httpConnectionOptions; private readonly ILoggerFactory _loggerFactory; public HttpConnectionFactory(IOptions options, ILoggerFactory loggerFactory) @@ -28,28 +27,15 @@ namespace Microsoft.AspNetCore.SignalR.Client throw new ArgumentNullException(nameof(loggerFactory)); } - _options = options.Value; + _httpConnectionOptions = options.Value; _loggerFactory = loggerFactory; } public async Task ConnectAsync(TransferFormat transferFormat) { - var httpOptions = new HttpOptions - { - HttpMessageHandlerFactory = _options.MessageHandlerFactory, - Headers = _options._headers != null ? new ReadOnlyDictionary(_options._headers) : null, - AccessTokenFactory = _options.AccessTokenFactory, - WebSocketOptions = _options.WebSocketOptions, - Cookies = _options._cookies, - Proxy = _options.Proxy, - UseDefaultCredentials = _options.UseDefaultCredentials, - ClientCertificates = _options._clientCertificates, - Credentials = _options.Credentials, - }; - - var connection = new HttpConnection(_options.Url, _options.Transports, _loggerFactory, httpOptions); + var connection = new HttpConnection(_httpConnectionOptions, _loggerFactory); await connection.StartAsync(transferFormat); return connection; } } -} +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SignalR.Client/HttpConnectionOptions.cs b/src/Microsoft.AspNetCore.SignalR.Client/HttpConnectionOptions.cs deleted file mode 100644 index b1a938c401..0000000000 --- a/src/Microsoft.AspNetCore.SignalR.Client/HttpConnectionOptions.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Net.WebSockets; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http.Connections; -using Microsoft.AspNetCore.Http.Connections.Internal; - -namespace Microsoft.AspNetCore.SignalR.Client -{ - public class HttpConnectionOptions - { - internal X509CertificateCollection _clientCertificates; - internal IDictionary _headers; - internal CookieContainer _cookies; - - public HttpConnectionOptions() - { - Transports = HttpTransports.All; - } - - public Uri Url { get; set; } - public HttpTransportType Transports { get; set; } - public Func MessageHandlerFactory { get; set; } - public bool? UseDefaultCredentials { get; set; } - public ICredentials Credentials { get; set; } - public IWebProxy Proxy { get; set; } - public Func> AccessTokenFactory { get; set; } - public Action WebSocketOptions { get; set; } - - public X509CertificateCollection ClientCertificates - { - get - { - if (_clientCertificates == null) - { - _clientCertificates = new X509CertificateCollection(); - } - - return _clientCertificates; - } - } - - public CookieContainer Cookies - { - get - { - if (_cookies == null) - { - _cookies = new CookieContainer(); - } - - return _cookies; - } - } - - public IDictionary Headers - { - get - { - if (_headers == null) - { - _headers = new Dictionary(StringComparer.Ordinal); - } - - return _headers; - } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SignalR.Client/HubConnectionBuilderHttpExtensions.cs b/src/Microsoft.AspNetCore.SignalR.Client/HubConnectionBuilderHttpExtensions.cs index ad797e5de2..624b00f22c 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client/HubConnectionBuilderHttpExtensions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client/HubConnectionBuilderHttpExtensions.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Http.Connections; +using Microsoft.AspNetCore.Http.Connections.Client; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.SignalR.Client diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.ConnectionLifecycle.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.ConnectionLifecycle.cs index 1d7ef85ac8..e60b3e6f1a 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.ConnectionLifecycle.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.ConnectionLifecycle.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections.Client; using Microsoft.AspNetCore.Http.Connections.Client.Internal; +using Microsoft.AspNetCore.Http.Connections.Internal; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.Extensions.Logging.Testing; using Xunit; @@ -115,6 +116,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests await WithConnectionAsync( CreateConnection( loggerFactory: loggerFactory, + transportType: HttpTransports.All, transport: new TestTransport(onTransportStart: OnTransportStart)), async (connection) => { @@ -142,6 +144,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests await WithConnectionAsync( CreateConnection( loggerFactory: loggerFactory, + transportType: HttpTransports.All, transport: new TestTransport(onTransportStart: OnTransportStart)), async (connection) => { @@ -318,7 +321,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests var sse = new ServerSentEventsTransport(new HttpClient(httpHandler)); await WithConnectionAsync( - CreateConnection(httpHandler, loggerFactory: loggerFactory, url: null, transport: sse), + CreateConnection(httpHandler, loggerFactory: loggerFactory, transport: sse), async (connection) => { await Assert.ThrowsAsync( @@ -344,7 +347,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests var sse = new ServerSentEventsTransport(new HttpClient(httpHandler)); await WithConnectionAsync( - CreateConnection(httpHandler, loggerFactory: loggerFactory, url: null, transport: sse), + CreateConnection(httpHandler, loggerFactory: loggerFactory, transport: sse), async (connection) => { var startTask = connection.StartAsync(TransferFormat.Text).OrTimeout(); diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.Helpers.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.Helpers.cs index aba4998f42..99f915e0a3 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.Helpers.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.Helpers.cs @@ -20,34 +20,39 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests string url = null, ITransport transport = null, ITransportFactory transportFactory = null, - HttpTransportType transportType = HttpTransportType.LongPolling, + HttpTransportType? transportType = null, Func> accessTokenFactory = null) { - var httpOptions = new HttpOptions + var httpOptions = new HttpConnectionOptions { + Transports = transportType ?? HttpTransportType.LongPolling, HttpMessageHandlerFactory = (httpMessageHandler) => httpHandler ?? TestHttpMessageHandler.CreateDefault(), AccessTokenFactory = accessTokenFactory, }; + if (url != null) + { + httpOptions.Url = new Uri(url); + } - return CreateConnection(httpOptions, loggerFactory, url, transport, transportFactory, transportType); + return CreateConnection(httpOptions, loggerFactory, transport, transportFactory); } - private static HttpConnection CreateConnection(HttpOptions httpOptions, ILoggerFactory loggerFactory = null, string url = null, ITransport transport = null, ITransportFactory transportFactory = null, HttpTransportType transportType = HttpTransportType.LongPolling) + private static HttpConnection CreateConnection(HttpConnectionOptions httpConnectionOptions, ILoggerFactory loggerFactory = null, ITransport transport = null, ITransportFactory transportFactory = null) { loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; - var uri = new Uri(url ?? "http://fakeuri.org/"); + httpConnectionOptions.Url = httpConnectionOptions.Url ?? new Uri("http://fakeuri.org/"); if (transportFactory != null) { - return new HttpConnection(uri, transportFactory, loggerFactory, httpOptions); + return new HttpConnection(httpConnectionOptions, loggerFactory, transportFactory); } else if (transport != null) { - return new HttpConnection(uri, new TestTransportFactory(transport), loggerFactory, httpOptions); + return new HttpConnection(httpConnectionOptions, loggerFactory, new TestTransportFactory(transport)); } else { - return new HttpConnection(uri, transportType, loggerFactory, httpOptions); + return new HttpConnection(httpConnectionOptions, loggerFactory); } } diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.cs index 0136e05956..cb8bb48daf 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.cs @@ -32,10 +32,10 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests } [Fact] - public void ConnectionReturnsUrlUsedToStartTheConnection() + public void CannotCreateConnectionWithNullUrlOnOptions() { - var connectionUrl = new Uri("http://fakeuri.org/"); - Assert.Equal(connectionUrl, new HttpConnection(connectionUrl).Url); + var exception = Assert.Throws(() => new HttpConnection(new HttpConnectionOptions(), NullLoggerFactory.Instance)); + Assert.Equal("httpConnectionOptions", exception.ParamName); } [Fact] @@ -53,7 +53,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests HttpClientHandler httpClientHandler = null; - var httpOptions = new HttpOptions(); + var httpOptions = new HttpConnectionOptions(); + httpOptions.Url = new Uri("http://fakeuri.org/"); httpOptions.HttpMessageHandlerFactory = inner => { httpClientHandler = (HttpClientHandler)inner; @@ -65,9 +66,10 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests httpOptions.UseDefaultCredentials = false; httpOptions.Credentials = Mock.Of(); httpOptions.Proxy = Mock.Of(); + httpOptions.Transports = HttpTransportType.LongPolling; await WithConnectionAsync( - CreateConnection(httpOptions, url: "http://fakeuri.org/"), + CreateConnection(httpOptions), async (connection) => { await connection.StartAsync(TransferFormat.Text).OrTimeout(); @@ -89,7 +91,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests testHttpHandler.OnNegotiate((request, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.BadGateway)); - var httpOptions = new HttpOptions(); + var httpOptions = new HttpConnectionOptions(); + httpOptions.Url = new Uri("http://fakeuri.org/"); httpOptions.HttpMessageHandlerFactory = inner => testHttpHandler; const string loggerName = "Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler"; @@ -104,7 +107,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests try { await WithConnectionAsync( - CreateConnection(httpOptions, loggerFactory: mockLoggerFactory.Object, url: "http://fakeuri.org/"), + CreateConnection(httpOptions, loggerFactory: mockLoggerFactory.Object), async (connection) => { await connection.StartAsync(TransferFormat.Text).OrTimeout(); diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionBuilderExtensionsTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionBuilderExtensionsTests.cs index 6070c193ff..0f41c04c04 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionBuilderExtensionsTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionBuilderExtensionsTests.cs @@ -4,6 +4,7 @@ using System; using System.Net; using Microsoft.AspNetCore.Http.Connections; +using Microsoft.AspNetCore.Http.Connections.Client; using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/DefaultTransportFactoryTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/DefaultTransportFactoryTests.cs index 965034f020..2cb7b0a835 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/DefaultTransportFactoryTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/DefaultTransportFactoryTests.cs @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [InlineData((HttpTransportType)int.MaxValue)] public void DefaultTransportFactoryCanBeCreatedWithNoOrUnknownTransportTypeFlags(HttpTransportType transportType) { - Assert.NotNull(new DefaultTransportFactory(transportType, new LoggerFactory(), new HttpClient(), httpOptions: null)); + Assert.NotNull(new DefaultTransportFactory(transportType, new LoggerFactory(), new HttpClient(), httpConnectionOptions: null)); } [Theory] @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public void DefaultTransportFactoryCannotBeCreatedWithoutHttpClient(HttpTransportType transportType) { var exception = Assert.Throws( - () => new DefaultTransportFactory(transportType, new LoggerFactory(), httpClient: null, httpOptions: null)); + () => new DefaultTransportFactory(transportType, new LoggerFactory(), httpClient: null, httpConnectionOptions: null)); Assert.Equal("httpClient", exception.ParamName); } @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [Fact] public void DefaultTransportFactoryCanBeCreatedWithoutHttpClientIfWebSocketsTransportRequestedExplicitly() { - new DefaultTransportFactory(HttpTransportType.WebSockets, new LoggerFactory(), httpClient: null, httpOptions: null); + new DefaultTransportFactory(HttpTransportType.WebSockets, new LoggerFactory(), httpClient: null, httpConnectionOptions: null); } [ConditionalTheory] @@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public void DefaultTransportFactoryCreatesRequestedTransportIfAvailable(HttpTransportType requestedTransport, Type expectedTransportType) { - var transportFactory = new DefaultTransportFactory(requestedTransport, loggerFactory: null, httpClient: new HttpClient(), httpOptions: null); + var transportFactory = new DefaultTransportFactory(requestedTransport, loggerFactory: null, httpClient: new HttpClient(), httpConnectionOptions: null); Assert.IsType(expectedTransportType, transportFactory.CreateTransport(AllTransportTypes)); } @@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public void DefaultTransportFactoryThrowsIfItCannotCreateRequestedTransport(HttpTransportType requestedTransport) { var transportFactory = - new DefaultTransportFactory(requestedTransport, loggerFactory: null, httpClient: new HttpClient(), httpOptions: null); + new DefaultTransportFactory(requestedTransport, loggerFactory: null, httpClient: new HttpClient(), httpConnectionOptions: null); var ex = Assert.Throws( () => transportFactory.CreateTransport(~requestedTransport)); @@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public void DefaultTransportFactoryCreatesWebSocketsTransportIfAvailable() { Assert.IsType( - new DefaultTransportFactory(AllTransportTypes, loggerFactory: null, httpClient: new HttpClient(), httpOptions: null) + new DefaultTransportFactory(AllTransportTypes, loggerFactory: null, httpClient: new HttpClient(), httpConnectionOptions: null) .CreateTransport(AllTransportTypes)); } @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { if (!TestHelpers.IsWebSocketsSupported()) { - var transportFactory = new DefaultTransportFactory(requestedTransport, loggerFactory: null, httpClient: new HttpClient(), httpOptions: null); + var transportFactory = new DefaultTransportFactory(requestedTransport, loggerFactory: null, httpClient: new HttpClient(), httpConnectionOptions: null); Assert.IsType(expectedTransportType, transportFactory.CreateTransport(AllTransportTypes)); } @@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests if (!TestHelpers.IsWebSocketsSupported()) { var transportFactory = - new DefaultTransportFactory(requestedTransport, loggerFactory: null, httpClient: new HttpClient(), httpOptions: null); + new DefaultTransportFactory(requestedTransport, loggerFactory: null, httpClient: new HttpClient(), httpConnectionOptions: null); var ex = Assert.Throws( () => transportFactory.CreateTransport(AllTransportTypes)); diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs index 01c1d5f2b7..0bebfc3ebc 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs @@ -23,6 +23,7 @@ using Moq; using Moq.Protected; using Xunit; using Xunit.Abstractions; +using HttpConnectionOptions = Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionOptions; namespace Microsoft.AspNetCore.SignalR.Tests { @@ -66,7 +67,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests // On Windows 7/2008R2 it should use ServerSentEvents transport to connect to the server. // The test logic lives in the TestTransportFactory and FakeTransport. - var connection = new HttpConnection(new Uri(url), new TestTransportFactory(), null, null); + var connection = new HttpConnection(new HttpConnectionOptions { Url = new Uri(url) }, null, new TestTransportFactory()); await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.DisposeAsync().OrTimeout(); } @@ -171,7 +172,14 @@ namespace Microsoft.AspNetCore.SignalR.Tests .Returns( (request, cancellationToken) => Task.FromException(new InvalidOperationException("HTTP requests should not be sent."))); - var connection = new HttpConnection(new Uri(url), HttpTransportType.WebSockets, loggerFactory, new HttpOptions { HttpMessageHandlerFactory = (httpMessageHandler) => mockHttpHandler.Object }); + var httpOptions = new HttpConnectionOptions + { + Url = new Uri(url), + Transports = HttpTransportType.WebSockets, + HttpMessageHandlerFactory = (httpMessageHandler) => mockHttpHandler.Object + }; + + var connection = new HttpConnection(httpOptions, loggerFactory); try { diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/Microsoft.AspNetCore.SignalR.Tests.csproj b/test/Microsoft.AspNetCore.SignalR.Tests/Microsoft.AspNetCore.SignalR.Tests.csproj index da0a775aaa..160b08c498 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/Microsoft.AspNetCore.SignalR.Tests.csproj +++ b/test/Microsoft.AspNetCore.SignalR.Tests/Microsoft.AspNetCore.SignalR.Tests.csproj @@ -21,10 +21,6 @@ - - - - diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs index 02d4b1144f..dc615fb678 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { ClientWebSocketOptions webSocketsOptions = null; - var httpOptions = new HttpOptions(); + var httpOptions = new HttpConnectionOptions(); httpOptions.Cookies.Add(new Cookie("Name", "Value", string.Empty, "fakeuri.org")); var clientCertificate = new X509Certificate(); httpOptions.ClientCertificates.Add(clientCertificate); @@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests httpOptions.Proxy = Mock.Of(); httpOptions.WebSocketOptions = options => webSocketsOptions = options; - var webSocketsTransport = new WebSocketsTransport(httpOptions: httpOptions, loggerFactory: null); + var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: httpOptions, loggerFactory: null); Assert.NotNull(webSocketsTransport); Assert.NotNull(webSocketsOptions); @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { using (StartLog(out var loggerFactory)) { - var webSocketsTransport = new WebSocketsTransport(httpOptions: null, loggerFactory: loggerFactory); + var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), TransferFormat.Binary).OrTimeout(); await webSocketsTransport.StopAsync().OrTimeout(); @@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { using (StartLog(out var loggerFactory)) { - var webSocketsTransport = new WebSocketsTransport(httpOptions: null, loggerFactory: loggerFactory); + var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/httpheader"), TransferFormat.Binary).OrTimeout(); @@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { using (StartLog(out var loggerFactory)) { - var webSocketsTransport = new WebSocketsTransport(httpOptions: null, loggerFactory: loggerFactory); + var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/httpheader"), TransferFormat.Binary).OrTimeout(); @@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { using (StartLog(out var loggerFactory)) { - var webSocketsTransport = new WebSocketsTransport(httpOptions: null, loggerFactory: loggerFactory); + var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), TransferFormat.Binary); webSocketsTransport.Output.Complete(); @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { using (StartLog(out var loggerFactory)) { - var webSocketsTransport = new WebSocketsTransport(httpOptions: null, loggerFactory: loggerFactory); + var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echoAndClose"), transferFormat); await webSocketsTransport.Output.WriteAsync(new byte[] { 0x42 }); @@ -172,7 +172,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { using (StartLog(out var loggerFactory)) { - var webSocketsTransport = new WebSocketsTransport(httpOptions: null, loggerFactory: loggerFactory); + var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), transferFormat).OrTimeout(); @@ -190,7 +190,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { using (StartLog(out var loggerFactory)) { - var webSocketsTransport = new WebSocketsTransport(httpOptions: null, loggerFactory: loggerFactory); + var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); var exception = await Assert.ThrowsAsync(() => webSocketsTransport.StartAsync(new Uri("http://fakeuri.org"), transferFormat));