Initial support for websocket subprotocols (#933)

* Initial support for websocket subprotocols
- Exposes a SubProtocol property on WebSocketOptions that picks the
protocol for all connections on the end point.
- This is required for things like mqtt over websockets (the SubProtocol in
this case is something like mqtt or mqttv3.1)
- Added test

#402
This commit is contained in:
David Fowler 2017-09-25 15:17:45 -07:00 committed by GitHub
parent 5497c7d4ce
commit 000f9cb192
4 changed files with 61 additions and 1 deletions

View File

@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Sockets.Internal.Transports
{
Debug.Assert(context.WebSockets.IsWebSocketRequest, "Not a websocket request");
using (var ws = await context.WebSockets.AcceptWebSocketAsync())
using (var ws = await context.WebSockets.AcceptWebSocketAsync(_options.SubProtocol))
{
_logger.SocketOpened(_connection.ConnectionId);

View File

@ -8,5 +8,7 @@ namespace Microsoft.AspNetCore.Sockets
public class WebSocketOptions
{
public TimeSpan CloseTimeout { get; set; } = TimeSpan.FromSeconds(5);
public string SubProtocol { get; set; }
}
}

View File

@ -2,10 +2,16 @@
// 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.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.SignalR.Tests.Common;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
@ -91,6 +97,56 @@ namespace Microsoft.AspNetCore.Sockets.Tests
Assert.Equal(2, authCount);
}
[ConditionalFact]
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")]
public async Task MapEndPointWithWebSocketSubProtocolSetsProtocol()
{
var host = new WebHostBuilder()
.UseUrls("http://127.0.0.1:0")
.UseKestrel()
.ConfigureServices(services =>
{
services.AddSockets();
services.AddEndPoint<MyEndPoint>();
})
.Configure(app =>
{
app.UseSockets(routes =>
{
routes.MapEndPoint<MyEndPoint>("socket", httpSocketOptions =>
{
httpSocketOptions.WebSockets.SubProtocol = "protocol1";
});
});
})
.Build();
await host.StartAsync();
var feature = host.ServerFeatures.Get<IServerAddressesFeature>();
var address = feature.Addresses.First().Replace("http", "ws") + "/socket";
var client = new ClientWebSocket();
client.Options.AddSubProtocol("protocol1");
client.Options.AddSubProtocol("protocol2");
await client.ConnectAsync(new Uri(address), CancellationToken.None);
Assert.Equal("protocol1", client.SubProtocol);
await client.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None).OrTimeout();
var result = await client.ReceiveAsync(new ArraySegment<byte>(new byte[1024]), CancellationToken.None).OrTimeout();
Assert.Equal(WebSocketMessageType.Close, result.MessageType);
}
private class MyEndPoint : EndPoint
{
public override async Task OnConnectedAsync(ConnectionContext connection)
{
while (!await connection.Transport.In.WaitToReadAsync())
{
}
}
}
private class InheritedAuthEndPoint : AuthEndPoint
{
public override Task OnConnectedAsync(ConnectionContext connection)

View File

@ -3,6 +3,8 @@
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' != 'Windows_NT'">netcoreapp2.0</TargetFrameworks>
<RuntimeIdentifier Condition="'$(TargetFramework)' != 'netcoreapp2.0'">win7-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>