Merge branch 'lodejard/featurereferences' into dev
This commit is contained in:
commit
364a712cb3
|
|
@ -0,0 +1,54 @@
|
||||||
|
// 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 Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Http.Features;
|
||||||
|
using Microsoft.AspNet.Http.Internal;
|
||||||
|
|
||||||
|
namespace SampleApp
|
||||||
|
{
|
||||||
|
public class PooledHttpContext : DefaultHttpContext
|
||||||
|
{
|
||||||
|
DefaultHttpRequest _pooledHttpRequest;
|
||||||
|
DefaultHttpResponse _pooledHttpResponse;
|
||||||
|
|
||||||
|
public PooledHttpContext(IFeatureCollection featureCollection) :
|
||||||
|
base(featureCollection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override HttpRequest InitializeHttpRequest()
|
||||||
|
{
|
||||||
|
if (_pooledHttpRequest != null)
|
||||||
|
{
|
||||||
|
_pooledHttpRequest.Initialize(this, Features);
|
||||||
|
return _pooledHttpRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DefaultHttpRequest(this, Features);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UninitializeHttpRequest(HttpRequest instance)
|
||||||
|
{
|
||||||
|
_pooledHttpRequest = instance as DefaultHttpRequest;
|
||||||
|
_pooledHttpRequest?.Uninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override HttpResponse InitializeHttpResponse()
|
||||||
|
{
|
||||||
|
if (_pooledHttpResponse != null)
|
||||||
|
{
|
||||||
|
_pooledHttpResponse.Initialize(this, Features);
|
||||||
|
return _pooledHttpResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DefaultHttpResponse(this, Features);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UninitializeHttpResponse(HttpResponse instance)
|
||||||
|
{
|
||||||
|
_pooledHttpResponse = instance as DefaultHttpResponse;
|
||||||
|
_pooledHttpResponse?.Uninitialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Http.Features;
|
||||||
|
|
||||||
|
namespace SampleApp
|
||||||
|
{
|
||||||
|
public class PooledHttpContextFactory : IHttpContextFactory
|
||||||
|
{
|
||||||
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
private readonly Stack<PooledHttpContext> _pool = new Stack<PooledHttpContext>();
|
||||||
|
|
||||||
|
public PooledHttpContextFactory(IHttpContextAccessor httpContextAccessor)
|
||||||
|
{
|
||||||
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpContext Create(IFeatureCollection featureCollection)
|
||||||
|
{
|
||||||
|
PooledHttpContext httpContext = null;
|
||||||
|
lock (_pool)
|
||||||
|
{
|
||||||
|
if (_pool.Count != 0)
|
||||||
|
{
|
||||||
|
httpContext = _pool.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (httpContext == null)
|
||||||
|
{
|
||||||
|
httpContext = new PooledHttpContext(featureCollection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
httpContext.Initialize(featureCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_httpContextAccessor != null)
|
||||||
|
{
|
||||||
|
_httpContextAccessor.HttpContext = httpContext;
|
||||||
|
}
|
||||||
|
return httpContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
if (_httpContextAccessor != null)
|
||||||
|
{
|
||||||
|
_httpContextAccessor.HttpContext = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pooled = httpContext as PooledHttpContext;
|
||||||
|
if (pooled != null)
|
||||||
|
{
|
||||||
|
pooled.Uninitialize();
|
||||||
|
lock (_pool)
|
||||||
|
{
|
||||||
|
_pool.Push(pooled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Http.Features
|
||||||
|
{
|
||||||
|
public struct FeatureReferences<TCache>
|
||||||
|
{
|
||||||
|
public FeatureReferences(IFeatureCollection collection)
|
||||||
|
{
|
||||||
|
Collection = collection;
|
||||||
|
Cache = default(TCache);
|
||||||
|
Revision = collection.Revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFeatureCollection Collection { get; private set; }
|
||||||
|
public int Revision { get; private set; }
|
||||||
|
|
||||||
|
// cache is a public field because the code calling Fetch must
|
||||||
|
// be able to pass ref values that "dot through" the TCache struct memory,
|
||||||
|
// if it was a Property then that getter would return a copy of the memory
|
||||||
|
// preventing the use of "ref"
|
||||||
|
public TCache Cache;
|
||||||
|
|
||||||
|
public TFeature Fetch<TFeature, TState>(
|
||||||
|
ref TFeature cached,
|
||||||
|
TState state,
|
||||||
|
Func<TState, TFeature> factory)
|
||||||
|
{
|
||||||
|
var cleared = false;
|
||||||
|
if (Revision != Collection.Revision)
|
||||||
|
{
|
||||||
|
cleared = true;
|
||||||
|
Cache = default(TCache);
|
||||||
|
Revision = Collection.Revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
var feature = cached;
|
||||||
|
if (feature == null)
|
||||||
|
{
|
||||||
|
feature = Collection.Get<TFeature>();
|
||||||
|
if (feature == null)
|
||||||
|
{
|
||||||
|
feature = factory(state);
|
||||||
|
|
||||||
|
Collection.Set(feature);
|
||||||
|
if (!cleared)
|
||||||
|
{
|
||||||
|
Cache = default(TCache);
|
||||||
|
}
|
||||||
|
Revision = Collection.Revision;
|
||||||
|
}
|
||||||
|
cached = feature;
|
||||||
|
}
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TFeature Fetch<TFeature>(ref TFeature cached, Func<IFeatureCollection, TFeature> factory) =>
|
||||||
|
Fetch(ref cached, Collection, factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,56 +12,27 @@ using Microsoft.AspNet.Http.Features.Authentication.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Authentication.Internal
|
namespace Microsoft.AspNet.Http.Authentication.Internal
|
||||||
{
|
{
|
||||||
public class DefaultAuthenticationManager : AuthenticationManager, IFeatureCache
|
public class DefaultAuthenticationManager : AuthenticationManager
|
||||||
{
|
{
|
||||||
private IFeatureCollection _features;
|
private FeatureReferences<IHttpAuthenticationFeature> _features;
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
private IHttpAuthenticationFeature _authentication;
|
|
||||||
|
|
||||||
public DefaultAuthenticationManager(IFeatureCollection features)
|
public DefaultAuthenticationManager(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
_features = features;
|
Initialize(features);
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
public virtual void Initialize(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
if (_cachedFeaturesRevision != _features.Revision)
|
_features = new FeatureReferences<IHttpAuthenticationFeature>(features);
|
||||||
{
|
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
public virtual void Uninitialize()
|
||||||
{
|
{
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
_features = default(FeatureReferences<IHttpAuthenticationFeature>);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateFeatures(IFeatureCollection features)
|
private IHttpAuthenticationFeature HttpAuthenticationFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache, f => new HttpAuthenticationFeature());
|
||||||
_features = features;
|
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetFeatures()
|
|
||||||
{
|
|
||||||
_authentication = null;
|
|
||||||
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpAuthenticationFeature HttpAuthenticationFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
|
||||||
this,
|
|
||||||
_features,
|
|
||||||
() => new HttpAuthenticationFeature(),
|
|
||||||
ref _authentication);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<AuthenticationDescription> GetAuthenticationSchemes()
|
public override IEnumerable<AuthenticationDescription> GetAuthenticationSchemes()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,70 +10,30 @@ using Microsoft.AspNet.Http.Features.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Internal
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
public class DefaultConnectionInfo : ConnectionInfo, IFeatureCache
|
public class DefaultConnectionInfo : ConnectionInfo
|
||||||
{
|
{
|
||||||
private IFeatureCollection _features;
|
private FeatureReferences<FeatureInterfaces> _features;
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
private IHttpConnectionFeature _connection;
|
|
||||||
private ITlsConnectionFeature _tlsConnection;
|
|
||||||
|
|
||||||
public DefaultConnectionInfo(IFeatureCollection features)
|
public DefaultConnectionInfo(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
_features = features;
|
Initialize(features);
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
public virtual void Initialize( IFeatureCollection features)
|
||||||
{
|
{
|
||||||
if (_cachedFeaturesRevision != _features.Revision)
|
_features = new FeatureReferences<FeatureInterfaces>(features);
|
||||||
{
|
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
public virtual void Uninitialize()
|
||||||
{
|
{
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
_features = default(FeatureReferences<FeatureInterfaces>);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateFeatures(IFeatureCollection features)
|
private IHttpConnectionFeature HttpConnectionFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.Connection, f => new HttpConnectionFeature());
|
||||||
_features = features;
|
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetFeatures()
|
private ITlsConnectionFeature TlsConnectionFeature=>
|
||||||
{
|
_features.Fetch(ref _features.Cache.TlsConnection, f => new TlsConnectionFeature());
|
||||||
_connection = null;
|
|
||||||
_tlsConnection = null;
|
|
||||||
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpConnectionFeature HttpConnectionFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
|
||||||
this,
|
|
||||||
_features,
|
|
||||||
() => new HttpConnectionFeature(),
|
|
||||||
ref _connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ITlsConnectionFeature TlsConnectionFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
|
||||||
this,
|
|
||||||
_features,
|
|
||||||
() => new TlsConnectionFeature(),
|
|
||||||
ref _tlsConnection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IPAddress RemoteIpAddress
|
public override IPAddress RemoteIpAddress
|
||||||
{
|
{
|
||||||
|
|
@ -115,5 +75,11 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
return TlsConnectionFeature.GetClientCertificateAsync(cancellationToken);
|
return TlsConnectionFeature.GetClientCertificateAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FeatureInterfaces
|
||||||
|
{
|
||||||
|
public IHttpConnectionFeature Connection;
|
||||||
|
public ITlsConnectionFeature TlsConnection;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,173 +14,99 @@ using Microsoft.AspNet.Http.Features.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Internal
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
public class DefaultHttpContext : HttpContext, IFeatureCache
|
public class DefaultHttpContext : HttpContext
|
||||||
{
|
{
|
||||||
private readonly DefaultHttpRequest _request;
|
private FeatureReferences<FeatureInterfaces> _features;
|
||||||
private readonly DefaultHttpResponse _response;
|
|
||||||
|
|
||||||
private DefaultAuthenticationManager _authenticationManager;
|
private HttpRequest _request;
|
||||||
private DefaultConnectionInfo _connection;
|
private HttpResponse _response;
|
||||||
private DefaultWebSocketManager _websockets;
|
private AuthenticationManager _authenticationManager;
|
||||||
|
private ConnectionInfo _connection;
|
||||||
private IItemsFeature _items;
|
private WebSocketManager _websockets;
|
||||||
private IServiceProvidersFeature _serviceProviders;
|
|
||||||
private IHttpAuthenticationFeature _authentication;
|
|
||||||
private IHttpRequestLifetimeFeature _lifetime;
|
|
||||||
private ISessionFeature _session;
|
|
||||||
|
|
||||||
private IFeatureCollection _features;
|
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
public DefaultHttpContext()
|
public DefaultHttpContext()
|
||||||
: this(new FeatureCollection())
|
: this(new FeatureCollection())
|
||||||
{
|
{
|
||||||
_features.Set<IHttpRequestFeature>(new HttpRequestFeature());
|
Features.Set<IHttpRequestFeature>(new HttpRequestFeature());
|
||||||
_features.Set<IHttpResponseFeature>(new HttpResponseFeature());
|
Features.Set<IHttpResponseFeature>(new HttpResponseFeature());
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultHttpContext(IFeatureCollection features)
|
public DefaultHttpContext(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
_features = features;
|
Initialize(features);
|
||||||
_request = new DefaultHttpRequest(this, features);
|
|
||||||
_response = new DefaultHttpResponse(this, features);
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
public virtual void Initialize(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
if (_cachedFeaturesRevision !=_features.Revision)
|
_features = new FeatureReferences<FeatureInterfaces>(features);
|
||||||
|
_request = InitializeHttpRequest();
|
||||||
|
_response = InitializeHttpResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Uninitialize()
|
||||||
|
{
|
||||||
|
_features = default(FeatureReferences<FeatureInterfaces>);
|
||||||
|
if (_request != null)
|
||||||
{
|
{
|
||||||
ResetFeatures();
|
UninitializeHttpRequest(_request);
|
||||||
|
_request = null;
|
||||||
}
|
}
|
||||||
}
|
if (_response != null)
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
|
||||||
{
|
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateFeatures(IFeatureCollection features)
|
|
||||||
{
|
|
||||||
_features = features;
|
|
||||||
ResetFeatures();
|
|
||||||
|
|
||||||
_request.UpdateFeatures(features);
|
|
||||||
_response.UpdateFeatures(features);
|
|
||||||
|
|
||||||
_authenticationManager?.UpdateFeatures(features);
|
|
||||||
_connection?.UpdateFeatures(features);
|
|
||||||
_websockets?.UpdateFeatures(features);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetFeatures()
|
|
||||||
{
|
|
||||||
_items = null;
|
|
||||||
_serviceProviders = null;
|
|
||||||
_authentication = null;
|
|
||||||
_lifetime = null;
|
|
||||||
_session = null;
|
|
||||||
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
|
|
||||||
IItemsFeature ItemsFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
{
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
UninitializeHttpResponse(_response);
|
||||||
this,
|
_response = null;
|
||||||
_features,
|
|
||||||
() => new ItemsFeature(),
|
|
||||||
ref _items);
|
|
||||||
}
|
}
|
||||||
}
|
if (_authenticationManager != null)
|
||||||
|
|
||||||
IServiceProvidersFeature ServiceProvidersFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
{
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
UninitializeAuthenticationManager(_authenticationManager);
|
||||||
this,
|
_authenticationManager = null;
|
||||||
_features,
|
|
||||||
() => new ServiceProvidersFeature(),
|
|
||||||
ref _serviceProviders);
|
|
||||||
}
|
}
|
||||||
}
|
if (_connection != null)
|
||||||
|
|
||||||
private IHttpAuthenticationFeature HttpAuthenticationFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
{
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
UninitializeConnectionInfo(_connection);
|
||||||
this,
|
_connection = null;
|
||||||
_features,
|
|
||||||
() => new HttpAuthenticationFeature(),
|
|
||||||
ref _authentication);
|
|
||||||
}
|
}
|
||||||
}
|
if (_websockets != null)
|
||||||
|
|
||||||
private IHttpRequestLifetimeFeature LifetimeFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
{
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
UninitializeWebSocketManager(_websockets);
|
||||||
this,
|
_websockets = null;
|
||||||
_features,
|
|
||||||
() => new HttpRequestLifetimeFeature(),
|
|
||||||
ref _lifetime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IItemsFeature ItemsFeature =>
|
||||||
|
_features.Fetch(ref _features.Cache.Items, f => new ItemsFeature());
|
||||||
|
|
||||||
private ISessionFeature SessionFeature
|
private IServiceProvidersFeature ServiceProvidersFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.ServiceProviders, f => new ServiceProvidersFeature());
|
||||||
get { return FeatureHelpers.GetAndCache(this, _features, ref _session); }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_features.Set(value);
|
|
||||||
_session = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpRequestIdentifierFeature RequestIdentifierFeature
|
private IHttpAuthenticationFeature HttpAuthenticationFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.Authentication, f => new HttpAuthenticationFeature());
|
||||||
get {
|
|
||||||
return FeatureHelpers.GetOrCreate<IHttpRequestIdentifierFeature>(
|
|
||||||
_features,
|
|
||||||
() => new HttpRequestIdentifierFeature());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IFeatureCollection Features { get { return _features; } }
|
private IHttpRequestLifetimeFeature LifetimeFeature =>
|
||||||
|
_features.Fetch(ref _features.Cache.Lifetime, f => new HttpRequestLifetimeFeature());
|
||||||
|
|
||||||
public override HttpRequest Request { get { return _request; } }
|
private ISessionFeature SessionFeature =>
|
||||||
|
_features.Fetch(ref _features.Cache.Session, f => new DefaultSessionFeature());
|
||||||
|
|
||||||
public override HttpResponse Response { get { return _response; } }
|
private ISessionFeature SessionFeatureOrNull =>
|
||||||
|
_features.Fetch(ref _features.Cache.Session, f => null);
|
||||||
|
|
||||||
public override ConnectionInfo Connection
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_connection == null)
|
|
||||||
{
|
|
||||||
_connection = new DefaultConnectionInfo(_features);
|
|
||||||
}
|
|
||||||
return _connection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override AuthenticationManager Authentication
|
private IHttpRequestIdentifierFeature RequestIdentifierFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.RequestIdentifier, f => new HttpRequestIdentifierFeature());
|
||||||
get
|
|
||||||
{
|
public override IFeatureCollection Features => _features.Collection;
|
||||||
if (_authenticationManager == null)
|
|
||||||
{
|
public override HttpRequest Request => _request;
|
||||||
_authenticationManager = new DefaultAuthenticationManager(_features);
|
|
||||||
}
|
public override HttpResponse Response => _response;
|
||||||
return _authenticationManager;
|
|
||||||
}
|
public override ConnectionInfo Connection => _connection ?? (_connection = InitializeConnectionInfo());
|
||||||
}
|
|
||||||
|
public override AuthenticationManager Authentication => _authenticationManager ?? (_authenticationManager = InitializeAuthenticationManager());
|
||||||
|
|
||||||
|
public override WebSocketManager WebSockets => _websockets ?? (_websockets = InitializeWebSocketManager());
|
||||||
|
|
||||||
|
|
||||||
public override ClaimsPrincipal User
|
public override ClaimsPrincipal User
|
||||||
{
|
{
|
||||||
|
|
@ -225,7 +151,7 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var feature = SessionFeature;
|
var feature = SessionFeatureOrNull;
|
||||||
if (feature == null)
|
if (feature == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Session has not been configured for this application " +
|
throw new InvalidOperationException("Session has not been configured for this application " +
|
||||||
|
|
@ -235,31 +161,41 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var feature = SessionFeature;
|
SessionFeature.Session = value;
|
||||||
if (feature == null)
|
|
||||||
{
|
|
||||||
feature = new DefaultSessionFeature();
|
|
||||||
SessionFeature = feature;
|
|
||||||
}
|
|
||||||
feature.Session = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override WebSocketManager WebSockets
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_websockets == null)
|
|
||||||
{
|
|
||||||
_websockets = new DefaultWebSocketManager(_features);
|
|
||||||
}
|
|
||||||
return _websockets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Abort()
|
public override void Abort()
|
||||||
{
|
{
|
||||||
LifetimeFeature.Abort();
|
LifetimeFeature.Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual HttpRequest InitializeHttpRequest() => new DefaultHttpRequest(this, Features);
|
||||||
|
protected virtual void UninitializeHttpRequest(HttpRequest instance) { }
|
||||||
|
|
||||||
|
protected virtual HttpResponse InitializeHttpResponse() => new DefaultHttpResponse(this, Features);
|
||||||
|
protected virtual void UninitializeHttpResponse(HttpResponse instance) { }
|
||||||
|
|
||||||
|
protected virtual ConnectionInfo InitializeConnectionInfo() => new DefaultConnectionInfo(Features);
|
||||||
|
protected virtual void UninitializeConnectionInfo(ConnectionInfo instance) { }
|
||||||
|
|
||||||
|
protected virtual AuthenticationManager InitializeAuthenticationManager() => new DefaultAuthenticationManager(Features);
|
||||||
|
protected virtual void UninitializeAuthenticationManager(AuthenticationManager instance) { }
|
||||||
|
|
||||||
|
protected virtual WebSocketManager InitializeWebSocketManager() => new DefaultWebSocketManager(Features);
|
||||||
|
protected virtual void UninitializeWebSocketManager(WebSocketManager instance) { }
|
||||||
|
|
||||||
|
struct FeatureInterfaces
|
||||||
|
{
|
||||||
|
public IItemsFeature Items;
|
||||||
|
public IServiceProvidersFeature ServiceProviders;
|
||||||
|
public IHttpAuthenticationFeature Authentication;
|
||||||
|
public IHttpRequestLifetimeFeature Lifetime;
|
||||||
|
public ISessionFeature Session;
|
||||||
|
public IHttpRequestIdentifierFeature RequestIdentifier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,96 +11,41 @@ using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Internal
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
public class DefaultHttpRequest : HttpRequest, IFeatureCache
|
public class DefaultHttpRequest : HttpRequest
|
||||||
{
|
{
|
||||||
private readonly DefaultHttpContext _context;
|
private HttpContext _context;
|
||||||
private IFeatureCollection _features;
|
private FeatureReferences<FeatureInterfaces> _features;
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
private IHttpRequestFeature _request;
|
public DefaultHttpRequest(HttpContext context, IFeatureCollection features)
|
||||||
private IQueryFeature _query;
|
{
|
||||||
private IFormFeature _form;
|
Initialize(context, features);
|
||||||
private IRequestCookiesFeature _cookies;
|
}
|
||||||
|
|
||||||
public DefaultHttpRequest(DefaultHttpContext context, IFeatureCollection features)
|
public virtual void Initialize(HttpContext context, IFeatureCollection features)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_features = features;
|
_features = new FeatureReferences<FeatureInterfaces>(features);
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
public virtual void Uninitialize()
|
||||||
{
|
{
|
||||||
if (_cachedFeaturesRevision != _features.Revision)
|
_context = null;
|
||||||
{
|
_features = default(FeatureReferences<FeatureInterfaces>);
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
public override HttpContext HttpContext => _context;
|
||||||
{
|
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateFeatures(IFeatureCollection features)
|
private IHttpRequestFeature HttpRequestFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.Request, f => null);
|
||||||
_features = features;
|
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetFeatures()
|
private IQueryFeature QueryFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.Query, f => new QueryFeature(f));
|
||||||
_request = null;
|
|
||||||
_query = null;
|
|
||||||
_form = null;
|
|
||||||
_cookies = null;
|
|
||||||
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
private IFormFeature FormFeature =>
|
||||||
}
|
_features.Fetch(ref _features.Cache.Form, this, f => new FormFeature(f));
|
||||||
|
|
||||||
private IHttpRequestFeature HttpRequestFeature
|
private IRequestCookiesFeature RequestCookiesFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.Cookies, f => new RequestCookiesFeature(f));
|
||||||
get { return FeatureHelpers.GetAndCache(this, _features, ref _request); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQueryFeature QueryFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
|
||||||
this,
|
|
||||||
_features,
|
|
||||||
(f) => new QueryFeature(f),
|
|
||||||
ref _query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IFormFeature FormFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
|
||||||
this,
|
|
||||||
_features,
|
|
||||||
this,
|
|
||||||
(r) => new FormFeature(r),
|
|
||||||
ref _form);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IRequestCookiesFeature RequestCookiesFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
|
||||||
this,
|
|
||||||
_features,
|
|
||||||
(f) => new RequestCookiesFeature(f),
|
|
||||||
ref _cookies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override HttpContext HttpContext { get { return _context; } }
|
|
||||||
|
|
||||||
public override PathString PathBase
|
public override PathString PathBase
|
||||||
{
|
{
|
||||||
|
|
@ -206,5 +151,13 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
return FormFeature.ReadFormAsync(cancellationToken);
|
return FormFeature.ReadFormAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FeatureInterfaces
|
||||||
|
{
|
||||||
|
public IHttpRequestFeature Request;
|
||||||
|
public IQueryFeature Query;
|
||||||
|
public IFormFeature Form;
|
||||||
|
public IRequestCookiesFeature Cookies;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,65 +10,34 @@ using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Internal
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
public class DefaultHttpResponse : HttpResponse, IFeatureCache
|
public class DefaultHttpResponse : HttpResponse
|
||||||
{
|
{
|
||||||
private readonly DefaultHttpContext _context;
|
private HttpContext _context;
|
||||||
private IFeatureCollection _features;
|
private FeatureReferences<FeatureInterfaces> _features;
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
private IHttpResponseFeature _response;
|
public DefaultHttpResponse(HttpContext context, IFeatureCollection features)
|
||||||
private IResponseCookiesFeature _cookies;
|
{
|
||||||
|
Initialize(context, features);
|
||||||
|
}
|
||||||
|
|
||||||
public DefaultHttpResponse(DefaultHttpContext context, IFeatureCollection features)
|
public virtual void Initialize(HttpContext context, IFeatureCollection features)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_features = features;
|
_features = new FeatureReferences<FeatureInterfaces>(features);
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
public virtual void Uninitialize()
|
||||||
{
|
{
|
||||||
if (_cachedFeaturesRevision != _features.Revision)
|
_context = null;
|
||||||
{
|
_features = default(FeatureReferences<FeatureInterfaces>);
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
private IHttpResponseFeature HttpResponseFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.Response, f => null);
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateFeatures(IFeatureCollection features)
|
private IResponseCookiesFeature ResponseCookiesFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.Cookies, f => new ResponseCookiesFeature(f));
|
||||||
_features = features;
|
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetFeatures()
|
|
||||||
{
|
|
||||||
_response = null;
|
|
||||||
_cookies = null;
|
|
||||||
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpResponseFeature HttpResponseFeature
|
|
||||||
{
|
|
||||||
get { return FeatureHelpers.GetAndCache(this, _features, ref _response); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private IResponseCookiesFeature ResponseCookiesFeature
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return FeatureHelpers.GetOrCreateAndCache(
|
|
||||||
this,
|
|
||||||
_features,
|
|
||||||
(f) => new ResponseCookiesFeature(f),
|
|
||||||
ref _cookies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override HttpContext HttpContext { get { return _context; } }
|
public override HttpContext HttpContext { get { return _context; } }
|
||||||
|
|
||||||
|
|
@ -163,5 +132,11 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
|
|
||||||
Headers[HeaderNames.Location] = location;
|
Headers[HeaderNames.Location] = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FeatureInterfaces
|
||||||
|
{
|
||||||
|
public IHttpResponseFeature Response;
|
||||||
|
public IResponseCookiesFeature Cookies;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,56 +10,30 @@ using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Internal
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
public class DefaultWebSocketManager : WebSocketManager, IFeatureCache
|
public class DefaultWebSocketManager : WebSocketManager
|
||||||
{
|
{
|
||||||
private IFeatureCollection _features;
|
private FeatureReferences<FeatureInterfaces> _features;
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
private IHttpRequestFeature _request;
|
|
||||||
private IHttpWebSocketFeature _webSockets;
|
|
||||||
|
|
||||||
public DefaultWebSocketManager(IFeatureCollection features)
|
public DefaultWebSocketManager(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
_features = features;
|
Initialize(features);
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
public virtual void Initialize(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
if (_cachedFeaturesRevision != _features.Revision)
|
_features = new FeatureReferences<FeatureInterfaces>(features);
|
||||||
{
|
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
public virtual void Uninitialize()
|
||||||
{
|
{
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
_features = default(FeatureReferences<FeatureInterfaces>);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateFeatures(IFeatureCollection features)
|
private IHttpRequestFeature HttpRequestFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.Request, f => null);
|
||||||
_features = features;
|
|
||||||
ResetFeatures();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetFeatures()
|
private IHttpWebSocketFeature WebSocketFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache.WebSockets, f => null);
|
||||||
_request = null;
|
|
||||||
_webSockets = null;
|
|
||||||
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpRequestFeature HttpRequestFeature
|
|
||||||
{
|
|
||||||
get { return FeatureHelpers.GetAndCache(this, _features, ref _request); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpWebSocketFeature WebSocketFeature
|
|
||||||
{
|
|
||||||
get { return FeatureHelpers.GetAndCache(this, _features, ref _webSockets); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsWebSocketRequest
|
public override bool IsWebSocketRequest
|
||||||
{
|
{
|
||||||
|
|
@ -85,5 +59,11 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
}
|
}
|
||||||
return WebSocketFeature.AcceptAsync(new WebSocketAcceptContext() { SubProtocol = subProtocol });
|
return WebSocketFeature.AcceptAsync(new WebSocketAcceptContext() { SubProtocol = subProtocol });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FeatureInterfaces
|
||||||
|
{
|
||||||
|
public IHttpRequestFeature Request;
|
||||||
|
public IHttpWebSocketFeature WebSockets;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
// 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;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Features
|
|
||||||
{
|
|
||||||
internal static class FeatureHelpers
|
|
||||||
{
|
|
||||||
public static T GetAndCache<T>(
|
|
||||||
IFeatureCache cache,
|
|
||||||
IFeatureCollection features,
|
|
||||||
ref T cachedObject)
|
|
||||||
where T : class
|
|
||||||
{
|
|
||||||
cache.CheckFeaturesRevision();
|
|
||||||
|
|
||||||
T obj = cachedObject;
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
obj = features.Get<T>();
|
|
||||||
cachedObject = obj;
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T GetOrCreate<T>(
|
|
||||||
IFeatureCollection features,
|
|
||||||
Func<T> factory)
|
|
||||||
where T : class
|
|
||||||
{
|
|
||||||
T obj = features.Get<T>();
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
obj = factory();
|
|
||||||
features.Set(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static T GetOrCreateAndCache<T>(
|
|
||||||
IFeatureCache cache,
|
|
||||||
IFeatureCollection features,
|
|
||||||
Func<T> factory,
|
|
||||||
ref T cachedObject)
|
|
||||||
where T : class
|
|
||||||
{
|
|
||||||
cache.CheckFeaturesRevision();
|
|
||||||
|
|
||||||
T obj = cachedObject;
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
obj = features.Get<T>();
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
obj = factory();
|
|
||||||
}
|
|
||||||
cachedObject = obj;
|
|
||||||
features.Set(obj);
|
|
||||||
cache.SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T GetOrCreateAndCache<T>(
|
|
||||||
IFeatureCache cache,
|
|
||||||
IFeatureCollection features,
|
|
||||||
Func<IFeatureCollection, T> factory,
|
|
||||||
ref T cachedObject)
|
|
||||||
where T : class
|
|
||||||
{
|
|
||||||
cache.CheckFeaturesRevision();
|
|
||||||
|
|
||||||
T obj = cachedObject;
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
obj = features.Get<T>();
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
obj = factory(features);
|
|
||||||
}
|
|
||||||
cachedObject = obj;
|
|
||||||
features.Set(obj);
|
|
||||||
cache.SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T GetOrCreateAndCache<T>(
|
|
||||||
IFeatureCache cache,
|
|
||||||
IFeatureCollection features,
|
|
||||||
HttpRequest request,
|
|
||||||
Func<HttpRequest, T> factory,
|
|
||||||
ref T cachedObject)
|
|
||||||
where T : class
|
|
||||||
{
|
|
||||||
cache.CheckFeaturesRevision();
|
|
||||||
|
|
||||||
T obj = cachedObject;
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
obj = features.Get<T>();
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
obj = factory(request);
|
|
||||||
}
|
|
||||||
cachedObject = obj;
|
|
||||||
features.Set(obj);
|
|
||||||
cache.SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Features
|
|
||||||
{
|
|
||||||
internal interface IFeatureCache
|
|
||||||
{
|
|
||||||
void CheckFeaturesRevision();
|
|
||||||
void SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,12 +7,9 @@ using Microsoft.AspNet.WebUtilities;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Features.Internal
|
namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
{
|
{
|
||||||
public class QueryFeature : IQueryFeature, IFeatureCache
|
public class QueryFeature : IQueryFeature
|
||||||
{
|
{
|
||||||
private readonly IFeatureCollection _features;
|
private FeatureReferences<IHttpRequestFeature> _features;
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
private IHttpRequestFeature _request;
|
|
||||||
|
|
||||||
private string _original;
|
private string _original;
|
||||||
private IQueryCollection _parsedValues;
|
private IQueryCollection _parsedValues;
|
||||||
|
|
@ -34,34 +31,17 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
throw new ArgumentNullException(nameof(features));
|
throw new ArgumentNullException(nameof(features));
|
||||||
}
|
}
|
||||||
|
|
||||||
_features = features;
|
_features = new FeatureReferences<IHttpRequestFeature>(features);
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
private IHttpRequestFeature HttpRequestFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache, f => null);
|
||||||
if (_cachedFeaturesRevision != _features.Revision)
|
|
||||||
{
|
|
||||||
_request = null;
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
|
||||||
{
|
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpRequestFeature HttpRequestFeature
|
|
||||||
{
|
|
||||||
get { return FeatureHelpers.GetAndCache(this, _features, ref _request); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IQueryCollection Query
|
public IQueryCollection Query
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_features == null)
|
if (_features.Collection == null)
|
||||||
{
|
{
|
||||||
if (_parsedValues == null)
|
if (_parsedValues == null)
|
||||||
{
|
{
|
||||||
|
|
@ -91,7 +71,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_parsedValues = value;
|
_parsedValues = value;
|
||||||
if (_features != null)
|
if (_features.Collection != null)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,9 @@ using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Features.Internal
|
namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
{
|
{
|
||||||
public class RequestCookiesFeature : IRequestCookiesFeature, IFeatureCache
|
public class RequestCookiesFeature : IRequestCookiesFeature
|
||||||
{
|
{
|
||||||
private readonly IFeatureCollection _features;
|
private FeatureReferences<IHttpRequestFeature> _features;
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
private IHttpRequestFeature _request;
|
|
||||||
|
|
||||||
private StringValues _original;
|
private StringValues _original;
|
||||||
private IRequestCookieCollection _parsedValues;
|
private IRequestCookieCollection _parsedValues;
|
||||||
|
|
||||||
|
|
@ -36,34 +32,17 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
throw new ArgumentNullException(nameof(features));
|
throw new ArgumentNullException(nameof(features));
|
||||||
}
|
}
|
||||||
|
|
||||||
_features = features;
|
_features = new FeatureReferences<IHttpRequestFeature>(features);
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
private IHttpRequestFeature HttpRequestFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache, f => null);
|
||||||
if (_cachedFeaturesRevision != _features.Revision)
|
|
||||||
{
|
|
||||||
_request = null;
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
|
||||||
{
|
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpRequestFeature HttpRequestFeature
|
|
||||||
{
|
|
||||||
get { return FeatureHelpers.GetAndCache(this, _features, ref _request); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRequestCookieCollection Cookies
|
public IRequestCookieCollection Cookies
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_features == null)
|
if (_features.Collection == null)
|
||||||
{
|
{
|
||||||
if (_parsedValues == null)
|
if (_parsedValues == null)
|
||||||
{
|
{
|
||||||
|
|
@ -91,7 +70,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
{
|
{
|
||||||
_parsedValues = value;
|
_parsedValues = value;
|
||||||
_original = StringValues.Empty;
|
_original = StringValues.Empty;
|
||||||
if (_features != null)
|
if (_features.Collection != null)
|
||||||
{
|
{
|
||||||
if (_parsedValues == null || _parsedValues.Count == 0)
|
if (_parsedValues == null || _parsedValues.Count == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,38 +5,18 @@ using Microsoft.AspNet.Http.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Features.Internal
|
namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
{
|
{
|
||||||
public class ResponseCookiesFeature : IResponseCookiesFeature, IFeatureCache
|
public class ResponseCookiesFeature : IResponseCookiesFeature
|
||||||
{
|
{
|
||||||
private readonly IFeatureCollection _features;
|
private FeatureReferences<IHttpResponseFeature> _features;
|
||||||
private int _cachedFeaturesRevision = -1;
|
|
||||||
|
|
||||||
private IHttpResponseFeature _response;
|
|
||||||
private IResponseCookies _cookiesCollection;
|
private IResponseCookies _cookiesCollection;
|
||||||
|
|
||||||
public ResponseCookiesFeature(IFeatureCollection features)
|
public ResponseCookiesFeature(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
_features = features;
|
_features = new FeatureReferences<IHttpResponseFeature>(features);
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFeatureCache.CheckFeaturesRevision()
|
private IHttpResponseFeature HttpResponseFeature =>
|
||||||
{
|
_features.Fetch(ref _features.Cache, f => null);
|
||||||
if (_cachedFeaturesRevision != _features.Revision)
|
|
||||||
{
|
|
||||||
_response = null;
|
|
||||||
((IFeatureCache)this).SetFeaturesRevision();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IFeatureCache.SetFeaturesRevision()
|
|
||||||
{
|
|
||||||
_cachedFeaturesRevision = _features.Revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IHttpResponseFeature HttpResponseFeature
|
|
||||||
{
|
|
||||||
get { return FeatureHelpers.GetAndCache(this, _features, ref _response); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IResponseCookies Cookies
|
public IResponseCookies Cookies
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -149,93 +149,88 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
items["foo"] = item;
|
items["foo"] = item;
|
||||||
Assert.Same(item, context.Items["foo"]);
|
Assert.Same(item, context.Items["foo"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void UpdateFeatures_ClearsCachedFeatures()
|
public void UpdateFeatures_ClearsCachedFeatures()
|
||||||
{
|
{
|
||||||
var features = new FeatureCollection();
|
var features = new FeatureCollection();
|
||||||
|
|
||||||
var context = new DefaultHttpContext(features);
|
|
||||||
|
|
||||||
var request = (DefaultHttpRequest)context.Request;
|
|
||||||
var response = (DefaultHttpResponse)context.Response;
|
|
||||||
|
|
||||||
var authentication = (DefaultAuthenticationManager)context.Authentication;
|
|
||||||
var connection = (DefaultConnectionInfo)context.Connection;
|
|
||||||
var websockets = (DefaultWebSocketManager)context.WebSockets;
|
|
||||||
|
|
||||||
Assert.Equal(0, features.Count());
|
|
||||||
|
|
||||||
TestCachedFeaturesAreNull(context.GetType(), context, features);
|
|
||||||
TestCachedFeaturesAreNull(request.GetType(), request, features);
|
|
||||||
TestCachedFeaturesAreNull(response.GetType(), response, features);
|
|
||||||
TestCachedFeaturesAreNull(authentication.GetType(), authentication, features);
|
|
||||||
TestCachedFeaturesAreNull(connection.GetType(), connection, features);
|
|
||||||
TestCachedFeaturesAreNull(websockets.GetType(), websockets, features);
|
|
||||||
|
|
||||||
context.Session = new TestSession();
|
|
||||||
features.Set<IHttpRequestFeature>(new HttpRequestFeature());
|
features.Set<IHttpRequestFeature>(new HttpRequestFeature());
|
||||||
features.Set<IHttpResponseFeature>(new HttpResponseFeature());
|
features.Set<IHttpResponseFeature>(new HttpResponseFeature());
|
||||||
features.Set<IHttpWebSocketFeature>(new TestHttpWebSocketFeature());
|
features.Set<IHttpWebSocketFeature>(new TestHttpWebSocketFeature());
|
||||||
|
|
||||||
TestCachedFeaturesAreSet(context.GetType(), context, features);
|
// featurecollection is set. all cached interfaces are null.
|
||||||
TestCachedFeaturesAreSet(request.GetType(), request, features);
|
var context = new DefaultHttpContext(features);
|
||||||
TestCachedFeaturesAreSet(response.GetType(), response, features);
|
TestAllCachedFeaturesAreNull(context, features);
|
||||||
TestCachedFeaturesAreSet(authentication.GetType(), authentication, features);
|
Assert.Equal(3, features.Count());
|
||||||
TestCachedFeaturesAreSet(connection.GetType(), connection, features);
|
|
||||||
TestCachedFeaturesAreSet(websockets.GetType(), websockets, features);
|
// getting feature properties populates feature collection with defaults
|
||||||
|
TestAllCachedFeaturesAreSet(context, features);
|
||||||
|
Assert.NotEqual(3, features.Count());
|
||||||
|
|
||||||
|
// featurecollection is null. and all cached interfaces are null.
|
||||||
|
// only top level is tested because child objects are inaccessible.
|
||||||
|
context.Uninitialize();
|
||||||
|
TestCachedFeaturesAreNull(context, null);
|
||||||
|
|
||||||
Assert.NotEqual(0, features.Count());
|
|
||||||
|
|
||||||
var newFeatures = new FeatureCollection();
|
var newFeatures = new FeatureCollection();
|
||||||
context.UpdateFeatures(newFeatures);
|
|
||||||
|
|
||||||
Assert.Equal(0, newFeatures.Count());
|
|
||||||
|
|
||||||
TestCachedFeaturesAreNull(context.GetType(), context, newFeatures);
|
|
||||||
TestCachedFeaturesAreNull(request.GetType(), request, newFeatures);
|
|
||||||
TestCachedFeaturesAreNull(response.GetType(), response, newFeatures);
|
|
||||||
TestCachedFeaturesAreNull(authentication.GetType(), authentication, newFeatures);
|
|
||||||
TestCachedFeaturesAreNull(connection.GetType(), connection, newFeatures);
|
|
||||||
TestCachedFeaturesAreNull(websockets.GetType(), websockets, newFeatures);
|
|
||||||
|
|
||||||
context.Session = new TestSession();
|
|
||||||
newFeatures.Set<IHttpRequestFeature>(new HttpRequestFeature());
|
newFeatures.Set<IHttpRequestFeature>(new HttpRequestFeature());
|
||||||
newFeatures.Set<IHttpResponseFeature>(new HttpResponseFeature());
|
newFeatures.Set<IHttpResponseFeature>(new HttpResponseFeature());
|
||||||
newFeatures.Set<IHttpWebSocketFeature>(new TestHttpWebSocketFeature());
|
newFeatures.Set<IHttpWebSocketFeature>(new TestHttpWebSocketFeature());
|
||||||
|
|
||||||
TestCachedFeaturesAreSet(context.GetType(), context, newFeatures);
|
// featurecollection is set to newFeatures. all cached interfaces are null.
|
||||||
TestCachedFeaturesAreSet(request.GetType(), request, newFeatures);
|
context.Initialize(newFeatures);
|
||||||
TestCachedFeaturesAreSet(response.GetType(), response, newFeatures);
|
TestAllCachedFeaturesAreNull(context, newFeatures);
|
||||||
TestCachedFeaturesAreSet(authentication.GetType(), authentication, newFeatures);
|
Assert.Equal(3, newFeatures.Count());
|
||||||
TestCachedFeaturesAreSet(connection.GetType(), connection, newFeatures);
|
|
||||||
TestCachedFeaturesAreSet(websockets.GetType(), websockets, newFeatures);
|
|
||||||
|
|
||||||
Assert.NotEqual(0, newFeatures.Count());
|
// getting feature properties populates new feature collection with defaults
|
||||||
|
TestAllCachedFeaturesAreSet(context, newFeatures);
|
||||||
|
Assert.NotEqual(3, newFeatures.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCachedFeaturesAreNull(Type type, object value, IFeatureCollection features)
|
void TestAllCachedFeaturesAreNull(HttpContext context, IFeatureCollection features)
|
||||||
{
|
{
|
||||||
|
TestCachedFeaturesAreNull(context, features);
|
||||||
|
TestCachedFeaturesAreNull(context.Request, features);
|
||||||
|
TestCachedFeaturesAreNull(context.Response, features);
|
||||||
|
TestCachedFeaturesAreNull(context.Authentication, features);
|
||||||
|
TestCachedFeaturesAreNull(context.Connection, features);
|
||||||
|
TestCachedFeaturesAreNull(context.WebSockets, features);
|
||||||
|
}
|
||||||
|
|
||||||
var fields = type
|
void TestCachedFeaturesAreNull(object value, IFeatureCollection features)
|
||||||
|
{
|
||||||
|
var type = value.GetType();
|
||||||
|
|
||||||
|
var field = type
|
||||||
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
|
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
.Where(f => f.FieldType.GetTypeInfo().IsInterface);
|
.Single(f =>
|
||||||
|
f.FieldType.GetTypeInfo().IsGenericType &&
|
||||||
|
f.FieldType.GetGenericTypeDefinition() == typeof(FeatureReferences<>));
|
||||||
|
|
||||||
foreach (var field in fields)
|
var boxedExpectedStruct = features == null ?
|
||||||
{
|
Activator.CreateInstance(field.FieldType) :
|
||||||
if (field.FieldType == typeof(IFeatureCollection))
|
Activator.CreateInstance(field.FieldType, features);
|
||||||
{
|
|
||||||
Assert.Same(features, field.GetValue(value));
|
var boxedActualStruct = field.GetValue(value);
|
||||||
}
|
|
||||||
else
|
Assert.Equal(boxedExpectedStruct, boxedActualStruct);
|
||||||
{
|
|
||||||
Assert.Null(field.GetValue(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCachedFeaturesAreSet(Type type, object value, IFeatureCollection features)
|
void TestAllCachedFeaturesAreSet(HttpContext context, IFeatureCollection features)
|
||||||
{
|
{
|
||||||
|
TestCachedFeaturesAreSet(context, features);
|
||||||
|
TestCachedFeaturesAreSet(context.Request, features);
|
||||||
|
TestCachedFeaturesAreSet(context.Response, features);
|
||||||
|
TestCachedFeaturesAreSet(context.Authentication, features);
|
||||||
|
TestCachedFeaturesAreSet(context.Connection, features);
|
||||||
|
TestCachedFeaturesAreSet(context.WebSockets, features);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCachedFeaturesAreSet(object value, IFeatureCollection features)
|
||||||
|
{
|
||||||
|
var type = value.GetType();
|
||||||
|
|
||||||
var properties = type
|
var properties = type
|
||||||
.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
|
.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
|
||||||
.Where(p => p.PropertyType.GetTypeInfo().IsInterface);
|
.Where(p => p.PropertyType.GetTypeInfo().IsInterface);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue