React to IFeatureCollection changes.

Use a static feature collection.
This commit is contained in:
Chris R 2015-07-29 15:29:43 -07:00
parent 2b5206ac18
commit aa34e5e46e
2 changed files with 122 additions and 28 deletions

View File

@ -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.

View File

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