Refactor HttpOptions in client (#1942)

- Rename HttpOptions to HttpConfigurationOptions
- Remove HttpConfigurationOptions from SignalR client project
- Updated client HttpConnection ctors
This commit is contained in:
James Newton-King 2018-04-11 20:20:04 +12:00 committed by GitHub
parent b30c2fecbf
commit 12b69a0fdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 170 additions and 214 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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<HttpConnection>();
_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<HttpConnection>();
_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<NegotiationResponse> GetNegotiationResponse()
{
var negotiationResponse = await Negotiate(Url, _httpClient, _logger);
var negotiationResponse = await Negotiate(_httpConnectionOptions.Url, _httpClient, _logger);
_connectionId = negotiationResponse.ConnectionId;
_logScope.ConnectionId = _connectionId;
return negotiationResponse;

View File

@ -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<string, string> _headers;
private X509CertificateCollection _clientCertificates;
private CookieContainer _cookies;
public HttpConnectionOptions()
{
_headers = new Dictionary<string, string>();
_clientCertificates = new X509CertificateCollection();
_cookies = new CookieContainer();
Transports = HttpTransports.All;
}
/// <summary>
/// Gets or sets a delegate for wrapping or replacing the <see cref="HttpMessageHandlerFactory"/>
/// that will make HTTP requests the server.
/// </summary>
public Func<HttpMessageHandler, HttpMessageHandler> HttpMessageHandlerFactory { get; set; }
public IReadOnlyCollection<KeyValuePair<string, string>> Headers { get; set; }
public IDictionary<string, string> 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<Task<string>> 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; }

View File

@ -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

View File

@ -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")]

View File

@ -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<HttpConnectionOptions> 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<ConnectionContext> ConnectAsync(TransferFormat transferFormat)
{
var httpOptions = new HttpOptions
{
HttpMessageHandlerFactory = _options.MessageHandlerFactory,
Headers = _options._headers != null ? new ReadOnlyDictionary<string, string>(_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;
}
}
}
}

View File

@ -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<string, string> _headers;
internal CookieContainer _cookies;
public HttpConnectionOptions()
{
Transports = HttpTransports.All;
}
public Uri Url { get; set; }
public HttpTransportType Transports { get; set; }
public Func<HttpMessageHandler, HttpMessageHandler> MessageHandlerFactory { get; set; }
public bool? UseDefaultCredentials { get; set; }
public ICredentials Credentials { get; set; }
public IWebProxy Proxy { get; set; }
public Func<Task<string>> AccessTokenFactory { get; set; }
public Action<ClientWebSocketOptions> 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<string, string> Headers
{
get
{
if (_headers == null)
{
_headers = new Dictionary<string, string>(StringComparer.Ordinal);
}
return _headers;
}
}
}
}

View File

@ -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

View File

@ -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<InvalidOperationException>(
@ -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();

View File

@ -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<Task<string>> 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);
}
}

View File

@ -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<ArgumentException>(() => 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<ICredentials>();
httpOptions.Proxy = Mock.Of<IWebProxy>();
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();

View File

@ -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;

View File

@ -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<ArgumentNullException>(
() => 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<InvalidOperationException>(
() => transportFactory.CreateTransport(~requestedTransport));
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
public void DefaultTransportFactoryCreatesWebSocketsTransportIfAvailable()
{
Assert.IsType<WebSocketsTransport>(
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<InvalidOperationException>(
() => transportFactory.CreateTransport(AllTransportTypes));

View File

@ -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<HttpRequestMessage, CancellationToken>(
(request, cancellationToken) => Task.FromException<HttpResponseMessage>(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
{

View File

@ -21,10 +21,6 @@
</Content>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\src\Common\DuplexPipe.cs" Link="DuplexPipe.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Client\Microsoft.AspNetCore.SignalR.Client.csproj" />

View File

@ -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<IWebProxy>();
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<ArgumentException>(() =>
webSocketsTransport.StartAsync(new Uri("http://fakeuri.org"), transferFormat));