#267, #273, Move WebSocket APIs to their own object, fix context object.

This commit is contained in:
Chris Ross 2015-04-21 12:34:32 -07:00
parent cc1a24b949
commit 0ed2692ef4
12 changed files with 108 additions and 69 deletions

View File

@ -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<string> 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<WebSocket> AcceptWebSocketAsync()
{
return AcceptWebSocketAsync(subProtocol: null);
}
public abstract Task<WebSocket> AcceptWebSocketAsync(string subProtocol);
}
}

View File

@ -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<string> WebSocketRequestedProtocols { get; }
public virtual Task<WebSocket> AcceptWebSocketAsync()
{
return AcceptWebSocketAsync(subProtocol: null);
}
public abstract Task<WebSocket> AcceptWebSocketAsync(string subProtocol);
}
}

View File

@ -10,6 +10,6 @@ namespace Microsoft.AspNet.Http
{
bool IsWebSocketRequest { get; }
Task<WebSocket> AcceptAsync(IWebSocketAcceptContext context);
Task<WebSocket> AcceptAsync(WebSocketAcceptContext context);
}
}

View File

@ -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; }
}
}

View File

@ -3,7 +3,7 @@
namespace Microsoft.AspNet.Http
{
public class WebSocketAcceptContext : IWebSocketAcceptContext
public class WebSocketAcceptContext
{
public virtual string SubProtocol { get; set; }
}

View File

@ -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<string> EmptyList = new List<string>();
private readonly HttpRequest _request;
private readonly HttpResponse _response;
private readonly ConnectionInfo _connection;
@ -28,8 +23,8 @@ namespace Microsoft.AspNet.Http
private FeatureReference<IServiceProvidersFeature> _serviceProviders;
private FeatureReference<IHttpAuthenticationFeature> _authentication;
private FeatureReference<IHttpRequestLifetimeFeature> _lifetime;
private FeatureReference<IHttpWebSocketFeature> _webSockets;
private FeatureReference<ISessionFeature> _session;
private WebSocketManager _websockets;
private IFeatureCollection _features;
public DefaultHttpContext()
@ -51,7 +46,6 @@ namespace Microsoft.AspNet.Http
_serviceProviders = FeatureReference<IServiceProvidersFeature>.Default;
_authentication = FeatureReference<IHttpAuthenticationFeature>.Default;
_lifetime = FeatureReference<IHttpRequestLifetimeFeature>.Default;
_webSockets = FeatureReference<IHttpWebSocketFeature>.Default;
_session = FeatureReference<ISessionFeature>.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<string> 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<WebSocket> AcceptWebSocketAsync(string subProtocol)
{
var webSocketFeature = WebSocketFeature;
if (WebSocketFeature == null)
{
throw new NotSupportedException("WebSockets are not supported");
}
return WebSocketFeature.AcceptAsync(new WebSocketAcceptContext() { SubProtocol = subProtocol } );
}
}
}

View File

@ -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<string> EmptyList = new List<string>();
private IFeatureCollection _features;
private FeatureReference<IHttpRequestFeature> _request = FeatureReference<IHttpRequestFeature>.Default;
private FeatureReference<IHttpWebSocketFeature> _webSockets = FeatureReference<IHttpWebSocketFeature>.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<string> WebSocketRequestedProtocols
{
get
{
return ParsingHelpers.GetHeaderUnmodified(HttpRequestFeature.Headers,
HeaderNames.WebSocketSubProtocols) ?? EmptyList;
}
}
public override Task<WebSocket> AcceptWebSocketAsync(string subProtocol)
{
if (WebSocketFeature == null)
{
throw new NotSupportedException("WebSockets are not supported");
}
return WebSocketFeature.AcceptAsync(new WebSocketAcceptContext() { SubProtocol = subProtocol });
}
}
}

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Owin
using WebSocketAcceptAlt =
Func
<
IWebSocketAcceptContext, // WebSocket Accept parameters
WebSocketAcceptContext, // WebSocket Accept parameters
Task<WebSocket>
>;
@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Owin
feature => new Func<Task>(() => feature.GetClientCertificateAsync(CancellationToken.None))));
}
if (context.IsWebSocketRequest)
if (context.WebSockets.IsWebSocketRequest)
{
_entries.Add(OwinConstants.WebSocket.AcceptAlt, new FeatureMap<IHttpWebSocketFeature>(feature => new WebSocketAcceptAlt(feature.AcceptAsync)));
}

View File

@ -277,14 +277,14 @@ namespace Microsoft.AspNet.Owin
}
}
Task<WebSocket> IHttpWebSocketFeature.AcceptAsync(IWebSocketAcceptContext context)
Task<WebSocket> 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<IWebSocketAcceptContext, Task<WebSocket>>)obj;
var accept = (Func<WebSocketAcceptContext, Task<WebSocket>>)obj;
return accept(context);
}

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Owin
using WebSocketAcceptAlt =
Func
<
IWebSocketAcceptContext, // WebSocket Accept parameters
WebSocketAcceptContext, // WebSocket Accept parameters
Task<WebSocket>
>;
@ -48,7 +48,7 @@ namespace Microsoft.AspNet.Owin
private Task UpstreamTask { get; set; }
private TaskCompletionSource<int> UpstreamWentAsyncTcs { get { return _upstreamWentAsync; } }
private async Task<WebSocket> AcceptWebSocketAsync(IWebSocketAcceptContext context)
private async Task<WebSocket> AcceptWebSocketAsync(WebSocketAcceptContext context)
{
IDictionary<string, object> options = null;
if (context is OwinWebSocketAcceptContext)

View File

@ -6,7 +6,7 @@ using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Owin
{
public class OwinWebSocketAcceptContext : IWebSocketAcceptContext
public class OwinWebSocketAcceptContext : WebSocketAcceptContext
{
private IDictionary<string, object> _options;
@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Owin
_options = options;
}
public string SubProtocol
public override string SubProtocol
{
get
{

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Owin
using WebSocketAcceptAlt =
Func
<
IWebSocketAcceptContext, // WebSocket Accept parameters
WebSocketAcceptContext, // WebSocket Accept parameters
Task<WebSocket>
>;
@ -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)
{