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 RequestContext _requestContext;
|
||||
private FeatureCollection _features;
|
||||
private IFeatureCollection _features;
|
||||
private bool _enableResponseCaching;
|
||||
|
||||
private Stream _requestBody;
|
||||
|
|
@ -76,11 +76,10 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
internal FeatureContext(RequestContext requestContext, bool enableResponseCaching)
|
||||
{
|
||||
_requestContext = requestContext;
|
||||
_features = new FeatureCollection();
|
||||
_features = new StandardFeatureCollection(this);
|
||||
_authHandler = new AuthenticationHandler(requestContext);
|
||||
_enableResponseCaching = enableResponseCaching;
|
||||
requestContext.Response.OnStarting(OnStartDelegate, this);
|
||||
PopulateFeatures();
|
||||
}
|
||||
|
||||
internal IFeatureCollection Features
|
||||
|
|
@ -88,6 +87,11 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
get { return _features; }
|
||||
}
|
||||
|
||||
internal object RequestContext
|
||||
{
|
||||
get { return _requestContext; }
|
||||
}
|
||||
|
||||
private Request Request
|
||||
{
|
||||
get { return _requestContext.Request; }
|
||||
|
|
@ -98,31 +102,6 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
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
|
||||
{
|
||||
get
|
||||
|
|
@ -326,6 +305,11 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
return _clientCert;
|
||||
}
|
||||
|
||||
internal ITlsConnectionFeature GetTlsConnectionFeature()
|
||||
{
|
||||
return Request.IsSecureConnection ? this : null;
|
||||
}
|
||||
|
||||
byte[] ITlsTokenBindingFeature.GetProvidedTokenBindingId()
|
||||
{
|
||||
return Request.GetProvidedTokenBindingId();
|
||||
|
|
@ -336,6 +320,11 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
return Request.GetReferredTokenBindingId();
|
||||
}
|
||||
|
||||
internal ITlsTokenBindingFeature GetTlsTokenBindingFeature()
|
||||
{
|
||||
return Request.IsSecureConnection ? this : null;
|
||||
}
|
||||
|
||||
void IHttpBufferingFeature.DisableRequestBuffering()
|
||||
{
|
||||
// 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