From d816c6ef6085976a880387d37f651d0cb1205c0e Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 13 Mar 2018 09:46:34 +1300 Subject: [PATCH] Add additional properties to HttpOptions (#1557) --- .../HubConnectionBuilderHttpExtensions.cs | 137 +++++++++++++++++- .../HttpConnection.cs | 50 ++++++- .../HttpOptions.cs | 14 +- .../WebSocketsTransport.cs | 52 +++++-- .../HttpConnectionTests.Helpers.cs | 10 +- .../HttpConnectionTests.cs | 51 +++++++ .../HubConnectionBuilderExtensionsTests.cs | 57 +++++++- .../EndToEndTests.cs | 2 +- .../WebSocketsTransportTests.cs | 32 ++++ 9 files changed, 379 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.AspNetCore.SignalR.Client/HubConnectionBuilderHttpExtensions.cs b/src/Microsoft.AspNetCore.SignalR.Client/HubConnectionBuilderHttpExtensions.cs index 93589fee3a..067755b8af 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client/HubConnectionBuilderHttpExtensions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client/HubConnectionBuilderHttpExtensions.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Net; using System.Net.Http; using System.Net.WebSockets; +using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Sockets; using Microsoft.AspNetCore.Sockets.Client; using Microsoft.AspNetCore.Sockets.Client.Http; @@ -19,6 +21,11 @@ namespace Microsoft.AspNetCore.SignalR.Client public static readonly string HeadersKey = "Headers"; public static readonly string AccessTokenFactoryKey = "AccessTokenFactory"; public static readonly string WebSocketOptionsKey = "WebSocketOptions"; + public static readonly string CookiesKey = "Cookies"; + public static readonly string ProxyKey = "Proxy"; + public static readonly string ClientCertificatesKey = "ClientCertificates"; + public static readonly string CredentialsKey = "Credentials"; + public static readonly string UseDefaultCredentialsKey = "UseDefaultCredentials"; public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, string url) { @@ -46,6 +53,11 @@ namespace Microsoft.AspNetCore.SignalR.Client Headers = headers != null ? new ReadOnlyDictionary(headers) : null, AccessTokenFactory = hubConnectionBuilder.GetAccessTokenFactory(), WebSocketOptions = hubConnectionBuilder.GetWebSocketOptions(), + Cookies = hubConnectionBuilder.GetCookies(), + Proxy = hubConnectionBuilder.GetProxy(), + UseDefaultCredentials = hubConnectionBuilder.GetUseDefaultCredentials(), + ClientCertificates = hubConnectionBuilder.GetClientCertificates(), + Credentials = hubConnectionBuilder.GetCredentials(), }; return new HttpConnection(url, @@ -62,9 +74,15 @@ namespace Microsoft.AspNetCore.SignalR.Client return hubConnectionBuilder; } - public static IHubConnectionBuilder WithMessageHandler(this IHubConnectionBuilder hubConnectionBuilder, HttpMessageHandler httpMessageHandler) + /// + /// Sets a delegate for wrapping or replacing the that will make HTTP requests the server. + /// + /// The . + /// A delegate for wrapping or replacing the that will make HTTP requests the server. + /// The . + public static IHubConnectionBuilder WithMessageHandler(this IHubConnectionBuilder hubConnectionBuilder, Func configurehttpMessageHandler) { - hubConnectionBuilder.AddSetting(HttpMessageHandlerKey, httpMessageHandler); + hubConnectionBuilder.AddSetting(HttpMessageHandlerKey, configurehttpMessageHandler); return hubConnectionBuilder; } @@ -87,6 +105,62 @@ namespace Microsoft.AspNetCore.SignalR.Client return hubConnectionBuilder; } + public static IHubConnectionBuilder WithUseDefaultCredentials(this IHubConnectionBuilder hubConnectionBuilder, bool useDefaultCredentials) + { + hubConnectionBuilder.AddSetting(UseDefaultCredentialsKey, useDefaultCredentials); + return hubConnectionBuilder; + } + + public static IHubConnectionBuilder WithCredentials(this IHubConnectionBuilder hubConnectionBuilder, ICredentials credentials) + { + hubConnectionBuilder.AddSetting(CredentialsKey, credentials); + return hubConnectionBuilder; + } + + public static IHubConnectionBuilder WithProxy(this IHubConnectionBuilder hubConnectionBuilder, IWebProxy proxy) + { + hubConnectionBuilder.AddSetting(ProxyKey, proxy); + return hubConnectionBuilder; + } + + public static IHubConnectionBuilder WithCookie(this IHubConnectionBuilder hubConnectionBuilder, Cookie cookie) + { + if (cookie == null) + { + throw new ArgumentNullException(nameof(cookie)); + } + + var cookies = hubConnectionBuilder.GetCookies(); + if (cookies == null) + { + cookies = new CookieContainer(); + hubConnectionBuilder.AddSetting(CookiesKey, cookies); + } + + cookies.Add(cookie); + + return hubConnectionBuilder; + } + + public static IHubConnectionBuilder WithClientCertificate(this IHubConnectionBuilder hubConnectionBuilder, X509Certificate clientCertificate) + { + if (clientCertificate == null) + { + throw new ArgumentNullException(nameof(clientCertificate)); + } + + var clientCertificates = hubConnectionBuilder.GetClientCertificates(); + if (clientCertificates == null) + { + clientCertificates = new X509CertificateCollection(); + hubConnectionBuilder.AddSetting(ClientCertificatesKey, clientCertificates); + } + + clientCertificates.Add(clientCertificate); + + return hubConnectionBuilder; + } + public static IHubConnectionBuilder WithAccessToken(this IHubConnectionBuilder hubConnectionBuilder, Func accessTokenFactory) { if (accessTokenFactory == null) @@ -121,9 +195,14 @@ namespace Microsoft.AspNetCore.SignalR.Client return TransportType.All; } - public static HttpMessageHandler GetMessageHandler(this IHubConnectionBuilder hubConnectionBuilder) + /// + /// Gets a delegate for wrapping or replacing the that will make HTTP requests the server. + /// + /// The . + /// A delegate for wrapping or replacing the that will make HTTP requests the server. + public static Func GetMessageHandler(this IHubConnectionBuilder hubConnectionBuilder) { - hubConnectionBuilder.TryGetSetting(HttpMessageHandlerKey, out var messageHandler); + hubConnectionBuilder.TryGetSetting>(HttpMessageHandlerKey, out var messageHandler); return messageHandler; } @@ -137,6 +216,56 @@ namespace Microsoft.AspNetCore.SignalR.Client return null; } + public static IWebProxy GetProxy(this IHubConnectionBuilder hubConnectionBuilder) + { + if (hubConnectionBuilder.TryGetSetting(ProxyKey, out var proxy)) + { + return proxy; + } + + return null; + } + + public static bool? GetUseDefaultCredentials(this IHubConnectionBuilder hubConnectionBuilder) + { + if (hubConnectionBuilder.TryGetSetting(UseDefaultCredentialsKey, out var useDefaultCredentials)) + { + return useDefaultCredentials; + } + + return null; + } + + public static CookieContainer GetCookies(this IHubConnectionBuilder hubConnectionBuilder) + { + if (hubConnectionBuilder.TryGetSetting(CookiesKey, out var cookies)) + { + return cookies; + } + + return null; + } + + public static ICredentials GetCredentials(this IHubConnectionBuilder hubConnectionBuilder) + { + if (hubConnectionBuilder.TryGetSetting(CredentialsKey, out var credentials)) + { + return credentials; + } + + return null; + } + + public static X509CertificateCollection GetClientCertificates(this IHubConnectionBuilder hubConnectionBuilder) + { + if (hubConnectionBuilder.TryGetSetting(ClientCertificatesKey, out var clientCertificates)) + { + return clientCertificates; + } + + return null; + } + public static Func GetAccessTokenFactory(this IHubConnectionBuilder hubConnectionBuilder) { if (hubConnectionBuilder.TryGetSetting>(AccessTokenFactoryKey, out var factory)) diff --git a/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpConnection.cs b/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpConnection.cs index ea44802378..482a0997d5 100644 --- a/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpConnection.cs +++ b/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpConnection.cs @@ -89,8 +89,7 @@ namespace Microsoft.AspNetCore.Sockets.Client _requestedTransportType = transportType; if (_requestedTransportType != TransportType.WebSockets) { - _httpClient = httpOptions?.HttpMessageHandler == null ? new HttpClient() : new HttpClient(httpOptions.HttpMessageHandler); - _httpClient.Timeout = HttpClientTimeout; + _httpClient = CreateHttpClient(); } _transportFactory = new DefaultTransportFactory(transportType, _loggerFactory, _httpClient, httpOptions); @@ -98,14 +97,57 @@ namespace Microsoft.AspNetCore.Sockets.Client _scopeDisposable = _logger.BeginScope(_logScope); } + private HttpClient CreateHttpClient() + { + HttpMessageHandler httpMessageHandler = null; + if (_httpOptions != null) + { + var httpClientHandler = new HttpClientHandler(); + if (_httpOptions.Proxy != null) + { + httpClientHandler.Proxy = _httpOptions.Proxy; + } + if (_httpOptions.Cookies != null) + { + httpClientHandler.CookieContainer = _httpOptions.Cookies; + } + if (_httpOptions.ClientCertificates != null) + { + httpClientHandler.ClientCertificates.AddRange(_httpOptions.ClientCertificates); + } + if (_httpOptions.UseDefaultCredentials != null) + { + httpClientHandler.UseDefaultCredentials = _httpOptions.UseDefaultCredentials.Value; + } + if (_httpOptions.Credentials != null) + { + httpClientHandler.Credentials = _httpOptions.Credentials; + } + + httpMessageHandler = httpClientHandler; + if (_httpOptions.HttpMessageHandler != null) + { + httpMessageHandler = _httpOptions.HttpMessageHandler(httpClientHandler); + if (httpMessageHandler == null) + { + throw new InvalidOperationException("Configured HttpMessageHandler did not return a value."); + } + } + } + + var httpClient = httpMessageHandler == null ? new HttpClient() : new HttpClient(httpMessageHandler); + httpClient.Timeout = HttpClientTimeout; + + return httpClient; + } + public HttpConnection(Uri url, ITransportFactory transportFactory, ILoggerFactory loggerFactory, HttpOptions httpOptions) { Url = url ?? throw new ArgumentNullException(nameof(url)); _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; _logger = _loggerFactory.CreateLogger(); _httpOptions = httpOptions; - _httpClient = _httpOptions?.HttpMessageHandler == null ? new HttpClient() : new HttpClient(_httpOptions?.HttpMessageHandler); - _httpClient.Timeout = HttpClientTimeout; + _httpClient = CreateHttpClient(); _transportFactory = transportFactory ?? throw new ArgumentNullException(nameof(transportFactory)); _logScope = new ConnectionLogScope(); _scopeDisposable = _logger.BeginScope(_logScope); diff --git a/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpOptions.cs b/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpOptions.cs index 81786b5084..c9c269185e 100644 --- a/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpOptions.cs +++ b/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpOptions.cs @@ -3,17 +3,29 @@ using System; using System.Collections.Generic; +using System.Net; using System.Net.Http; using System.Net.WebSockets; +using System.Security.Cryptography.X509Certificates; namespace Microsoft.AspNetCore.Sockets.Client.Http { public class HttpOptions { - public HttpMessageHandler HttpMessageHandler { get; set; } + /// + /// Gets or sets a delegate for wrapping or replacing the + /// that will make HTTP requests the server. + /// + public Func HttpMessageHandler { get; set; } + public IReadOnlyCollection> Headers { 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; } /// /// Gets or sets a delegate that will be invoked with the object used diff --git a/src/Microsoft.AspNetCore.Sockets.Client.Http/WebSocketsTransport.cs b/src/Microsoft.AspNetCore.Sockets.Client.Http/WebSocketsTransport.cs index f43d7f0b4e..6464d089cc 100644 --- a/src/Microsoft.AspNetCore.Sockets.Client.Http/WebSocketsTransport.cs +++ b/src/Microsoft.AspNetCore.Sockets.Client.Http/WebSocketsTransport.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.IO.Pipelines; +using System.Net; using System.Net.WebSockets; using System.Runtime.InteropServices; using System.Threading; @@ -38,22 +39,51 @@ namespace Microsoft.AspNetCore.Sockets.Client // 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?.Headers != null) + if (httpOptions != null) { - foreach (var header in httpOptions.Headers) + if (httpOptions.Headers != null) { - _webSocket.Options.SetRequestHeader(header.Key, header.Value); + foreach (var header in httpOptions.Headers) + { + _webSocket.Options.SetRequestHeader(header.Key, header.Value); + } } + + if (httpOptions.Cookies != null) + { + _webSocket.Options.Cookies = httpOptions.Cookies; + } + + if (httpOptions.ClientCertificates != null) + { + _webSocket.Options.ClientCertificates.AddRange(httpOptions.ClientCertificates); + } + + if (httpOptions.Credentials != null) + { + _webSocket.Options.Credentials = httpOptions.Credentials; + } + + if (httpOptions.Proxy != null) + { + _webSocket.Options.Proxy = httpOptions.Proxy; + } + + if (httpOptions.UseDefaultCredentials != null) + { + _webSocket.Options.UseDefaultCredentials = httpOptions.UseDefaultCredentials.Value; + } + + if (httpOptions.AccessTokenFactory != null) + { + _webSocket.Options.SetRequestHeader("Authorization", $"Bearer {httpOptions.AccessTokenFactory()}"); + } + + httpOptions.WebSocketOptions?.Invoke(_webSocket.Options); + + _closeTimeout = httpOptions.CloseTimeout; } - if (httpOptions?.AccessTokenFactory != null) - { - _webSocket.Options.SetRequestHeader("Authorization", $"Bearer {httpOptions.AccessTokenFactory()}"); - } - - httpOptions?.WebSocketOptions?.Invoke(_webSocket.Options); - - _closeTimeout = httpOptions?.CloseTimeout ?? TimeSpan.FromSeconds(5); _logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger(); } diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.Helpers.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.Helpers.cs index 36d4ca0146..6a6441841c 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.Helpers.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.Helpers.cs @@ -16,11 +16,17 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests { private static HttpConnection CreateConnection(HttpMessageHandler httpHandler = null, ILoggerFactory loggerFactory = null, string url = null, ITransport transport = null) { - loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; var httpOptions = new HttpOptions() { - HttpMessageHandler = httpHandler ?? TestHttpMessageHandler.CreateDefault(), + HttpMessageHandler = (httpMessageHandler) => httpHandler ?? TestHttpMessageHandler.CreateDefault(), }; + + return CreateConnection(httpOptions, loggerFactory, url, transport); + } + + private static HttpConnection CreateConnection(HttpOptions httpOptions, ILoggerFactory loggerFactory = null, string url = null, ITransport transport = null) + { + loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; var uri = new Uri(url ?? "http://fakeuri.org/"); var connection = (transport != null) ? diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.cs index f8cf843588..32bec2a0cf 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HttpConnectionTests.cs @@ -2,14 +2,21 @@ // 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.IO.Pipelines; +using System.Net; +using System.Net.Http; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Client.Tests; using Microsoft.AspNetCore.Sockets; using Microsoft.AspNetCore.Sockets.Client; +using Microsoft.AspNetCore.Sockets.Client.Http; using Microsoft.AspNetCore.Sockets.Features; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; +using Moq; using Xunit; using Xunit.Abstractions; @@ -140,5 +147,49 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests Assert.Equal(TransferMode.Binary, transferModeFeature.TransferMode); }); } + + [Fact] + public async Task HttpOptionsSetOntoHttpClientHandler() + { + var testHttpHandler = new TestHttpMessageHandler(); + + var negotiateUrlTcs = new TaskCompletionSource(); + testHttpHandler.OnNegotiate((request, cancellationToken) => + { + negotiateUrlTcs.TrySetResult(request.RequestUri.ToString()); + return ResponseUtils.CreateResponse(HttpStatusCode.OK, + ResponseUtils.CreateNegotiationContent()); + }); + + HttpClientHandler httpClientHandler = null; + + HttpOptions httpOptions = new HttpOptions(); + httpOptions.HttpMessageHandler = inner => + { + httpClientHandler = (HttpClientHandler)inner; + return testHttpHandler; + }; + httpOptions.Cookies.Add(new Cookie("Name", "Value", string.Empty, "fakeuri.org")); + var clientCertificate = new X509Certificate(); + httpOptions.ClientCertificates.Add(clientCertificate); + httpOptions.UseDefaultCredentials = false; + httpOptions.Credentials = Mock.Of(); + httpOptions.Proxy = Mock.Of(); + + await WithConnectionAsync( + CreateConnection(httpOptions, url: "http://fakeuri.org/"), + async (connection, closed) => + { + await connection.StartAsync().OrTimeout(); + }); + + Assert.NotNull(httpClientHandler); + Assert.Equal(1, httpClientHandler.CookieContainer.Count); + Assert.Single(httpClientHandler.ClientCertificates); + Assert.Same(clientCertificate, httpClientHandler.ClientCertificates[0]); + Assert.False(httpClientHandler.UseDefaultCredentials); + Assert.Same(httpOptions.Proxy, httpClientHandler.Proxy); + Assert.Same(httpOptions.Credentials, httpClientHandler.Credentials); + } } } diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionBuilderExtensionsTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionBuilderExtensionsTests.cs index ea4b0f164a..bfca9f5be0 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionBuilderExtensionsTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionBuilderExtensionsTests.cs @@ -1,18 +1,68 @@ // 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.Linq; +using System.Net; using System.Net.Http; +using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.AspNetCore.Sockets; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; using Moq; using Xunit; +using TransportType = Microsoft.AspNetCore.Sockets.TransportType; namespace Microsoft.AspNetCore.SignalR.Client.Tests { public class HubConnectionBuilderExtensionsTests { + [Fact] + public void WithProxyRegistersGivenProxy() + { + var connectionBuilder = new HubConnectionBuilder(); + var proxy = Mock.Of(); + connectionBuilder.WithProxy(proxy); + Assert.Same(proxy, connectionBuilder.GetProxy()); + } + + [Fact] + public void WithCredentialsRegistersGivenCredentials() + { + var connectionBuilder = new HubConnectionBuilder(); + var credentials = Mock.Of(); + connectionBuilder.WithCredentials(credentials); + Assert.Same(credentials, connectionBuilder.GetCredentials()); + } + + [Fact] + public void WithUseDefaultCredentialsRegistersGivenUseDefaultCredentials() + { + var connectionBuilder = new HubConnectionBuilder(); + var useDefaultCredentials = true; + connectionBuilder.WithUseDefaultCredentials(useDefaultCredentials); + Assert.Equal(useDefaultCredentials, connectionBuilder.GetUseDefaultCredentials()); + } + + [Fact] + public void WithClientCertificateRegistersGivenClientCertificate() + { + var connectionBuilder = new HubConnectionBuilder(); + var certificate = new X509Certificate(); + connectionBuilder.WithClientCertificate(certificate); + Assert.Contains(certificate, connectionBuilder.GetClientCertificates().Cast()); + } + + [Fact] + public void WithCookieRegistersGivenCookie() + { + var connectionBuilder = new HubConnectionBuilder(); + var cookie = new Cookie("Name!", "Value!", string.Empty, "www.contoso.com"); + connectionBuilder.WithCookie(cookie); + Assert.Equal(1, connectionBuilder.GetCookies().Count); + } + [Fact] public void WithHubProtocolRegistersGivenProtocol() { @@ -60,10 +110,11 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests [Fact] public void WithMsgHandlerRegistersGivenMessageHandler() { + var messageHandler = new Func(httpMessageHandler => default); + var connectionBuilder = new HubConnectionBuilder(); - var msgHandler = Mock.Of(); - connectionBuilder.WithMessageHandler(msgHandler); - Assert.Same(msgHandler, connectionBuilder.GetMessageHandler()); + connectionBuilder.WithMessageHandler(messageHandler); + Assert.Same(messageHandler, connectionBuilder.GetMessageHandler()); } [Theory] diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs index 0db5b7a8e9..e12ae52925 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs @@ -132,7 +132,7 @@ 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), TransportType.WebSockets, loggerFactory, new HttpOptions { HttpMessageHandler = mockHttpHandler.Object }); + var connection = new HttpConnection(new Uri(url), TransportType.WebSockets, loggerFactory, new HttpOptions { HttpMessageHandler = (httpMessageHandler) => mockHttpHandler.Object }); try { diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs index a2996c4896..0b3d93b011 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs @@ -3,9 +3,14 @@ using System; using System.Buffers; +using System.Collections.Generic; using System.IO.Pipelines; using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.WebSockets; using System.Reflection; +using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Sockets; @@ -35,6 +40,33 @@ namespace Microsoft.AspNetCore.SignalR.Tests _serverFixture = serverFixture; } + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")] + public void HttpOptionsSetOntoWebSocketOptions() + { + ClientWebSocketOptions webSocketsOptions = null; + + HttpOptions httpOptions = new HttpOptions(); + httpOptions.Cookies.Add(new Cookie("Name", "Value", string.Empty, "fakeuri.org")); + var clientCertificate = new X509Certificate(); + httpOptions.ClientCertificates.Add(clientCertificate); + httpOptions.UseDefaultCredentials = false; + httpOptions.Credentials = Mock.Of(); + httpOptions.Proxy = Mock.Of(); + httpOptions.WebSocketOptions = options => webSocketsOptions = options; + + var webSocketsTransport = new WebSocketsTransport(httpOptions: httpOptions, loggerFactory: null); + Assert.NotNull(webSocketsTransport); + + Assert.NotNull(webSocketsOptions); + Assert.Equal(1, webSocketsOptions.Cookies.Count); + Assert.Single(webSocketsOptions.ClientCertificates); + Assert.Same(clientCertificate, webSocketsOptions.ClientCertificates[0]); + Assert.False(webSocketsOptions.UseDefaultCredentials); + Assert.Same(httpOptions.Proxy, webSocketsOptions.Proxy); + Assert.Same(httpOptions.Credentials, webSocketsOptions.Credentials); + } + [ConditionalFact] [OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")] public async Task WebSocketsTransportStopsSendAndReceiveLoopsWhenTransportIsStopped()