107 lines
3.8 KiB
C#
107 lines
3.8 KiB
C#
// Copyright (c) .NET Foundation. 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;
|
|
using System.Collections.Generic;
|
|
using Microsoft.AspNetCore.Http.Features;
|
|
using Microsoft.AspNetCore.Http.Features.Authentication;
|
|
|
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
|
{
|
|
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() }, TODO: https://github.com/aspnet/HttpSysServer/issues/231
|
|
{ typeof(IHttpBufferingFeature), _identityFunc },
|
|
{ typeof(IHttpRequestLifetimeFeature), _identityFunc },
|
|
{ typeof(IHttpAuthenticationFeature), _identityFunc },
|
|
{ typeof(IHttpRequestIdentifierFeature), _identityFunc },
|
|
{ typeof(RequestContext), ctx => ctx.RequestContext },
|
|
{ typeof(IHttpMaxRequestBodySizeFeature), _identityFunc },
|
|
{ typeof(IHttpBodyControlFeature), _identityFunc },
|
|
};
|
|
|
|
private readonly FeatureContext _featureContext;
|
|
|
|
static StandardFeatureCollection()
|
|
{
|
|
if (ComNetOS.IsWin8orLater)
|
|
{
|
|
// Only add the upgrade feature if it stands a chance of working.
|
|
// SignalR uses the presence of the feature to detect feature support.
|
|
// https://github.com/aspnet/HttpSysServer/issues/427
|
|
_featureFuncLookup[typeof(IHttpUpgradeFeature)] = _identityFunc;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
public TFeature Get<TFeature>()
|
|
{
|
|
return (TFeature)this[typeof(TFeature)];
|
|
}
|
|
|
|
public void Set<TFeature>(TFeature instance)
|
|
{
|
|
this[typeof(TFeature)] = instance;
|
|
}
|
|
}
|
|
}
|