diff --git a/src/Microsoft.AspNet.Http.Core/HttpContext.cs b/src/Microsoft.AspNet.Http.Core/HttpContext.cs index 83457e775c..14646bf069 100644 --- a/src/Microsoft.AspNet.Http.Core/HttpContext.cs +++ b/src/Microsoft.AspNet.Http.Core/HttpContext.cs @@ -3,10 +3,8 @@ using System; using System.Collections.Generic; -using System.Net.WebSockets; using System.Security.Claims; using System.Threading; -using System.Threading.Tasks; using Microsoft.AspNet.Http.Authentication; namespace Microsoft.AspNet.Http @@ -33,9 +31,7 @@ namespace Microsoft.AspNet.Http public abstract ISessionCollection Session { get; } - public abstract bool IsWebSocketRequest { get; } - - public abstract IList WebSocketRequestedProtocols { get; } + public abstract WebSocketManager WebSockets { get; } public abstract void Abort(); @@ -54,12 +50,5 @@ namespace Microsoft.AspNet.Http { SetFeature(typeof(T), instance); } - - public virtual Task AcceptWebSocketAsync() - { - return AcceptWebSocketAsync(subProtocol: null); - } - - public abstract Task AcceptWebSocketAsync(string subProtocol); } } diff --git a/src/Microsoft.AspNet.Http.Core/WebSocketManager.cs b/src/Microsoft.AspNet.Http.Core/WebSocketManager.cs new file mode 100644 index 0000000000..cf7fd11f63 --- /dev/null +++ b/src/Microsoft.AspNet.Http.Core/WebSocketManager.cs @@ -0,0 +1,23 @@ +// 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.Collections.Generic; +using System.Net.WebSockets; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Http +{ + public abstract class WebSocketManager + { + public abstract bool IsWebSocketRequest { get; } + + public abstract IList WebSocketRequestedProtocols { get; } + + public virtual Task AcceptWebSocketAsync() + { + return AcceptWebSocketAsync(subProtocol: null); + } + + public abstract Task AcceptWebSocketAsync(string subProtocol); + } +} diff --git a/src/Microsoft.AspNet.Http.Interfaces/IHttpWebSocketFeature.cs b/src/Microsoft.AspNet.Http.Interfaces/IHttpWebSocketFeature.cs index 3e86058140..eb64b4bea9 100644 --- a/src/Microsoft.AspNet.Http.Interfaces/IHttpWebSocketFeature.cs +++ b/src/Microsoft.AspNet.Http.Interfaces/IHttpWebSocketFeature.cs @@ -10,6 +10,6 @@ namespace Microsoft.AspNet.Http { bool IsWebSocketRequest { get; } - Task AcceptAsync(IWebSocketAcceptContext context); + Task AcceptAsync(WebSocketAcceptContext context); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Http.Interfaces/IWebSocketAcceptContext.cs b/src/Microsoft.AspNet.Http.Interfaces/IWebSocketAcceptContext.cs deleted file mode 100644 index 81f041bb27..0000000000 --- a/src/Microsoft.AspNet.Http.Interfaces/IWebSocketAcceptContext.cs +++ /dev/null @@ -1,10 +0,0 @@ -// 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. - -namespace Microsoft.AspNet.Http -{ - public interface IWebSocketAcceptContext - { - string SubProtocol { get; set; } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Http/WebSocketAcceptContext.cs b/src/Microsoft.AspNet.Http.Interfaces/WebSocketAcceptContext.cs similarity index 81% rename from src/Microsoft.AspNet.Http/WebSocketAcceptContext.cs rename to src/Microsoft.AspNet.Http.Interfaces/WebSocketAcceptContext.cs index 34747f900f..210ec0c2b0 100644 --- a/src/Microsoft.AspNet.Http/WebSocketAcceptContext.cs +++ b/src/Microsoft.AspNet.Http.Interfaces/WebSocketAcceptContext.cs @@ -3,7 +3,7 @@ namespace Microsoft.AspNet.Http { - public class WebSocketAcceptContext : IWebSocketAcceptContext + public class WebSocketAcceptContext { public virtual string SubProtocol { get; set; } } diff --git a/src/Microsoft.AspNet.Http/DefaultHttpContext.cs b/src/Microsoft.AspNet.Http/DefaultHttpContext.cs index 7dc14893b5..65365e98b8 100644 --- a/src/Microsoft.AspNet.Http/DefaultHttpContext.cs +++ b/src/Microsoft.AspNet.Http/DefaultHttpContext.cs @@ -3,22 +3,17 @@ using System; using System.Collections.Generic; -using System.Net.WebSockets; using System.Security.Claims; using System.Threading; -using System.Threading.Tasks; using Microsoft.AspNet.FeatureModel; using Microsoft.AspNet.Http.Authentication; using Microsoft.AspNet.Http.Collections; using Microsoft.AspNet.Http.Infrastructure; -using Microsoft.Net.Http.Headers; namespace Microsoft.AspNet.Http { public class DefaultHttpContext : HttpContext { - private static IList EmptyList = new List(); - private readonly HttpRequest _request; private readonly HttpResponse _response; private readonly ConnectionInfo _connection; @@ -28,8 +23,8 @@ namespace Microsoft.AspNet.Http private FeatureReference _serviceProviders; private FeatureReference _authentication; private FeatureReference _lifetime; - private FeatureReference _webSockets; private FeatureReference _session; + private WebSocketManager _websockets; private IFeatureCollection _features; public DefaultHttpContext() @@ -51,7 +46,6 @@ namespace Microsoft.AspNet.Http _serviceProviders = FeatureReference.Default; _authentication = FeatureReference.Default; _lifetime = FeatureReference.Default; - _webSockets = FeatureReference.Default; _session = FeatureReference.Default; } @@ -75,11 +69,6 @@ namespace Microsoft.AspNet.Http get { return _lifetime.Fetch(_features); } } - private IHttpWebSocketFeature WebSocketFeature - { - get { return _webSockets.Fetch(_features); } - } - private ISessionFeature SessionFeature { get { return _session.Fetch(_features); } @@ -161,20 +150,15 @@ namespace Microsoft.AspNet.Http } } - public override bool IsWebSocketRequest + public override WebSocketManager WebSockets { get { - var webSocketFeature = WebSocketFeature; - return webSocketFeature != null && webSocketFeature.IsWebSocketRequest; - } - } - - public override IList WebSocketRequestedProtocols - { - get - { - return Request.Headers.GetValues(HeaderNames.WebSocketSubProtocols) ?? EmptyList; + if (_websockets == null) + { + _websockets = new DefaultWebSocketManager(_features); + } + return _websockets; } } @@ -203,15 +187,5 @@ namespace Microsoft.AspNet.Http { _features[type] = instance; } - - public override Task AcceptWebSocketAsync(string subProtocol) - { - var webSocketFeature = WebSocketFeature; - if (WebSocketFeature == null) - { - throw new NotSupportedException("WebSockets are not supported"); - } - return WebSocketFeature.AcceptAsync(new WebSocketAcceptContext() { SubProtocol = subProtocol } ); - } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Http/DefaultWebSocketManager.cs b/src/Microsoft.AspNet.Http/DefaultWebSocketManager.cs new file mode 100644 index 0000000000..c1845c66e5 --- /dev/null +++ b/src/Microsoft.AspNet.Http/DefaultWebSocketManager.cs @@ -0,0 +1,63 @@ +// 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 System.Collections.Generic; +using System.Net.WebSockets; +using System.Threading.Tasks; +using Microsoft.AspNet.FeatureModel; +using Microsoft.AspNet.Http.Infrastructure; +using Microsoft.Net.Http.Headers; + +namespace Microsoft.AspNet.Http +{ + public class DefaultWebSocketManager : WebSocketManager + { + private static IList EmptyList = new List(); + + private IFeatureCollection _features; + private FeatureReference _request = FeatureReference.Default; + private FeatureReference _webSockets = FeatureReference.Default; + + public DefaultWebSocketManager(IFeatureCollection features) + { + _features = features; + } + + private IHttpRequestFeature HttpRequestFeature + { + get { return _request.Fetch(_features); } + } + + private IHttpWebSocketFeature WebSocketFeature + { + get { return _webSockets.Fetch(_features); } + } + + public override bool IsWebSocketRequest + { + get + { + return WebSocketFeature != null && WebSocketFeature.IsWebSocketRequest; + } + } + + public override IList WebSocketRequestedProtocols + { + get + { + return ParsingHelpers.GetHeaderUnmodified(HttpRequestFeature.Headers, + HeaderNames.WebSocketSubProtocols) ?? EmptyList; + } + } + + public override Task AcceptWebSocketAsync(string subProtocol) + { + if (WebSocketFeature == null) + { + throw new NotSupportedException("WebSockets are not supported"); + } + return WebSocketFeature.AcceptAsync(new WebSocketAcceptContext() { SubProtocol = subProtocol }); + } + } +} diff --git a/src/Microsoft.AspNet.Owin/OwinEnvironment.cs b/src/Microsoft.AspNet.Owin/OwinEnvironment.cs index 75b1c88067..9dfae8a833 100644 --- a/src/Microsoft.AspNet.Owin/OwinEnvironment.cs +++ b/src/Microsoft.AspNet.Owin/OwinEnvironment.cs @@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Owin using WebSocketAcceptAlt = Func < - IWebSocketAcceptContext, // WebSocket Accept parameters + WebSocketAcceptContext, // WebSocket Accept parameters Task >; @@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Owin feature => new Func(() => feature.GetClientCertificateAsync(CancellationToken.None)))); } - if (context.IsWebSocketRequest) + if (context.WebSockets.IsWebSocketRequest) { _entries.Add(OwinConstants.WebSocket.AcceptAlt, new FeatureMap(feature => new WebSocketAcceptAlt(feature.AcceptAsync))); } diff --git a/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs b/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs index 50d58adb9c..195fb04cb0 100644 --- a/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs +++ b/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs @@ -277,14 +277,14 @@ namespace Microsoft.AspNet.Owin } } - Task IHttpWebSocketFeature.AcceptAsync(IWebSocketAcceptContext context) + Task IHttpWebSocketFeature.AcceptAsync(WebSocketAcceptContext context) { object obj; if (!Environment.TryGetValue(OwinConstants.WebSocket.AcceptAlt, out obj)) { throw new NotSupportedException("WebSockets are not supported"); // TODO: LOC } - var accept = (Func>)obj; + var accept = (Func>)obj; return accept(context); } diff --git a/src/Microsoft.AspNet.Owin/WebSockets/OwinWebSocketAcceptAdapter.cs b/src/Microsoft.AspNet.Owin/WebSockets/OwinWebSocketAcceptAdapter.cs index 07b58bc27e..50448cd560 100644 --- a/src/Microsoft.AspNet.Owin/WebSockets/OwinWebSocketAcceptAdapter.cs +++ b/src/Microsoft.AspNet.Owin/WebSockets/OwinWebSocketAcceptAdapter.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Owin using WebSocketAcceptAlt = Func < - IWebSocketAcceptContext, // WebSocket Accept parameters + WebSocketAcceptContext, // WebSocket Accept parameters Task >; @@ -48,7 +48,7 @@ namespace Microsoft.AspNet.Owin private Task UpstreamTask { get; set; } private TaskCompletionSource UpstreamWentAsyncTcs { get { return _upstreamWentAsync; } } - private async Task AcceptWebSocketAsync(IWebSocketAcceptContext context) + private async Task AcceptWebSocketAsync(WebSocketAcceptContext context) { IDictionary options = null; if (context is OwinWebSocketAcceptContext) diff --git a/src/Microsoft.AspNet.Owin/WebSockets/OwinWebSocketAcceptContext.cs b/src/Microsoft.AspNet.Owin/WebSockets/OwinWebSocketAcceptContext.cs index 56bc445f77..45cacf76ab 100644 --- a/src/Microsoft.AspNet.Owin/WebSockets/OwinWebSocketAcceptContext.cs +++ b/src/Microsoft.AspNet.Owin/WebSockets/OwinWebSocketAcceptContext.cs @@ -6,7 +6,7 @@ using Microsoft.AspNet.Http; namespace Microsoft.AspNet.Owin { - public class OwinWebSocketAcceptContext : IWebSocketAcceptContext + public class OwinWebSocketAcceptContext : WebSocketAcceptContext { private IDictionary _options; @@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Owin _options = options; } - public string SubProtocol + public override string SubProtocol { get { diff --git a/src/Microsoft.AspNet.Owin/WebSockets/WebSocketAcceptAdapter.cs b/src/Microsoft.AspNet.Owin/WebSockets/WebSocketAcceptAdapter.cs index 8a7d7aa0cf..71efc5490b 100644 --- a/src/Microsoft.AspNet.Owin/WebSockets/WebSocketAcceptAdapter.cs +++ b/src/Microsoft.AspNet.Owin/WebSockets/WebSocketAcceptAdapter.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Owin using WebSocketAcceptAlt = Func < - IWebSocketAcceptContext, // WebSocket Accept parameters + WebSocketAcceptContext, // WebSocket Accept parameters Task >; @@ -65,11 +65,11 @@ namespace Microsoft.AspNet.Owin await next(environment); if ((int)environment[OwinConstants.ResponseStatusCode] == 101 && adapter._callback != null) { - IWebSocketAcceptContext acceptContext = null; + WebSocketAcceptContext acceptContext = null; object obj; - if (adapter._options != null && adapter._options.TryGetValue(typeof(IWebSocketAcceptContext).FullName, out obj)) + if (adapter._options != null && adapter._options.TryGetValue(typeof(WebSocketAcceptContext).FullName, out obj)) { - acceptContext = obj as IWebSocketAcceptContext; + acceptContext = obj as WebSocketAcceptContext; } else if (adapter._options != null) {