[SignalR] Copy cookies from negotiate to WebSockets (#24572)

This commit is contained in:
Brennan 2020-09-10 18:22:14 -07:00 committed by GitHub
parent 327d55d01c
commit 970d0f5d00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 5 deletions

View File

@ -1721,6 +1721,34 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
}
}
[ConditionalFact]
[WebSocketsSupportedCondition]
public async Task CookiesFromNegotiateAreAppliedToWebSockets()
{
await using (var server = await StartServer<Startup>())
{
var hubConnection = new HubConnectionBuilder()
.WithLoggerFactory(LoggerFactory)
.WithUrl(server.Url + "/default", HttpTransportType.WebSockets)
.Build();
try
{
await hubConnection.StartAsync().OrTimeout();
var cookieValue = await hubConnection.InvokeAsync<string>(nameof(TestHub.GetCookieValue), "fromNegotiate").OrTimeout();
Assert.Equal("a value", cookieValue);
}
catch (Exception ex)
{
LoggerFactory.CreateLogger<HubConnectionTests>().LogError(ex, "{ExceptionType} from test", ex.GetType().FullName);
throw;
}
finally
{
await hubConnection.DisposeAsync().OrTimeout();
}
}
}
[Fact]
public async Task CheckHttpConnectionFeatures()
{

View File

@ -65,6 +65,18 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
app.UseAuthentication();
app.UseAuthorization();
app.Use(next =>
{
return context =>
{
if (context.Request.Path.Value.EndsWith("/negotiate"))
{
context.Response.Cookies.Append("fromNegotiate", "a value");
}
return next(context);
};
});
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<TestHub>("/default");

View File

@ -69,6 +69,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
private static readonly Action<ILogger, Exception> _serverSentEventsNotSupportedByBrowser =
LoggerMessage.Define(LogLevel.Debug, new EventId(19, "ServerSentEventsNotSupportedByBrowser"), "Skipping ServerSentEvents because they are not supported by the browser.");
private static readonly Action<ILogger, Exception> _cookiesNotSupported =
LoggerMessage.Define(LogLevel.Trace, new EventId(20, "CookiesNotSupported"), "Cookies are not supported on this platform.");
public static void Starting(ILogger logger)
{
_starting(logger, null);
@ -175,6 +178,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
{
_serverSentEventsNotSupportedByBrowser(logger, null);
}
public static void CookiesNotSupported(ILogger logger)
{
_cookiesNotSupported(logger, null);
}
}
}
}

View File

@ -154,7 +154,6 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
_isRunningInBrowser = Utils.IsRunningInBrowser();
if (httpConnectionOptions.Transports == HttpTransportType.ServerSentEvents && _isRunningInBrowser)
{
throw new ArgumentException("ServerSentEvents can not be the only transport specified when running in the browser.", nameof(httpConnectionOptions));
@ -537,13 +536,21 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
httpClientHandler.Proxy = _httpConnectionOptions.Proxy;
}
// Only access HttpClientHandler.ClientCertificates and HttpClientHandler.CookieContainer
// if the user has configured those options
// Some variants of Mono do not support client certs or cookies and will throw NotImplementedException
if (_httpConnectionOptions.Cookies.Count > 0)
try
{
// On supported platforms, we need to pass the cookie container to the http client
// so that we can capture any cookies from the negotiate response and give them to WebSockets.
httpClientHandler.CookieContainer = _httpConnectionOptions.Cookies;
}
// Some variants of Mono do not support client certs or cookies and will throw NotImplementedException or NotSupportedException
// Also WASM doesn't support some settings in the browser
catch (Exception ex) when (ex is NotSupportedException || ex is NotImplementedException)
{
Log.CookiesNotSupported(_logger);
}
// Only access HttpClientHandler.ClientCertificates
// if the user has configured those options
// https://github.com/aspnet/SignalR/issues/2232
var clientCertificates = _httpConnectionOptions.ClientCertificates;
if (clientCertificates?.Count > 0)