Skip to content

Commit eb3a719

Browse files
authored
Cross-compile SignalR client libraries and enable platform compat ana… (#26140)
* Cross-compile SignalR client libraries and enable platform compat analyzer * Make our own OperatingSystem for downlevel tfms * Changes per PR feedback * Eliminate one of the analyzer bugs * Add browser
1 parent 1c200f2 commit eb3a719

23 files changed

+283
-108
lines changed

global.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"sdk": {
3-
"version": "5.0.100-rc.1.20452.10"
3+
"version": "6.0.100-alpha.1.20472.11"
44
},
55
"tools": {
6-
"dotnet": "5.0.100-rc.1.20452.10",
6+
"dotnet": "6.0.100-alpha.1.20472.11",
77
"runtimes": {
88
"dotnet/x64": [
99
"2.1.18",

src/Shared/OperatingSystem.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
#if NETCOREAPP
5+
#error Use System.OperatingSystem instead.
6+
#else
7+
8+
using System.Runtime.InteropServices;
9+
10+
namespace Microsoft.AspNetCore
11+
{
12+
internal sealed class OperatingSystem
13+
{
14+
private static readonly bool _isBrowser = RuntimeInformation.IsOSPlatform(OSPlatform.Create("browser"));
15+
16+
public static bool IsBrowser() => _isBrowser;
17+
}
18+
}
19+
#endif

src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,7 @@ private async Task ReconnectAsync(Exception closeException)
14591459

14601460
private OperationCanceledException GetOperationCanceledException(string message, Exception innerException, CancellationToken cancellationToken)
14611461
{
1462-
#if NETSTANDARD2_1
1462+
#if NETSTANDARD2_1 || NETCOREAPP
14631463
return new OperationCanceledException(message, innerException, _state.StopCts.Token);
14641464
#else
14651465
return new OperationCanceledException(message, innerException);

src/SignalR/clients/csharp/Client.Core/src/Microsoft.AspNetCore.SignalR.Client.Core.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<Description>Client for ASP.NET Core SignalR</Description>
5-
<TargetFrameworks>$(DefaultNetFxTargetFramework);netstandard2.0;netstandard2.1</TargetFrameworks>
5+
<TargetFrameworks>$(DefaultNetCoreTargetFramework);$(DefaultNetFxTargetFramework);netstandard2.0;netstandard2.1</TargetFrameworks>
66
<RootNamespace>Microsoft.AspNetCore.SignalR.Client</RootNamespace>
77
</PropertyGroup>
88

@@ -38,4 +38,8 @@
3838
<InternalsVisibleTo Include="Microsoft.AspNetCore.SignalR.Client.Tests" />
3939
</ItemGroup>
4040

41+
<ItemGroup>
42+
<SupportedPlatform Include="browser" />
43+
</ItemGroup>
44+
4145
</Project>

src/SignalR/clients/csharp/Client/src/Microsoft.AspNetCore.SignalR.Client.csproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<Description>Client for ASP.NET Core SignalR</Description>
5-
<TargetFrameworks>$(DefaultNetFxTargetFramework);netstandard2.0</TargetFrameworks>
5+
<TargetFrameworks>$(DefaultNetCoreTargetFramework);$(DefaultNetFxTargetFramework);netstandard2.0</TargetFrameworks>
66
</PropertyGroup>
77

88
<ItemGroup>
@@ -14,4 +14,8 @@
1414
<InternalsVisibleTo Include="Microsoft.AspNetCore.SignalR.Client.Tests" />
1515
<InternalsVisibleTo Include="Microsoft.AspNetCore.SignalR.Client.FunctionalTests" />
1616
</ItemGroup>
17+
18+
<ItemGroup>
19+
<SupportedPlatform Include="browser" />
20+
</ItemGroup>
1721
</Project>

src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnection.cs

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq;
99
using System.Net.Http;
1010
using System.Net.WebSockets;
11+
using System.Runtime.InteropServices;
1112
using System.Threading;
1213
using System.Threading.Tasks;
1314
using Microsoft.AspNetCore.Connections;
@@ -38,7 +39,6 @@ public partial class HttpConnection : ConnectionContext, IConnectionInherentKeep
3839
private bool _started;
3940
private bool _disposed;
4041
private bool _hasInherentKeepAlive;
41-
private bool _isRunningInBrowser;
4242

4343
private readonly HttpClient _httpClient;
4444
private readonly HttpConnectionOptions _httpConnectionOptions;
@@ -152,9 +152,7 @@ public HttpConnection(HttpConnectionOptions httpConnectionOptions, ILoggerFactor
152152
_httpClient = CreateHttpClient();
153153
}
154154

155-
_isRunningInBrowser = Utils.IsRunningInBrowser();
156-
157-
if (httpConnectionOptions.Transports == HttpTransportType.ServerSentEvents && _isRunningInBrowser)
155+
if (httpConnectionOptions.Transports == HttpTransportType.ServerSentEvents && OperatingSystem.IsBrowser())
158156
{
159157
throw new ArgumentException("ServerSentEvents can not be the only transport specified when running in the browser.", nameof(httpConnectionOptions));
160158
}
@@ -376,7 +374,7 @@ private async Task SelectAndStartTransport(TransferFormat transferFormat, Cancel
376374
continue;
377375
}
378376

379-
if (transportType == HttpTransportType.ServerSentEvents && _isRunningInBrowser)
377+
if (transportType == HttpTransportType.ServerSentEvents && OperatingSystem.IsBrowser())
380378
{
381379
Log.ServerSentEventsNotSupportedByBrowser(_logger);
382380
transportExceptions.Add(new TransportFailedException("ServerSentEvents", "The transport is not supported in the browser."));
@@ -529,42 +527,49 @@ private HttpClient CreateHttpClient()
529527
var httpClientHandler = new HttpClientHandler();
530528
HttpMessageHandler httpMessageHandler = httpClientHandler;
531529

530+
var isBrowser = OperatingSystem.IsBrowser();
531+
532532
if (_httpConnectionOptions != null)
533533
{
534-
if (_httpConnectionOptions.Proxy != null)
534+
if (!isBrowser)
535535
{
536-
httpClientHandler.Proxy = _httpConnectionOptions.Proxy;
537-
}
536+
// Configure options that do not work in the browser inside this if-block
537+
if (_httpConnectionOptions.Proxy != null)
538+
{
539+
httpClientHandler.Proxy = _httpConnectionOptions.Proxy;
540+
}
538541

539-
try
540-
{
541-
// On supported platforms, we need to pass the cookie container to the http client
542-
// so that we can capture any cookies from the negotiate response and give them to WebSockets.
543-
httpClientHandler.CookieContainer = _httpConnectionOptions.Cookies;
544-
}
545-
// Some variants of Mono do not support client certs or cookies and will throw NotImplementedException or NotSupportedException
546-
// Also WASM doesn't support some settings in the browser
547-
catch (Exception ex) when (ex is NotSupportedException || ex is NotImplementedException)
548-
{
549-
Log.CookiesNotSupported(_logger);
550-
}
542+
try
543+
{
544+
// On supported platforms, we need to pass the cookie container to the http client
545+
// so that we can capture any cookies from the negotiate response and give them to WebSockets.
546+
httpClientHandler.CookieContainer = _httpConnectionOptions.Cookies;
547+
}
548+
catch (Exception ex) when (ex is NotSupportedException || ex is NotImplementedException)
549+
{
550+
// Some variants of Mono do not support client certs or cookies and will throw NotImplementedException or NotSupportedException
551+
Log.CookiesNotSupported(_logger);
552+
}
551553

552-
// Only access HttpClientHandler.ClientCertificates
553-
// if the user has configured those options
554-
// https://github.com/aspnet/SignalR/issues/2232
555-
var clientCertificates = _httpConnectionOptions.ClientCertificates;
556-
if (clientCertificates?.Count > 0)
557-
{
558-
httpClientHandler.ClientCertificates.AddRange(clientCertificates);
559-
}
554+
// Only access HttpClientHandler.ClientCertificates
555+
// if the user has configured those options
556+
// https://github.com/aspnet/SignalR/issues/2232
560557

561-
if (_httpConnectionOptions.UseDefaultCredentials != null)
562-
{
563-
httpClientHandler.UseDefaultCredentials = _httpConnectionOptions.UseDefaultCredentials.Value;
564-
}
565-
if (_httpConnectionOptions.Credentials != null)
566-
{
567-
httpClientHandler.Credentials = _httpConnectionOptions.Credentials;
558+
var clientCertificates = _httpConnectionOptions.ClientCertificates;
559+
if (clientCertificates?.Count > 0)
560+
{
561+
httpClientHandler.ClientCertificates.AddRange(clientCertificates);
562+
}
563+
564+
if (_httpConnectionOptions.UseDefaultCredentials != null)
565+
{
566+
httpClientHandler.UseDefaultCredentials = _httpConnectionOptions.UseDefaultCredentials.Value;
567+
}
568+
569+
if (_httpConnectionOptions.Credentials != null)
570+
{
571+
httpClientHandler.Credentials = _httpConnectionOptions.Credentials;
572+
}
568573
}
569574

570575
httpMessageHandler = httpClientHandler;
@@ -645,7 +650,7 @@ private void CheckDisposed()
645650

646651
private static bool IsWebSocketsSupported()
647652
{
648-
#if NETSTANDARD2_1
653+
#if NETSTANDARD2_1 || NETCOREAPP
649654
// .NET Core 2.1 and above has a managed implementation
650655
return true;
651656
#else

src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionFactory.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Net;
6+
using System.Runtime.InteropServices;
67
using System.Threading;
78
using System.Threading.Tasks;
89
using Microsoft.AspNetCore.Connections;
@@ -86,23 +87,22 @@ internal static HttpConnectionOptions ShallowCopyHttpConnectionOptions(HttpConne
8687
{
8788
HttpMessageHandlerFactory = options.HttpMessageHandlerFactory,
8889
Headers = options.Headers,
89-
Cookies = options.Cookies,
9090
Url = options.Url,
9191
Transports = options.Transports,
9292
SkipNegotiation = options.SkipNegotiation,
9393
AccessTokenProvider = options.AccessTokenProvider,
9494
CloseTimeout = options.CloseTimeout,
95-
Credentials = options.Credentials,
96-
Proxy = options.Proxy,
97-
UseDefaultCredentials = options.UseDefaultCredentials,
9895
DefaultTransferFormat = options.DefaultTransferFormat,
99-
WebSocketConfiguration = options.WebSocketConfiguration,
10096
};
10197

102-
// WASM doesn't support Crypto APIs and our setter throws if you try to assign null
103-
if (options.ClientCertificates != null)
98+
if (!OperatingSystem.IsBrowser())
10499
{
100+
newOptions.Cookies = options.Cookies;
105101
newOptions.ClientCertificates = options.ClientCertificates;
102+
newOptions.Credentials = options.Credentials;
103+
newOptions.Proxy = options.Proxy;
104+
newOptions.UseDefaultCredentials = options.UseDefaultCredentials;
105+
newOptions.WebSocketConfiguration = options.WebSocketConfiguration;
106106
}
107107

108108
return newOptions;

0 commit comments

Comments
 (0)