Split http and non-http layers (#487)

* Split http and non-http layers
- This change introduces Microsoft.AspNetCore.SignalR.Http
and Microsoft.AspNetCore.Sockets.Http which expose extension methods
on IAppBuilder for wiring up a sockets and signalr pipeline.
This commit is contained in:
David Fowler 2017-05-24 07:09:46 -07:00 committed by GitHub
parent a31c693178
commit d55ebfeee0
38 changed files with 196 additions and 68 deletions

View File

@ -78,6 +78,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Signal
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Sockets.Abstractions", "src\Microsoft.AspNetCore.Sockets.Abstractions\Microsoft.AspNetCore.Sockets.Abstractions.csproj", "{F2E4FBD6-9AEA-4A82-BAC9-3FAACA677DF8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Http", "src\Microsoft.AspNetCore.SignalR.Http\Microsoft.AspNetCore.SignalR.Http.csproj", "{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Sockets.Http", "src\Microsoft.AspNetCore.Sockets.Http\Microsoft.AspNetCore.Sockets.Http.csproj", "{9E403E93-3284-486F-9A5F-1E15FCE426A5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -192,6 +196,14 @@ Global
{F2E4FBD6-9AEA-4A82-BAC9-3FAACA677DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2E4FBD6-9AEA-4A82-BAC9-3FAACA677DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2E4FBD6-9AEA-4A82-BAC9-3FAACA677DF8}.Release|Any CPU.Build.0 = Release|Any CPU
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}.Release|Any CPU.Build.0 = Release|Any CPU
{9E403E93-3284-486F-9A5F-1E15FCE426A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E403E93-3284-486F-9A5F-1E15FCE426A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E403E93-3284-486F-9A5F-1E15FCE426A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E403E93-3284-486F-9A5F-1E15FCE426A5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -225,5 +237,7 @@ Global
{96771B3F-4D18-41A7-A75B-FF38E76AAC89} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
{75E342F6-5445-4E7E-9143-6D9AE62C2B1E} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
{F2E4FBD6-9AEA-4A82-BAC9-3FAACA677DF8} = {DA69F624-5398-4884-87E4-B816698CDE65}
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA} = {DA69F624-5398-4884-87E4-B816698CDE65}
{9E403E93-3284-486F-9A5F-1E15FCE426A5} = {DA69F624-5398-4884-87E4-B816698CDE65}
EndGlobalSection
EndGlobal

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Http\Microsoft.AspNetCore.SignalR.Http.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.SignalR.Client.TS\Microsoft.AspNetCore.SignalR.Client.TS.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(AspNetCoreVersion)" />

View File

@ -12,7 +12,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Redis\Microsoft.AspNetCore.SignalR.Redis.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Http\Microsoft.AspNetCore.SignalR.Http.csproj" />
<ProjectReference Include="..\..\client-ts\Microsoft.AspNetCore.SignalR.Client.TS\Microsoft.AspNetCore.SignalR.Client.TS.csproj" />
</ItemGroup>

View File

@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets.Http\Microsoft.AspNetCore.Sockets.Http.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -12,6 +12,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets.Http\Microsoft.AspNetCore.Sockets.Http.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Http\Microsoft.AspNetCore.SignalR.Http.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Redis\Microsoft.AspNetCore.SignalR.Redis.csproj" />
<ProjectReference Include="..\..\client-ts\Microsoft.AspNetCore.SignalR.Client.TS\Microsoft.AspNetCore.SignalR.Client.TS.csproj" />

View File

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Sockets;
namespace Microsoft.AspNetCore.SignalR
{
public class HubRouteBuilder
{
private readonly SocketRouteBuilder _routes;
public HubRouteBuilder(SocketRouteBuilder routes)
{
_routes = routes;
}
public void MapHub<THub>(string path) where THub : Hub<IClientProxy>
{
_routes.MapSocket(path, builder =>
{
builder.UseHub<THub>();
});
}
}
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<Description>Components for providing real-time bi-directional communication across the Web.</Description>
<TargetFramework>netcoreapp2.0</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;signalr</PackageTags>
<EnableApiCheck>false</EnableApiCheck>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets.Http\Microsoft.AspNetCore.Sockets.Http.csproj" />
</ItemGroup>
</Project>

View File

@ -10,7 +10,6 @@ namespace Microsoft.AspNetCore.Builder
{
public static IApplicationBuilder UseSignalR(this IApplicationBuilder app, Action<HubRouteBuilder> configure)
{
// REVIEW: Should we discover hubs?
app.UseSockets(routes =>
{
configure(new HubRouteBuilder(routes));
@ -19,19 +18,4 @@ namespace Microsoft.AspNetCore.Builder
return app;
}
}
public class HubRouteBuilder
{
private readonly SocketRouteBuilder _routes;
public HubRouteBuilder(SocketRouteBuilder routes)
{
_routes = routes;
}
public void MapHub<THub>(string path) where THub : Hub<IClientProxy>
{
_routes.MapEndPoint<HubEndPoint<THub>>(path);
}
}
}

View File

@ -0,0 +1,16 @@
// 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 Microsoft.AspNetCore.SignalR;
namespace Microsoft.Extensions.DependencyInjection
{
public static class SignalRDependencyInjectionExtensions
{
public static ISignalRBuilder AddSignalR(this IServiceCollection services)
{
services.AddSockets();
return services.AddSignalRCore();
}
}
}

View File

@ -13,6 +13,7 @@
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
<PackageReference Include="Microsoft.Extensions.Options" Version="$(AspNetCoreVersion)" />
<PackageReference Include="StackExchange.Redis.StrongName" Version="$(RedisVersion)" />
</ItemGroup>

View File

@ -13,7 +13,6 @@ using Microsoft.AspNetCore.Sockets;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.SignalR
{
@ -29,7 +28,7 @@ namespace Microsoft.AspNetCore.SignalR
}
}
public class HubEndPoint<THub, TClient> : EndPoint, IInvocationBinder where THub : Hub<TClient>
public class HubEndPoint<THub, TClient> : IInvocationBinder where THub : Hub<TClient>
{
private readonly Dictionary<string, HubMethodDescriptor> _methods = new Dictionary<string, HubMethodDescriptor>(StringComparer.OrdinalIgnoreCase);
@ -54,7 +53,7 @@ namespace Microsoft.AspNetCore.SignalR
DiscoverHubMethods();
}
public override async Task OnConnectedAsync(ConnectionContext connection)
public async Task OnConnectedAsync(ConnectionContext connection)
{
try
{

View File

@ -12,8 +12,10 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets.Abstractions\Microsoft.AspNetCore.Sockets.Abstractions.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.SignalR.Common\Microsoft.AspNetCore.SignalR.Common.csproj" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" Version="$(AspNetCoreVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.ObjectMethodExecutor.Sources" Version="$(AspNetCoreVersion)" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="$(JsonNetVersion)" />

View File

@ -8,15 +8,13 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class SignalRDependencyInjectionExtensions
{
public static ISignalRBuilder AddSignalR(this IServiceCollection services)
public static ISignalRBuilder AddSignalRCore(this IServiceCollection services)
{
services.AddSockets();
services.AddSingleton(typeof(HubLifetimeManager<>), typeof(DefaultHubLifetimeManager<>));
services.AddSingleton(typeof(IHubProtocolResolver), typeof(DefaultHubProtocolResolver));
services.AddSingleton(typeof(IHubContext<>), typeof(HubContext<>));
services.AddSingleton(typeof(HubEndPoint<>), typeof(HubEndPoint<>));
services.AddScoped(typeof(IHubActivator<,>), typeof(DefaultHubActivator<,>));
services.AddRouting();
return new SignalRBuilder(services);
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Sockets;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.SignalR
{
public static class SignalRSocketBuilderExtensions
{
public static ISocketBuilder UseHub<THub>(this ISocketBuilder socketBuilder) where THub : Hub<IClientProxy>
{
return socketBuilder.Run(connection =>
{
var endpoint = socketBuilder.ApplicationServices.GetRequiredService<HubEndPoint<THub>>();
return endpoint.OnConnectedAsync(connection);
});
}
}
}

View File

@ -16,8 +16,7 @@ namespace Microsoft.AspNetCore.Sockets
{
get
{
ConnectionContext connection;
if (_connections.TryGetValue(connectionId, out connection))
if (_connections.TryGetValue(connectionId, out var connection))
{
return connection;
}
@ -34,8 +33,7 @@ namespace Microsoft.AspNetCore.Sockets
public void Remove(ConnectionContext connection)
{
ConnectionContext dummy;
_connections.TryRemove(connection.ConnectionId, out dummy);
_connections.TryRemove(connection.ConnectionId, out var dummy);
}
public IEnumerator<ConnectionContext> GetEnumerator()

View File

@ -19,5 +19,16 @@ namespace Microsoft.AspNetCore.Sockets
};
});
}
public static ISocketBuilder Run(this ISocketBuilder socketBuilder, Func<ConnectionContext, Task> middleware)
{
return socketBuilder.Use(next =>
{
return context =>
{
return middleware(context);
};
});
}
}
}

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<Description>Components for providing real-time bi-directional communication across the Web.</Description>
<TargetFramework>netcoreapp2.0</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;signalr</PackageTags>
<EnableApiCheck>false</EnableApiCheck>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets.Common\Microsoft.AspNetCore.Sockets.Common.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.WebSockets.Internal\Microsoft.AspNetCore.WebSockets.Internal.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.SecurityHelper.Sources" Version="$(AspNetCoreVersion)" PrivateAssets="All" />
<PackageReference Include="System.Threading.Tasks.Channels" Version="$(CoreFxLabsVersion)" />
</ItemGroup>
</Project>

View File

@ -1,29 +1,8 @@
// 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;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Sockets;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Builder
namespace Microsoft.AspNetCore.Sockets
{
public static class HttpDispatcherAppBuilderExtensions
{
public static IApplicationBuilder UseSockets(this IApplicationBuilder app, Action<SocketRouteBuilder> callback)
{
var dispatcher = app.ApplicationServices.GetRequiredService<HttpConnectionDispatcher>();
var routes = new RouteBuilder(app);
callback(new SocketRouteBuilder(routes, dispatcher));
app.UseWebSocketConnections();
app.UseRouter(routes.Build());
return app;
}
}
public class SocketRouteBuilder
{
private readonly HttpConnectionDispatcher _dispatcher;

View File

@ -0,0 +1,26 @@
// 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 Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Sockets;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Builder
{
public static class SocketsAppBuilderExtensions
{
public static IApplicationBuilder UseSockets(this IApplicationBuilder app, Action<SocketRouteBuilder> callback)
{
var dispatcher = app.ApplicationServices.GetRequiredService<HttpConnectionDispatcher>();
var routes = new RouteBuilder(app);
callback(new SocketRouteBuilder(routes, dispatcher));
app.UseWebSocketConnections();
app.UseRouter(routes.Build());
return app;
}
}
}

View File

@ -0,0 +1,18 @@
// 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 Microsoft.AspNetCore.Sockets;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
public static class SocketsDependencyInjectionExtensions
{
public static IServiceCollection AddSockets(this IServiceCollection services)
{
services.AddRouting();
services.TryAddSingleton<HttpConnectionDispatcher>();
return services.AddSocketsCore();
}
}
}

View File

@ -8,7 +8,6 @@ namespace Microsoft.AspNetCore.Sockets
/// <summary>
/// Represents an end point that multiple connections connect to. For HTTP, endpoints are URLs, for non HTTP it can be a TCP listener (or similar)
/// </summary>
// REVIEW: This doesn't have any members any more... marker interface? Still even necessary?
public abstract class EndPoint
{
/// <summary>

View File

@ -14,11 +14,9 @@
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets.Abstractions\Microsoft.AspNetCore.Sockets.Abstractions.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets.Common\Microsoft.AspNetCore.Sockets.Common.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.WebSockets.Internal\Microsoft.AspNetCore.WebSockets.Internal.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.SecurityHelper.Sources" Version="$(AspNetCoreVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="System.Threading.Tasks.Channels" Version="$(CoreFxLabsVersion)" />
</ItemGroup>

View File

@ -8,12 +8,12 @@ using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Sockets
{
public static class HttpSocketBuilderExtensions
public static class SocketBuilderExtensions
{
public static ISocketBuilder UseEndPoint<TEndPoint>(this ISocketBuilder socketBuilder) where TEndPoint : EndPoint
{
// This is a terminal middleware, so there's no need to use the 'next' parameter
return socketBuilder.Use((connection, _) =>
return socketBuilder.Run(connection =>
{
var endpoint = socketBuilder.ApplicationServices.GetRequiredService<TEndPoint>();
return endpoint.OnConnectedAsync(connection);

View File

@ -9,12 +9,10 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class SocketsDependencyInjectionExtensions
{
public static IServiceCollection AddSockets(this IServiceCollection services)
public static IServiceCollection AddSocketsCore(this IServiceCollection services)
{
services.AddRouting();
services.TryAddSingleton<ConnectionManager>();
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, SocketsApplicationLifetimeService>());
services.TryAddSingleton<HttpConnectionDispatcher>();
return services;
}
}

View File

@ -11,7 +11,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Http\Microsoft.AspNetCore.SignalR.Http.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Client\Microsoft.AspNetCore.SignalR.Client.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(AspNetCoreVersion)" />

View File

@ -11,8 +11,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets.Http\Microsoft.AspNetCore.Sockets.Http.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Http\Microsoft.AspNetCore.SignalR.Http.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Client\Microsoft.AspNetCore.SignalR.Client.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />

View File

@ -12,7 +12,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets.Http\Microsoft.AspNetCore.Sockets.Http.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(AspNetCoreVersion)" />