React to IFeatureCollection changes.
Use a static feature collection.
This commit is contained in:
parent
2b5206ac18
commit
aa34e5e46e
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
private static Func<object,Task> OnStartDelegate = OnStart;
|
private static Func<object,Task> OnStartDelegate = OnStart;
|
||||||
|
|
||||||
private RequestContext _requestContext;
|
private RequestContext _requestContext;
|
||||||
private FeatureCollection _features;
|
private IFeatureCollection _features;
|
||||||
private bool _enableResponseCaching;
|
private bool _enableResponseCaching;
|
||||||
|
|
||||||
private Stream _requestBody;
|
private Stream _requestBody;
|
||||||
|
|
@ -76,11 +76,10 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
internal FeatureContext(RequestContext requestContext, bool enableResponseCaching)
|
internal FeatureContext(RequestContext requestContext, bool enableResponseCaching)
|
||||||
{
|
{
|
||||||
_requestContext = requestContext;
|
_requestContext = requestContext;
|
||||||
_features = new FeatureCollection();
|
_features = new StandardFeatureCollection(this);
|
||||||
_authHandler = new AuthenticationHandler(requestContext);
|
_authHandler = new AuthenticationHandler(requestContext);
|
||||||
_enableResponseCaching = enableResponseCaching;
|
_enableResponseCaching = enableResponseCaching;
|
||||||
requestContext.Response.OnStarting(OnStartDelegate, this);
|
requestContext.Response.OnStarting(OnStartDelegate, this);
|
||||||
PopulateFeatures();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IFeatureCollection Features
|
internal IFeatureCollection Features
|
||||||
|
|
@ -88,6 +87,11 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
get { return _features; }
|
get { return _features; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal object RequestContext
|
||||||
|
{
|
||||||
|
get { return _requestContext; }
|
||||||
|
}
|
||||||
|
|
||||||
private Request Request
|
private Request Request
|
||||||
{
|
{
|
||||||
get { return _requestContext.Request; }
|
get { return _requestContext.Request; }
|
||||||
|
|
@ -98,31 +102,6 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
get { return _requestContext.Response; }
|
get { return _requestContext.Response; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateFeatures()
|
|
||||||
{
|
|
||||||
_features.Add(typeof(IHttpRequestFeature), this);
|
|
||||||
_features.Add(typeof(IHttpConnectionFeature), this);
|
|
||||||
_features.Add(typeof(IHttpResponseFeature), this);
|
|
||||||
_features.Add(typeof(IHttpSendFileFeature), this);
|
|
||||||
_features.Add(typeof(IHttpBufferingFeature), this);
|
|
||||||
_features.Add(typeof(IHttpRequestLifetimeFeature), this);
|
|
||||||
_features.Add(typeof(IHttpAuthenticationFeature), this);
|
|
||||||
_features.Add(typeof(IHttpRequestIdentifierFeature), this);
|
|
||||||
|
|
||||||
if (Request.IsSecureConnection)
|
|
||||||
{
|
|
||||||
_features.Add(typeof(ITlsConnectionFeature), this);
|
|
||||||
_features.Add(typeof(ITlsTokenBindingFeature), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Win8+
|
|
||||||
if (WebSocketHelpers.AreWebSocketsSupported)
|
|
||||||
{
|
|
||||||
_features.Add(typeof(IHttpUpgradeFeature), this);
|
|
||||||
_features.Add(typeof(IHttpWebSocketFeature), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream IHttpRequestFeature.Body
|
Stream IHttpRequestFeature.Body
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -326,6 +305,11 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
return _clientCert;
|
return _clientCert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal ITlsConnectionFeature GetTlsConnectionFeature()
|
||||||
|
{
|
||||||
|
return Request.IsSecureConnection ? this : null;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] ITlsTokenBindingFeature.GetProvidedTokenBindingId()
|
byte[] ITlsTokenBindingFeature.GetProvidedTokenBindingId()
|
||||||
{
|
{
|
||||||
return Request.GetProvidedTokenBindingId();
|
return Request.GetProvidedTokenBindingId();
|
||||||
|
|
@ -336,6 +320,11 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
return Request.GetReferredTokenBindingId();
|
return Request.GetReferredTokenBindingId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal ITlsTokenBindingFeature GetTlsTokenBindingFeature()
|
||||||
|
{
|
||||||
|
return Request.IsSecureConnection ? this : null;
|
||||||
|
}
|
||||||
|
|
||||||
void IHttpBufferingFeature.DisableRequestBuffering()
|
void IHttpBufferingFeature.DisableRequestBuffering()
|
||||||
{
|
{
|
||||||
// There is no request buffering.
|
// There is no request buffering.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
// Copyright (c) .NET Foundation.
|
||||||
|
// All Rights Reserved
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
||||||
|
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
||||||
|
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||||
|
// NON-INFRINGEMENT.
|
||||||
|
// See the Apache 2 License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Http.Features;
|
||||||
|
using Microsoft.AspNet.Http.Features.Authentication;
|
||||||
|
using Microsoft.Net.Http.Server;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.WebListener
|
||||||
|
{
|
||||||
|
internal sealed class StandardFeatureCollection : IFeatureCollection
|
||||||
|
{
|
||||||
|
private static readonly Func<FeatureContext, object> _identityFunc = ReturnIdentity;
|
||||||
|
private static readonly Dictionary<Type, Func<FeatureContext, object>> _featureFuncLookup = new Dictionary<Type, Func<FeatureContext, object>>()
|
||||||
|
{
|
||||||
|
{ typeof(IHttpRequestFeature), _identityFunc },
|
||||||
|
{ typeof(IHttpConnectionFeature), _identityFunc },
|
||||||
|
{ typeof(IHttpResponseFeature), _identityFunc },
|
||||||
|
{ typeof(IHttpSendFileFeature), _identityFunc },
|
||||||
|
{ typeof(ITlsConnectionFeature), ctx => ctx.GetTlsConnectionFeature() },
|
||||||
|
{ typeof(ITlsTokenBindingFeature), ctx => ctx.GetTlsTokenBindingFeature() },
|
||||||
|
{ typeof(IHttpBufferingFeature), _identityFunc },
|
||||||
|
{ typeof(IHttpRequestLifetimeFeature), _identityFunc },
|
||||||
|
{ typeof(IHttpUpgradeFeature), _identityFunc },
|
||||||
|
{ typeof(IHttpWebSocketFeature), _identityFunc },
|
||||||
|
{ typeof(IHttpAuthenticationFeature), _identityFunc },
|
||||||
|
{ typeof(IHttpRequestIdentifierFeature), _identityFunc },
|
||||||
|
{ typeof(RequestContext), ctx => ctx.RequestContext },
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly FeatureContext _featureContext;
|
||||||
|
|
||||||
|
public StandardFeatureCollection(FeatureContext featureContext)
|
||||||
|
{
|
||||||
|
_featureContext = featureContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsReadOnly
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Revision
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object this[Type key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Func<FeatureContext, object> lookupFunc;
|
||||||
|
_featureFuncLookup.TryGetValue(key, out lookupFunc);
|
||||||
|
return lookupFunc?.Invoke(_featureContext);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The collection is read-only");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object ReturnIdentity(FeatureContext featureContext)
|
||||||
|
{
|
||||||
|
return featureContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return ((IEnumerable<KeyValuePair<Type, object>>)this).GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator<KeyValuePair<Type, object>> IEnumerable<KeyValuePair<Type, object>>.GetEnumerator()
|
||||||
|
{
|
||||||
|
foreach (var featureFunc in _featureFuncLookup)
|
||||||
|
{
|
||||||
|
var feature = featureFunc.Value(_featureContext);
|
||||||
|
if (feature != null)
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<Type, object>(featureFunc.Key, feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose()
|
||||||
|
{
|
||||||
|
// nothing to dispose of
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue