Fix SignalR+WebSockets on WASM (#25922)
* Fix SignalR+WebSockets on WASM * fb * move stuff * select
This commit is contained in:
parent
e51468db03
commit
899deacb22
|
|
@ -7,7 +7,9 @@ using BasicTestApp;
|
|||
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
|
||||
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
|
||||
using Microsoft.AspNetCore.E2ETesting;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Support.UI;
|
||||
using TestServer;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
|
@ -38,13 +40,28 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void SignalRClientWorks()
|
||||
public void SignalRClientWorksWithLongPolling()
|
||||
{
|
||||
Browser.FindElement(By.Id("hub-url")).SendKeys(
|
||||
new Uri(_apiServerFixture.RootUri, "/subdir/chathub").AbsoluteUri);
|
||||
var target = new SelectElement(Browser.FindElement(By.Id("transport-type")));
|
||||
target.SelectByText("LongPolling");
|
||||
Browser.FindElement(By.Id("hub-connect")).Click();
|
||||
|
||||
Browser.Equal("SignalR Client: Echo",
|
||||
Browser.Equal("SignalR Client: Echo LongPolling",
|
||||
() => Browser.FindElements(By.CssSelector("li")).FirstOrDefault()?.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SignalRClientWorksWithWebSockets()
|
||||
{
|
||||
Browser.FindElement(By.Id("hub-url")).SendKeys(
|
||||
new Uri(_apiServerFixture.RootUri, "/subdir/chathub").AbsoluteUri);
|
||||
var target = new SelectElement(Browser.FindElement(By.Id("transport-type")));
|
||||
target.SelectByText("WebSockets");
|
||||
Browser.FindElement(By.Id("hub-connect")).Click();
|
||||
|
||||
Browser.Equal("SignalR Client: Echo WebSockets",
|
||||
() => Browser.FindElements(By.CssSelector("li")).FirstOrDefault()?.Text);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
@using Microsoft.AspNetCore.SignalR.Client
|
||||
@using Microsoft.AspNetCore.Http.Connections
|
||||
|
||||
<h1 id="signalr-client">SignalR Client</h1>
|
||||
|
||||
|
|
@ -7,6 +8,10 @@
|
|||
<p>
|
||||
Hub URL:
|
||||
<input id="hub-url" @bind="hubUrl" />
|
||||
<select id="transport-type" @bind="transportType">
|
||||
<option value=@HttpTransportType.LongPolling>LongPolling</option>
|
||||
<option value=@HttpTransportType.WebSockets>WebSockets</option>
|
||||
</select>
|
||||
<button id="hub-connect" @onclick="Connect">Connect</button>
|
||||
</p>
|
||||
|
||||
|
|
@ -21,13 +26,14 @@
|
|||
|
||||
@code {
|
||||
private string hubUrl;
|
||||
private HttpTransportType transportType;
|
||||
private HubConnection hubConnection;
|
||||
private List<string> messages = new List<string>();
|
||||
|
||||
protected async Task Connect()
|
||||
{
|
||||
hubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(hubUrl)
|
||||
.WithUrl(hubUrl, transportType)
|
||||
.Build();
|
||||
|
||||
hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
|
||||
|
|
@ -38,7 +44,7 @@
|
|||
});
|
||||
|
||||
await hubConnection.StartAsync();
|
||||
await hubConnection.SendAsync("SendMessage", "SignalR Client", "Echo");
|
||||
await hubConnection.SendAsync("SendMessage", "SignalR Client", $"Echo {transportType}");
|
||||
}
|
||||
|
||||
public bool IsConnected =>
|
||||
|
|
|
|||
|
|
@ -39,8 +39,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal
|
|||
{
|
||||
return new WebSocketsTransport(_httpConnectionOptions, _loggerFactory, _accessTokenProvider);
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
catch (PlatformNotSupportedException ex)
|
||||
{
|
||||
Log.TransportNotSupported(_loggerFactory.CreateLogger<DefaultTransportFactory>(), HttpTransportType.WebSockets, ex);
|
||||
_websocketsSupported = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -59,5 +60,16 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal
|
|||
|
||||
throw new InvalidOperationException("No requested transports available on the server.");
|
||||
}
|
||||
|
||||
private static class Log
|
||||
{
|
||||
private static readonly Action<ILogger, HttpTransportType, Exception> _transportNotSupported =
|
||||
LoggerMessage.Define<HttpTransportType>(LogLevel.Debug, new EventId(1, "TransportNotSupported"), "Transport '{TransportType}' is not supported.");
|
||||
|
||||
public static void TransportNotSupported(ILogger logger, HttpTransportType transportType, Exception ex)
|
||||
{
|
||||
_transportNotSupported(logger, transportType, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,66 +37,70 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal
|
|||
public WebSocketsTransport(HttpConnectionOptions httpConnectionOptions, ILoggerFactory loggerFactory, Func<Task<string>> accessTokenProvider)
|
||||
{
|
||||
_webSocket = new ClientWebSocket();
|
||||
_isRunningInBrowser = Utils.IsRunningInBrowser();
|
||||
|
||||
// Full Framework will throw when trying to set the User-Agent header
|
||||
// So avoid setting it in netstandard2.0 and only set it in netstandard2.1 and higher
|
||||
// ClientWebSocketOptions throws PNSE when accessing and setting properties
|
||||
if (!_isRunningInBrowser)
|
||||
{
|
||||
// Full Framework will throw when trying to set the User-Agent header
|
||||
// So avoid setting it in netstandard2.0 and only set it in netstandard2.1 and higher
|
||||
#if !NETSTANDARD2_0
|
||||
_webSocket.Options.SetRequestHeader("User-Agent", Constants.UserAgentHeader.ToString());
|
||||
_webSocket.Options.SetRequestHeader("User-Agent", Constants.UserAgentHeader.ToString());
|
||||
#else
|
||||
// Set an alternative user agent header on Full framework
|
||||
_webSocket.Options.SetRequestHeader("X-SignalR-User-Agent", Constants.UserAgentHeader.ToString());
|
||||
// Set an alternative user agent header on Full framework
|
||||
_webSocket.Options.SetRequestHeader("X-SignalR-User-Agent", Constants.UserAgentHeader.ToString());
|
||||
#endif
|
||||
|
||||
if (httpConnectionOptions != null)
|
||||
{
|
||||
if (httpConnectionOptions.Headers != null)
|
||||
if (httpConnectionOptions != null)
|
||||
{
|
||||
foreach (var header in httpConnectionOptions.Headers)
|
||||
if (httpConnectionOptions.Headers != null)
|
||||
{
|
||||
_webSocket.Options.SetRequestHeader(header.Key, header.Value);
|
||||
foreach (var header in httpConnectionOptions.Headers)
|
||||
{
|
||||
_webSocket.Options.SetRequestHeader(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.Cookies != null)
|
||||
{
|
||||
_webSocket.Options.Cookies = httpConnectionOptions.Cookies;
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.ClientCertificates != null)
|
||||
{
|
||||
_webSocket.Options.ClientCertificates.AddRange(httpConnectionOptions.ClientCertificates);
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.Credentials != null)
|
||||
{
|
||||
_webSocket.Options.Credentials = httpConnectionOptions.Credentials;
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.Proxy != null)
|
||||
{
|
||||
_webSocket.Options.Proxy = httpConnectionOptions.Proxy;
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.UseDefaultCredentials != null)
|
||||
{
|
||||
_webSocket.Options.UseDefaultCredentials = httpConnectionOptions.UseDefaultCredentials.Value;
|
||||
}
|
||||
|
||||
httpConnectionOptions.WebSocketConfiguration?.Invoke(_webSocket.Options);
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.Cookies != null)
|
||||
{
|
||||
_webSocket.Options.Cookies = httpConnectionOptions.Cookies;
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.ClientCertificates != null)
|
||||
{
|
||||
_webSocket.Options.ClientCertificates.AddRange(httpConnectionOptions.ClientCertificates);
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.Credentials != null)
|
||||
{
|
||||
_webSocket.Options.Credentials = httpConnectionOptions.Credentials;
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.Proxy != null)
|
||||
{
|
||||
_webSocket.Options.Proxy = httpConnectionOptions.Proxy;
|
||||
}
|
||||
|
||||
if (httpConnectionOptions.UseDefaultCredentials != null)
|
||||
{
|
||||
_webSocket.Options.UseDefaultCredentials = httpConnectionOptions.UseDefaultCredentials.Value;
|
||||
}
|
||||
|
||||
httpConnectionOptions.WebSocketConfiguration?.Invoke(_webSocket.Options);
|
||||
|
||||
_closeTimeout = httpConnectionOptions.CloseTimeout;
|
||||
// Set this header so the server auth middleware will set an Unauthorized instead of Redirect status code
|
||||
// See: https://github.com/aspnet/Security/blob/ff9f145a8e89c9756ea12ff10c6d47f2f7eb345f/src/Microsoft.AspNetCore.Authentication.Cookies/Events/CookieAuthenticationEvents.cs#L42
|
||||
_webSocket.Options.SetRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
}
|
||||
|
||||
// Set this header so the server auth middleware will set an Unauthorized instead of Redirect status code
|
||||
// See: https://github.com/aspnet/Security/blob/ff9f145a8e89c9756ea12ff10c6d47f2f7eb345f/src/Microsoft.AspNetCore.Authentication.Cookies/Events/CookieAuthenticationEvents.cs#L42
|
||||
_webSocket.Options.SetRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
_closeTimeout = httpConnectionOptions?.CloseTimeout ?? default;
|
||||
|
||||
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<WebSocketsTransport>();
|
||||
|
||||
// Ignore the HttpConnectionOptions access token provider. We were given an updated delegate from the HttpConnection.
|
||||
_accessTokenProvider = accessTokenProvider;
|
||||
|
||||
_isRunningInBrowser = Utils.IsRunningInBrowser();
|
||||
}
|
||||
|
||||
public async Task StartAsync(Uri url, TransferFormat transferFormat, CancellationToken cancellationToken = default)
|
||||
|
|
|
|||
Loading…
Reference in New Issue