Server: Expose WebSocketOptions. Make feature replacement configurable.

This commit is contained in:
Chris Ross 2014-06-30 12:50:55 -07:00
parent b24d808b58
commit df425e4796
5 changed files with 83 additions and 21 deletions

View File

@ -25,11 +25,13 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="WebSocketAcceptContext.cs" />
<Compile Include="WebSocketMiddleware.cs" />
<Compile Include="WebSocketMiddlewareExtensions.cs" />
<Compile Include="WebSocketOptions.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="project.json" />
</ItemGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
</Project>

View File

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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.AspNet.HttpFeature;
namespace Microsoft.AspNet.WebSockets.Server
{
public class WebSocketAcceptContext : IWebSocketAcceptContext
{
public string SubProtocol { get; set; }
public int? ReceiveBufferSize { get; set; }
public TimeSpan? KeepAliveInterval { get; set; }
// public ArraySegment<byte>? Buffer { get; set; } // TODO
}
}

View File

@ -15,21 +15,27 @@ namespace Microsoft.AspNet.WebSockets.Server
{
public class WebSocketMiddleware
{
private RequestDelegate _next;
private readonly RequestDelegate _next;
private readonly WebSocketOptions _options;
public WebSocketMiddleware(RequestDelegate next)
public WebSocketMiddleware(RequestDelegate next, WebSocketOptions options)
{
_next = next;
_options = options;
// TODO: validate options.
}
public Task Invoke(HttpContext context)
{
// Detect if an opaque upgrade is available, and if websocket upgrade headers are present.
// If so, add a websocket upgrade.
// Detect if an opaque upgrade is available. If so, add a websocket upgrade.
var upgradeFeature = context.GetFeature<IHttpOpaqueUpgradeFeature>();
if (upgradeFeature != null)
{
context.SetFeature<IHttpWebSocketFeature>(new UpgradeHandshake(context, upgradeFeature));
if (_options.ReplaceFeature || context.GetFeature<IHttpWebSocketFeature>() == null)
{
context.SetFeature<IHttpWebSocketFeature>(new UpgradeHandshake(context, upgradeFeature, _options));
}
}
return _next(context);
@ -37,13 +43,15 @@ namespace Microsoft.AspNet.WebSockets.Server
private class UpgradeHandshake : IHttpWebSocketFeature
{
private HttpContext _context;
private IHttpOpaqueUpgradeFeature _upgradeFeature;
private readonly HttpContext _context;
private readonly IHttpOpaqueUpgradeFeature _upgradeFeature;
private readonly WebSocketOptions _options;
public UpgradeHandshake(HttpContext context, IHttpOpaqueUpgradeFeature upgradeFeature)
public UpgradeHandshake(HttpContext context, IHttpOpaqueUpgradeFeature upgradeFeature, WebSocketOptions options)
{
_context = context;
_upgradeFeature = upgradeFeature;
_options = options;
}
public bool IsWebSocketRequest
@ -70,7 +78,7 @@ namespace Microsoft.AspNet.WebSockets.Server
{
if (!IsWebSocketRequest)
{
throw new InvalidOperationException("Not a WebSocket request.");
throw new InvalidOperationException("Not a WebSocket request."); // TODO: LOC
}
string subProtocol = null;
@ -79,8 +87,8 @@ namespace Microsoft.AspNet.WebSockets.Server
subProtocol = acceptContext.SubProtocol;
}
TimeSpan keepAliveInterval = TimeSpan.FromMinutes(2); // TODO:
int receiveBufferSize = 4 * 1024; // TODO:
TimeSpan keepAliveInterval = _options.KeepAliveInterval;
int receiveBufferSize = _options.ReceiveBufferSize;
var advancedAcceptContext = acceptContext as WebSocketAcceptContext;
if (advancedAcceptContext != null)
{
@ -106,13 +114,5 @@ namespace Microsoft.AspNet.WebSockets.Server
return CommonWebSocket.CreateServerWebSocket(opaqueTransport, subProtocol, keepAliveInterval, receiveBufferSize);
}
}
public class WebSocketAcceptContext : IWebSocketAcceptContext
{
public string SubProtocol { get; set; }
public int? ReceiveBufferSize { get; set; }
public TimeSpan? KeepAliveInterval { get; set; }
// public ArraySegment<byte>? Buffer { get; set; } // TODO
}
}
}

View File

@ -9,7 +9,12 @@ namespace Microsoft.AspNet.Builder
{
public static IBuilder UseWebSockets(this IBuilder builder)
{
return builder.Use(next => new WebSocketMiddleware(next).Invoke);
return builder.UseWebSockets(new WebSocketOptions());
}
public static IBuilder UseWebSockets(this IBuilder builder, WebSocketOptions options) // TODO: [NotNull]
{
return builder.Use(next => new WebSocketMiddleware(next, options).Invoke);
}
}
}

View File

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNet.WebSockets.Server
{
/// <summary>
/// Configuration options for the WebSocketMiddleware
/// </summary>
public class WebSocketOptions
{
public WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromMinutes(2);
ReceiveBufferSize = 4 * 1024;
ReplaceFeature = false;
}
/// <summary>
/// Gets or sets the frequency at which to send Ping/Pong keep-alive control frames.
/// The default is two minutes.
/// </summary>
public TimeSpan KeepAliveInterval { get; set; }
/// <summary>
/// Gets or sets the size of the protocol buffer used to receive and parse frames.
/// The default is 4kb.
/// </summary>
public int ReceiveBufferSize { get; set; }
/// <summary>
/// Gets or sets if the middleware should replace the WebSocket implementation provided by
/// a component earlier in the stack. This is false by default.
/// </summary>
public bool ReplaceFeature { get; set; }
}
}