diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.FeatureCollection.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.FeatureCollection.cs index a8e0e92a74..0fa8447d8f 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.FeatureCollection.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.FeatureCollection.cs @@ -22,8 +22,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http private string _pathBase; private int _featureRevision; - private Dictionary Extra => MaybeExtra ?? Interlocked.CompareExchange(ref MaybeExtra, new Dictionary(), null); - private Dictionary MaybeExtra; + private List> MaybeExtra; public void ResetFeatureCollection() { diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.Generated.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.Generated.cs index 3339bb30a8..4d336eb9e0 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.Generated.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.Generated.cs @@ -9,20 +9,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http private static readonly Type IHttpRequestFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestFeature); private static readonly Type IHttpResponseFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpResponseFeature); private static readonly Type IHttpRequestIdentifierFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature); - private static readonly Type IHttpSendFileFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature); private static readonly Type IServiceProvidersFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature); - private static readonly Type IHttpAuthenticationFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature); private static readonly Type IHttpRequestLifetimeFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature); + private static readonly Type IHttpConnectionFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature); + private static readonly Type IHttpAuthenticationFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature); private static readonly Type IQueryFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature); private static readonly Type IFormFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Internal.IFormFeature); - private static readonly Type IResponseCookiesFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Internal.IResponseCookiesFeature); - private static readonly Type IItemsFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Internal.IItemsFeature); - private static readonly Type IHttpConnectionFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature); - private static readonly Type ITlsConnectionFeatureType = typeof(global::Microsoft.AspNet.Http.Features.ITlsConnectionFeature); - private static readonly Type IHttpUpgradeFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature); - private static readonly Type IHttpWebSocketFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpWebSocketFeature); - private static readonly Type ISessionFeatureType = typeof(global::Microsoft.AspNet.Http.Features.ISessionFeature); - private static readonly Type IHttpSendFileFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature); private static readonly Type IHttpUpgradeFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature); private static readonly Type IResponseCookiesFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Internal.IResponseCookiesFeature); private static readonly Type IItemsFeatureType = typeof(global::Microsoft.AspNet.Http.Features.Internal.IItemsFeature); @@ -73,7 +65,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestFeature)) { - return _currentIHttpRequestFeature; } if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpResponseFeature)) @@ -82,67 +73,31 @@ namespace Microsoft.AspNet.Server.Kestrel.Http } if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature)) { - if ((_featureOverridenFlags & flagIHttpSendFileFeature) == 0L) - { - return this; - } - return SlowFeatureGet(key); + return _currentIHttpRequestIdentifierFeature; } if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature)) { - if ((_featureOverridenFlags & flagIServiceProvidersFeature) == 0L) - { - return this; - } - return SlowFeatureGet(key); - } - if (key == IHttpAuthenticationFeatureType) - { - if ((_featureOverridenFlags & flagIHttpAuthenticationFeature) == 0L) - { - return this; - } - return SlowFeatureGet(key); + return _currentIServiceProvidersFeature; } if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature)) { - if ((_featureOverridenFlags & flagIHttpRequestLifetimeFeature) == 0L) - { - return this; - } - return SlowFeatureGet(key); + return _currentIHttpRequestLifetimeFeature; } - if (key == IQueryFeatureType) + if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature)) { - if ((_featureOverridenFlags & flagIQueryFeature) == 0L) - { - return this; - } - return SlowFeatureGet(key); + return _currentIHttpConnectionFeature; } - if (key == IFormFeatureType) + if (key == typeof(global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature)) { - if ((_featureOverridenFlags & flagIFormFeature) == 0L) - { - return this; - } - return SlowFeatureGet(key); + return _currentIHttpAuthenticationFeature; } - if (key == IResponseCookiesFeatureType) + if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature)) { - if ((_featureOverridenFlags & flagIResponseCookiesFeature) == 0L) - { - return this; - } - return SlowFeatureGet(key); + return _currentIQueryFeature; } - if (key == IItemsFeatureType) + if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IFormFeature)) { - if ((_featureOverridenFlags & flagIItemsFeature) == 0L) - { - return this; - } - return SlowFeatureGet(key); + return _currentIFormFeature; } if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature)) { @@ -172,14 +127,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { return _currentIHttpSendFileFeature; } - return ExtraFeatureGet(key); } - private void FastFeatureSet(Type key, object feature) { - if (key == IHttpRequestFeatureType) + _featureRevision++; + + if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestFeature)) { _currentIHttpRequestFeature = feature; return; @@ -191,67 +146,37 @@ namespace Microsoft.AspNet.Server.Kestrel.Http } if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature)) { - FastFeatureSetInner(flagIHttpSendFileFeature, key, feature); + _currentIHttpRequestIdentifierFeature = feature; return; } if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature)) { - FastFeatureSetInner(flagIServiceProvidersFeature, key, feature); - return; - } - if (key == IHttpAuthenticationFeatureType) - { - FastFeatureSetInner(flagIHttpAuthenticationFeature, key, feature); + _currentIServiceProvidersFeature = feature; return; } if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature)) { - FastFeatureSetInner(flagIHttpRequestLifetimeFeature, key, feature); - return; - } - if (key == IQueryFeatureType) - { - FastFeatureSetInner(flagIQueryFeature, key, feature); - return; - } - if (key == IFormFeatureType) - { - FastFeatureSetInner(flagIFormFeature, key, feature); - return; - } - if (key == IResponseCookiesFeatureType) - { - FastFeatureSetInner(flagIResponseCookiesFeature, key, feature); - return; - } - if (key == IItemsFeatureType) - { - FastFeatureSetInner(flagIItemsFeature, key, feature); + _currentIHttpRequestLifetimeFeature = feature; return; } if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature)) { - FastFeatureSetInner(flagIHttpConnectionFeature, key, feature); + _currentIHttpConnectionFeature = feature; return; } - if (key == ITlsConnectionFeatureType) + if (key == typeof(global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature)) { - FastFeatureSetInner(flagITlsConnectionFeature, key, feature); + _currentIHttpAuthenticationFeature = feature; return; } - if (key == IHttpUpgradeFeatureType) + if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature)) { - FastFeatureSetInner(flagIHttpUpgradeFeature, key, feature); + _currentIQueryFeature = feature; return; } - if (key == IHttpWebSocketFeatureType) + if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IFormFeature)) { - FastFeatureSetInner(flagIHttpWebSocketFeature, key, feature); - return; - } - if (key == ISessionFeatureType) - { - FastFeatureSetInner(flagISessionFeature, key, feature); + _currentIFormFeature = feature; return; } if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature)) @@ -304,55 +229,31 @@ namespace Microsoft.AspNet.Server.Kestrel.Http } if (_currentIHttpRequestIdentifierFeature != null) { - yield return new KeyValuePair(IHttpSendFileFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature); + yield return new KeyValuePair(IHttpRequestIdentifierFeatureType, _currentIHttpRequestIdentifierFeature as global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature); } - if ((_featureOverridenFlags & flagIServiceProvidersFeature) == 0L) + if (_currentIServiceProvidersFeature != null) { - yield return new KeyValuePair(IServiceProvidersFeatureType, this as global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature); + yield return new KeyValuePair(IServiceProvidersFeatureType, _currentIServiceProvidersFeature as global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature); } - if ((_featureOverridenFlags & flagIHttpAuthenticationFeature) == 0L) + if (_currentIHttpRequestLifetimeFeature != null) { - yield return new KeyValuePair(IHttpAuthenticationFeatureType, this as global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature); + yield return new KeyValuePair(IHttpRequestLifetimeFeatureType, _currentIHttpRequestLifetimeFeature as global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature); } - if ((_featureOverridenFlags & flagIHttpRequestLifetimeFeature) == 0L) + if (_currentIHttpConnectionFeature != null) { - yield return new KeyValuePair(IHttpRequestLifetimeFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature); + yield return new KeyValuePair(IHttpConnectionFeatureType, _currentIHttpConnectionFeature as global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature); } - if ((_featureOverridenFlags & flagIQueryFeature) == 0L) + if (_currentIHttpAuthenticationFeature != null) { - yield return new KeyValuePair(IQueryFeatureType, this as global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature); + yield return new KeyValuePair(IHttpAuthenticationFeatureType, _currentIHttpAuthenticationFeature as global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature); } - if ((_featureOverridenFlags & flagIFormFeature) == 0L) + if (_currentIQueryFeature != null) { - yield return new KeyValuePair(IFormFeatureType, this as global::Microsoft.AspNet.Http.Features.Internal.IFormFeature); + yield return new KeyValuePair(IQueryFeatureType, _currentIQueryFeature as global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature); } - if ((_featureOverridenFlags & flagIResponseCookiesFeature) == 0L) + if (_currentIFormFeature != null) { - yield return new KeyValuePair(IResponseCookiesFeatureType, this as global::Microsoft.AspNet.Http.Features.Internal.IResponseCookiesFeature); - } - if ((_featureOverridenFlags & flagIItemsFeature) == 0L) - { - yield return new KeyValuePair(IItemsFeatureType, this as global::Microsoft.AspNet.Http.Features.Internal.IItemsFeature); - } - if ((_featureOverridenFlags & flagIHttpConnectionFeature) == 0L) - { - yield return new KeyValuePair(IHttpConnectionFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature); - } - if ((_featureOverridenFlags & flagITlsConnectionFeature) == 0L) - { - yield return new KeyValuePair(ITlsConnectionFeatureType, this as global::Microsoft.AspNet.Http.Features.ITlsConnectionFeature); - } - if ((_featureOverridenFlags & flagIHttpUpgradeFeature) == 0L) - { - yield return new KeyValuePair(IHttpUpgradeFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature); - } - if ((_featureOverridenFlags & flagIHttpWebSocketFeature) == 0L) - { - yield return new KeyValuePair(IHttpWebSocketFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpWebSocketFeature); - } - if ((_featureOverridenFlags & flagISessionFeature) == 0L) - { - yield return new KeyValuePair(ISessionFeatureType, this as global::Microsoft.AspNet.Http.Features.ISessionFeature); + yield return new KeyValuePair(IFormFeatureType, _currentIFormFeature as global::Microsoft.AspNet.Http.Features.Internal.IFormFeature); } if (_currentIHttpUpgradeFeature != null) { diff --git a/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/FrameFeatureCollection.cs b/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/FrameFeatureCollection.cs index 8e1cba3a5f..f8dcf8d927 100644 --- a/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/FrameFeatureCollection.cs +++ b/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/FrameFeatureCollection.cs @@ -25,26 +25,40 @@ namespace Microsoft.AspNet.Server.Kestrel.GeneratedCode public static string GeneratedFile() { - var commonFeatures = new[] + var alwaysFeatures = new[] { typeof(IHttpRequestFeature), typeof(IHttpResponseFeature), typeof(IHttpRequestIdentifierFeature), - typeof(IHttpSendFileFeature), typeof(IServiceProvidersFeature), - typeof(IHttpAuthenticationFeature), typeof(IHttpRequestLifetimeFeature), + typeof(IHttpConnectionFeature) + }; + + var commonFeatures = new[] + { + typeof(IHttpAuthenticationFeature), typeof(IQueryFeature), - typeof(IFormFeature), + typeof(IFormFeature) + }; + + var sometimesFeatures = new[] + { + typeof(IHttpUpgradeFeature), typeof(IResponseCookiesFeature), typeof(IItemsFeature), - typeof(IHttpConnectionFeature), typeof(ITlsConnectionFeature), - typeof(IHttpUpgradeFeature), typeof(IHttpWebSocketFeature), - typeof(ISessionFeature), + typeof(ISessionFeature) }; + var rareFeatures = new[] + { + typeof(IHttpSendFileFeature) + }; + + var allFeatures = alwaysFeatures.Concat(commonFeatures).Concat(sometimesFeatures).Concat(rareFeatures); + // NOTE: This list MUST always match the set of feature interfaces implemented by Frame. // See also: src/Microsoft.AspNet.Server.Kestrel/Http/Frame.FeatureCollection.cs var implementedFeatures = new[] @@ -53,7 +67,7 @@ namespace Microsoft.AspNet.Server.Kestrel.GeneratedCode typeof(IHttpResponseFeature), typeof(IHttpUpgradeFeature), }; - + return $@" using System; using System.Collections.Generic; @@ -69,7 +83,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http private void FastReset() {{{Each(implementedFeatures, feature => $@" _current{feature.Name} = this;")} - {Each(allFeatures.Where( f => !implementedFeatures.Contains(f)), feature => $@" + {Each(allFeatures.Where(f => !implementedFeatures.Contains(f)), feature => $@" _current{feature.Name} = null;")} }} @@ -79,7 +93,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http {{ return _current{feature.Name}; }}")} - return ExtraFeatureGet(key); }} @@ -101,6 +114,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http {{ yield return new KeyValuePair({feature.Name}Type, _current{feature.Name} as global::{feature.FullName}); }}")} + if (MaybeExtra != null) {{ foreach(var item in MaybeExtra)