Remove all extensibility from the DefaultHttpContext (#6504)

- Seal all of the classes
- Remove virtual methods
- Delete pooled HttpContext code
- Removed obsolete AuthenticationManager
This commit is contained in:
David Fowler 2019-01-09 11:37:06 -08:00 committed by GitHub
parent 74f1ccad0d
commit a11c68ae35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 56 additions and 1208 deletions

View File

@ -40,14 +40,6 @@ namespace Microsoft.AspNetCore.Http
/// </summary>
public abstract WebSocketManager WebSockets { get; }
/// <summary>
/// This is obsolete and will be removed in a future version.
/// The recommended alternative is to use Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.
/// See https://go.microsoft.com/fwlink/?linkid=845470.
/// </summary>
[Obsolete("This is obsolete and will be removed in a future version. The recommended alternative is to use Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions. See https://go.microsoft.com/fwlink/?linkid=845470.")]
public abstract AuthenticationManager Authentication { get; }
/// <summary>
/// Gets or sets the user for this request.
/// </summary>

View File

@ -1,184 +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;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http.Features.Authentication;
namespace Microsoft.AspNetCore.Http.Authentication.Internal
{
[Obsolete("This is obsolete and will be removed in a future version. See https://go.microsoft.com/fwlink/?linkid=845470.")]
public class DefaultAuthenticationManager : AuthenticationManager
{
// Lambda hoisted to static readonly field to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpAuthenticationFeature> _newAuthenticationFeature = f => new HttpAuthenticationFeature();
private HttpContext _context;
private FeatureReferences<IHttpAuthenticationFeature> _features;
public DefaultAuthenticationManager(HttpContext context)
{
Initialize(context);
}
public virtual void Initialize(HttpContext context)
{
_context = context;
_features = new FeatureReferences<IHttpAuthenticationFeature>(context.Features);
}
public virtual void Uninitialize()
{
_features = default(FeatureReferences<IHttpAuthenticationFeature>);
}
public override HttpContext HttpContext => _context;
private IHttpAuthenticationFeature HttpAuthenticationFeature =>
_features.Fetch(ref _features.Cache, _newAuthenticationFeature);
public override IEnumerable<AuthenticationDescription> GetAuthenticationSchemes()
{
#pragma warning disable CS0618 // Type or member is obsolete
var handler = HttpAuthenticationFeature.Handler;
#pragma warning restore CS0618 // Type or member is obsolete
if (handler == null)
{
return new AuthenticationDescription[0];
}
var describeContext = new DescribeSchemesContext();
handler.GetDescriptions(describeContext);
return describeContext.Results.Select(description => new AuthenticationDescription(description));
}
// Remove once callers have been switched to GetAuthenticateInfoAsync
public override async Task AuthenticateAsync(AuthenticateContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
#pragma warning disable CS0618 // Type or member is obsolete
var handler = HttpAuthenticationFeature.Handler;
#pragma warning restore CS0618 // Type or member is obsolete
if (handler != null)
{
await handler.AuthenticateAsync(context);
}
if (!context.Accepted)
{
throw new InvalidOperationException($"No authentication handler is configured to authenticate for the scheme: {context.AuthenticationScheme}");
}
}
public override async Task<AuthenticateInfo> GetAuthenticateInfoAsync(string authenticationScheme)
{
if (authenticationScheme == null)
{
throw new ArgumentNullException(nameof(authenticationScheme));
}
#pragma warning disable CS0618 // Type or member is obsolete
var handler = HttpAuthenticationFeature.Handler;
#pragma warning restore CS0618 // Type or member is obsolete
var context = new AuthenticateContext(authenticationScheme);
if (handler != null)
{
await handler.AuthenticateAsync(context);
}
if (!context.Accepted)
{
throw new InvalidOperationException($"No authentication handler is configured to authenticate for the scheme: {context.AuthenticationScheme}");
}
return new AuthenticateInfo
{
Principal = context.Principal,
Properties = new AuthenticationProperties(context.Properties),
Description = new AuthenticationDescription(context.Description)
};
}
public override async Task ChallengeAsync(string authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior)
{
if (string.IsNullOrEmpty(authenticationScheme))
{
throw new ArgumentException(nameof(authenticationScheme));
}
#pragma warning disable CS0618 // Type or member is obsolete
var handler = HttpAuthenticationFeature.Handler;
#pragma warning restore CS0618 // Type or member is obsolete
var challengeContext = new ChallengeContext(authenticationScheme, properties?.Items, behavior);
if (handler != null)
{
await handler.ChallengeAsync(challengeContext);
}
if (!challengeContext.Accepted)
{
throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}");
}
}
public override async Task SignInAsync(string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties)
{
if (string.IsNullOrEmpty(authenticationScheme))
{
throw new ArgumentException(nameof(authenticationScheme));
}
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
#pragma warning disable CS0618 // Type or member is obsolete
var handler = HttpAuthenticationFeature.Handler;
#pragma warning restore CS0618 // Type or member is obsolete
var signInContext = new SignInContext(authenticationScheme, principal, properties?.Items);
if (handler != null)
{
await handler.SignInAsync(signInContext);
}
if (!signInContext.Accepted)
{
throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}");
}
}
public override async Task SignOutAsync(string authenticationScheme, AuthenticationProperties properties)
{
if (string.IsNullOrEmpty(authenticationScheme))
{
throw new ArgumentException(nameof(authenticationScheme));
}
#pragma warning disable CS0618 // Type or member is obsolete
var handler = HttpAuthenticationFeature.Handler;
#pragma warning restore CS0618 // Type or member is obsolete
var signOutContext = new SignOutContext(authenticationScheme, properties?.Items);
if (handler != null)
{
await handler.SignOutAsync(signOutContext);
}
if (!signOutContext.Accepted)
{
throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}");
}
}
}
}

View File

@ -5,15 +5,13 @@ using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Http.Authentication.Internal;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http.Features.Authentication;
using Microsoft.AspNetCore.Http.Internal;
namespace Microsoft.AspNetCore.Http
{
public class DefaultHttpContext : HttpContext
public sealed class DefaultHttpContext : HttpContext
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IItemsFeature> _newItemsFeature = f => new ItemsFeature();
@ -26,15 +24,11 @@ namespace Microsoft.AspNetCore.Http
private FeatureReferences<FeatureInterfaces> _features;
private HttpRequest _request;
private HttpResponse _response;
private readonly DefaultHttpRequest _request;
private readonly DefaultHttpResponse _response;
#pragma warning disable CS0618 // Type or member is obsolete
private AuthenticationManager _authenticationManager;
#pragma warning restore CS0618 // Type or member is obsolete
private ConnectionInfo _connection;
private WebSocketManager _websockets;
private DefaultConnectionInfo _connection;
private DefaultWebSocketManager _websockets;
public DefaultHttpContext()
: this(new FeatureCollection())
@ -45,46 +39,27 @@ namespace Microsoft.AspNetCore.Http
public DefaultHttpContext(IFeatureCollection features)
{
Initialize(features);
_features = new FeatureReferences<FeatureInterfaces>(features);
_request = new DefaultHttpRequest(this);
_response = new DefaultHttpResponse(this);
}
public virtual void Initialize(IFeatureCollection features)
public void Initialize(IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
_request = InitializeHttpRequest();
_response = InitializeHttpResponse();
_request.Initialize();
_response.Initialize();
_connection?.Initialize(features);
_websockets?.Initialize(features);
}
public virtual void Uninitialize()
public void Uninitialize()
{
_features = default(FeatureReferences<FeatureInterfaces>);
if (_request != null)
{
UninitializeHttpRequest(_request);
_request = null;
}
if (_response != null)
{
UninitializeHttpResponse(_response);
_response = null;
}
if (_authenticationManager != null)
{
#pragma warning disable CS0618 // Type or member is obsolete
UninitializeAuthenticationManager(_authenticationManager);
#pragma warning restore CS0618 // Type or member is obsolete
_authenticationManager = null;
}
if (_connection != null)
{
UninitializeConnectionInfo(_connection);
_connection = null;
}
if (_websockets != null)
{
UninitializeWebSocketManager(_websockets);
_websockets = null;
}
_features = default;
_request.Uninitialize();
_response.Uninitialize();
_connection?.Uninitialize();
_websockets?.Uninitialize();
}
private IItemsFeature ItemsFeature =>
@ -115,17 +90,9 @@ namespace Microsoft.AspNetCore.Http
public override HttpResponse Response => _response;
public override ConnectionInfo Connection => _connection ?? (_connection = InitializeConnectionInfo());
public override ConnectionInfo Connection => _connection ?? (_connection = new DefaultConnectionInfo(_features.Collection));
/// <summary>
/// This is obsolete and will be removed in a future version.
/// The recommended alternative is to use Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.
/// See https://go.microsoft.com/fwlink/?linkid=845470.
/// </summary>
[Obsolete("This is obsolete and will be removed in a future version. The recommended alternative is to use Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions. See https://go.microsoft.com/fwlink/?linkid=845470.")]
public override AuthenticationManager Authentication => _authenticationManager ?? (_authenticationManager = InitializeAuthenticationManager());
public override WebSocketManager WebSockets => _websockets ?? (_websockets = InitializeWebSocketManager());
public override WebSocketManager WebSockets => _websockets ?? (_websockets = new DefaultWebSocketManager(_features.Collection));
public override ClaimsPrincipal User
@ -186,30 +153,11 @@ namespace Microsoft.AspNetCore.Http
}
public override void Abort()
{
LifetimeFeature.Abort();
}
protected virtual HttpRequest InitializeHttpRequest() => new DefaultHttpRequest(this);
protected virtual void UninitializeHttpRequest(HttpRequest instance) { }
protected virtual HttpResponse InitializeHttpResponse() => new DefaultHttpResponse(this);
protected virtual void UninitializeHttpResponse(HttpResponse instance) { }
protected virtual ConnectionInfo InitializeConnectionInfo() => new DefaultConnectionInfo(Features);
protected virtual void UninitializeConnectionInfo(ConnectionInfo instance) { }
[Obsolete("This is obsolete and will be removed in a future version. See https://go.microsoft.com/fwlink/?linkid=845470.")]
protected virtual AuthenticationManager InitializeAuthenticationManager() => new DefaultAuthenticationManager(this);
[Obsolete("This is obsolete and will be removed in a future version. See https://go.microsoft.com/fwlink/?linkid=845470.")]
protected virtual void UninitializeAuthenticationManager(AuthenticationManager instance) { }
protected virtual WebSocketManager InitializeWebSocketManager() => new DefaultWebSocketManager(Features);
protected virtual void UninitializeWebSocketManager(WebSocketManager instance) { }
struct FeatureInterfaces
{
public IItemsFeature Items;

View File

@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Http
return container.HttpContext;
}
return new ReusableHttpContext(featureCollection);
return new DefaultHttpContext(featureCollection);
}
public void Dispose(HttpContext httpContext)

View File

@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.Http.Internal
{
public class DefaultConnectionInfo : ConnectionInfo
public sealed class DefaultConnectionInfo : ConnectionInfo
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpConnectionFeature> _newHttpConnectionFeature = f => new HttpConnectionFeature();
@ -23,14 +23,14 @@ namespace Microsoft.AspNetCore.Http.Internal
Initialize(features);
}
public virtual void Initialize( IFeatureCollection features)
public void Initialize( IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
}
public virtual void Uninitialize()
public void Uninitialize()
{
_features = default(FeatureReferences<FeatureInterfaces>);
_features = default;
}
private IHttpConnectionFeature HttpConnectionFeature =>
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Http.Internal
set { TlsConnectionFeature.ClientCertificate = value; }
}
public override Task<X509Certificate2> GetClientCertificateAsync(CancellationToken cancellationToken = new CancellationToken())
public override Task<X509Certificate2> GetClientCertificateAsync(CancellationToken cancellationToken = default)
{
return TlsConnectionFeature.GetClientCertificateAsync(cancellationToken);
}

View File

@ -12,7 +12,7 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Http.Internal
{
public class DefaultHttpRequest : HttpRequest
public sealed class DefaultHttpRequest : HttpRequest
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpRequestFeature> _nullRequestFeature = f => null;
@ -22,24 +22,23 @@ namespace Microsoft.AspNetCore.Http.Internal
private readonly static Func<IFeatureCollection, IRouteValuesFeature> _newRouteValuesFeature = f => new RouteValuesFeature();
private readonly static Func<HttpContext, IRequestBodyPipeFeature> _newRequestBodyPipeFeature = context => new RequestBodyPipeFeature(context);
private HttpContext _context;
private readonly DefaultHttpContext _context;
private FeatureReferences<FeatureInterfaces> _features;
public DefaultHttpRequest(HttpContext context)
{
Initialize(context);
}
public virtual void Initialize(HttpContext context)
public DefaultHttpRequest(DefaultHttpContext context)
{
_context = context;
_features = new FeatureReferences<FeatureInterfaces>(context.Features);
_features = new FeatureReferences<FeatureInterfaces>(_context.Features);
}
public virtual void Uninitialize()
public void Initialize()
{
_context = null;
_features = default(FeatureReferences<FeatureInterfaces>);
_features = new FeatureReferences<FeatureInterfaces>(_context.Features);
}
public void Uninitialize()
{
_features = default;
}
public override HttpContext HttpContext => _context;

View File

@ -10,31 +10,30 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Http.Internal
{
public class DefaultHttpResponse : HttpResponse
public sealed class DefaultHttpResponse : HttpResponse
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpResponseFeature> _nullResponseFeature = f => null;
private readonly static Func<IFeatureCollection, IResponseCookiesFeature> _newResponseCookiesFeature = f => new ResponseCookiesFeature(f);
private readonly static Func<HttpContext, IResponseBodyPipeFeature> _newResponseBodyPipeFeature = context => new ResponseBodyPipeFeature(context);
private HttpContext _context;
private readonly DefaultHttpContext _context;
private FeatureReferences<FeatureInterfaces> _features;
public DefaultHttpResponse(HttpContext context)
{
Initialize(context);
}
public virtual void Initialize(HttpContext context)
public DefaultHttpResponse(DefaultHttpContext context)
{
_context = context;
_features = new FeatureReferences<FeatureInterfaces>(context.Features);
_features = new FeatureReferences<FeatureInterfaces>(_context.Features);
}
public virtual void Uninitialize()
public void Initialize()
{
_context = null;
_features = default(FeatureReferences<FeatureInterfaces>);
_features = new FeatureReferences<FeatureInterfaces>(_context.Features);
}
public void Uninitialize()
{
_features = default;
}
private IHttpResponseFeature HttpResponseFeature =>

View File

@ -10,7 +10,7 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Http.Internal
{
public class DefaultWebSocketManager : WebSocketManager
public sealed class DefaultWebSocketManager : WebSocketManager
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpRequestFeature> _nullRequestFeature = f => null;
@ -23,14 +23,14 @@ namespace Microsoft.AspNetCore.Http.Internal
Initialize(features);
}
public virtual void Initialize(IFeatureCollection features)
public void Initialize(IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
}
public virtual void Uninitialize()
public void Uninitialize()
{
_features = default(FeatureReferences<FeatureInterfaces>);
_features = default;
}
private IHttpRequestFeature HttpRequestFeature =>

View File

@ -1,89 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.Http.Internal
{
public sealed class ReusableConnectionInfo : ConnectionInfo
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpConnectionFeature> _newHttpConnectionFeature = f => new HttpConnectionFeature();
private readonly static Func<IFeatureCollection, ITlsConnectionFeature> _newTlsConnectionFeature = f => new TlsConnectionFeature();
private FeatureReferences<FeatureInterfaces> _features;
public ReusableConnectionInfo(IFeatureCollection features)
{
Initialize(features);
}
public void Initialize(IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
}
public void Uninitialize()
{
_features = default(FeatureReferences<FeatureInterfaces>);
}
private IHttpConnectionFeature HttpConnectionFeature =>
_features.Fetch(ref _features.Cache.Connection, _newHttpConnectionFeature);
private ITlsConnectionFeature TlsConnectionFeature =>
_features.Fetch(ref _features.Cache.TlsConnection, _newTlsConnectionFeature);
/// <inheritdoc />
public override string Id
{
get { return HttpConnectionFeature.ConnectionId; }
set { HttpConnectionFeature.ConnectionId = value; }
}
public override IPAddress RemoteIpAddress
{
get { return HttpConnectionFeature.RemoteIpAddress; }
set { HttpConnectionFeature.RemoteIpAddress = value; }
}
public override int RemotePort
{
get { return HttpConnectionFeature.RemotePort; }
set { HttpConnectionFeature.RemotePort = value; }
}
public override IPAddress LocalIpAddress
{
get { return HttpConnectionFeature.LocalIpAddress; }
set { HttpConnectionFeature.LocalIpAddress = value; }
}
public override int LocalPort
{
get { return HttpConnectionFeature.LocalPort; }
set { HttpConnectionFeature.LocalPort = value; }
}
public override X509Certificate2 ClientCertificate
{
get { return TlsConnectionFeature.ClientCertificate; }
set { TlsConnectionFeature.ClientCertificate = value; }
}
public override Task<X509Certificate2> GetClientCertificateAsync(CancellationToken cancellationToken = default)
{
return TlsConnectionFeature.GetClientCertificateAsync(cancellationToken);
}
struct FeatureInterfaces
{
public IHttpConnectionFeature Connection;
public ITlsConnectionFeature TlsConnection;
}
}
}

View File

@ -1,165 +0,0 @@
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http.Features.Authentication;
namespace Microsoft.AspNetCore.Http.Internal
{
public sealed class ReusableHttpContext : HttpContext
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IItemsFeature> _newItemsFeature = f => new ItemsFeature();
private readonly static Func<IFeatureCollection, IServiceProvidersFeature> _newServiceProvidersFeature = f => new ServiceProvidersFeature();
private readonly static Func<IFeatureCollection, IHttpAuthenticationFeature> _newHttpAuthenticationFeature = f => new HttpAuthenticationFeature();
private readonly static Func<IFeatureCollection, IHttpRequestLifetimeFeature> _newHttpRequestLifetimeFeature = f => new HttpRequestLifetimeFeature();
private readonly static Func<IFeatureCollection, ISessionFeature> _newSessionFeature = f => new DefaultSessionFeature();
private readonly static Func<IFeatureCollection, ISessionFeature> _nullSessionFeature = f => null;
private readonly static Func<IFeatureCollection, IHttpRequestIdentifierFeature> _newHttpRequestIdentifierFeature = f => new HttpRequestIdentifierFeature();
private FeatureReferences<FeatureInterfaces> _features;
private ReusableHttpRequest _request;
private ReusableHttpResponse _response;
private ReusableConnectionInfo _connection;
private ReusableWebSocketManager _websockets;
public ReusableHttpContext(IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
_request = new ReusableHttpRequest(this);
_response = new ReusableHttpResponse(this);
}
public void Initialize(IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
_request.Initialize(this);
_response.Initialize(this);
_connection?.Initialize(features);
_websockets?.Initialize(features);
}
public void Uninitialize()
{
_features = default;
_request.Uninitialize();
_response.Uninitialize();
_connection?.Uninitialize();
_websockets?.Uninitialize();
}
private IItemsFeature ItemsFeature =>
_features.Fetch(ref _features.Cache.Items, _newItemsFeature);
private IServiceProvidersFeature ServiceProvidersFeature =>
_features.Fetch(ref _features.Cache.ServiceProviders, _newServiceProvidersFeature);
private IHttpAuthenticationFeature HttpAuthenticationFeature =>
_features.Fetch(ref _features.Cache.Authentication, _newHttpAuthenticationFeature);
private IHttpRequestLifetimeFeature LifetimeFeature =>
_features.Fetch(ref _features.Cache.Lifetime, _newHttpRequestLifetimeFeature);
private ISessionFeature SessionFeature =>
_features.Fetch(ref _features.Cache.Session, _newSessionFeature);
private ISessionFeature SessionFeatureOrNull =>
_features.Fetch(ref _features.Cache.Session, _nullSessionFeature);
private IHttpRequestIdentifierFeature RequestIdentifierFeature =>
_features.Fetch(ref _features.Cache.RequestIdentifier, _newHttpRequestIdentifierFeature);
public override IFeatureCollection Features => _features.Collection;
public override HttpRequest Request => _request;
public override HttpResponse Response => _response;
public override ConnectionInfo Connection => _connection ?? (_connection = new ReusableConnectionInfo(_features.Collection));
[Obsolete("This is obsolete and will be removed in a future version. The recommended alternative is to use Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions. See https://go.microsoft.com/fwlink/?linkid=845470.")]
public override AuthenticationManager Authentication => throw new NotSupportedException();
public override WebSocketManager WebSockets => _websockets ?? (_websockets = new ReusableWebSocketManager(_features.Collection));
public override ClaimsPrincipal User
{
get
{
var user = HttpAuthenticationFeature.User;
if (user == null)
{
user = new ClaimsPrincipal(new ClaimsIdentity());
HttpAuthenticationFeature.User = user;
}
return user;
}
set { HttpAuthenticationFeature.User = value; }
}
public override IDictionary<object, object> Items
{
get { return ItemsFeature.Items; }
set { ItemsFeature.Items = value; }
}
public override IServiceProvider RequestServices
{
get { return ServiceProvidersFeature.RequestServices; }
set { ServiceProvidersFeature.RequestServices = value; }
}
public override CancellationToken RequestAborted
{
get { return LifetimeFeature.RequestAborted; }
set { LifetimeFeature.RequestAborted = value; }
}
public override string TraceIdentifier
{
get { return RequestIdentifierFeature.TraceIdentifier; }
set { RequestIdentifierFeature.TraceIdentifier = value; }
}
public override ISession Session
{
get
{
var feature = SessionFeatureOrNull;
if (feature == null)
{
throw new InvalidOperationException("Session has not been configured for this application " +
"or request.");
}
return feature.Session;
}
set
{
SessionFeature.Session = value;
}
}
public override void Abort()
{
LifetimeFeature.Abort();
}
struct FeatureInterfaces
{
public IItemsFeature Items;
public IServiceProvidersFeature ServiceProviders;
public IHttpAuthenticationFeature Authentication;
public IHttpRequestLifetimeFeature Lifetime;
public ISessionFeature Session;
public IHttpRequestIdentifierFeature RequestIdentifier;
}
}
}

View File

@ -1,186 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipelines;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Http.Internal
{
public sealed class ReusableHttpRequest : HttpRequest
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpRequestFeature> _nullRequestFeature = f => null;
private readonly static Func<IFeatureCollection, IQueryFeature> _newQueryFeature = f => new QueryFeature(f);
private readonly static Func<HttpRequest, IFormFeature> _newFormFeature = r => new FormFeature(r);
private readonly static Func<IFeatureCollection, IRequestCookiesFeature> _newRequestCookiesFeature = f => new RequestCookiesFeature(f);
private readonly static Func<IFeatureCollection, IRouteValuesFeature> _newRouteValuesFeature = f => new RouteValuesFeature();
private readonly static Func<HttpContext, IRequestBodyPipeFeature> _newRequestBodyPipeFeature = context => new RequestBodyPipeFeature(context);
private HttpContext _context;
private FeatureReferences<FeatureInterfaces> _features;
public ReusableHttpRequest(HttpContext context)
{
Initialize(context);
}
public void Initialize(HttpContext context)
{
_context = context;
_features = new FeatureReferences<FeatureInterfaces>(context.Features);
}
public void Uninitialize()
{
_context = null;
_features = default;
}
public override HttpContext HttpContext => _context;
private IHttpRequestFeature HttpRequestFeature =>
_features.Fetch(ref _features.Cache.Request, _nullRequestFeature);
private IQueryFeature QueryFeature =>
_features.Fetch(ref _features.Cache.Query, _newQueryFeature);
private IFormFeature FormFeature =>
_features.Fetch(ref _features.Cache.Form, this, _newFormFeature);
private IRequestCookiesFeature RequestCookiesFeature =>
_features.Fetch(ref _features.Cache.Cookies, _newRequestCookiesFeature);
private IRouteValuesFeature RouteValuesFeature =>
_features.Fetch(ref _features.Cache.RouteValues, _newRouteValuesFeature);
private IRequestBodyPipeFeature RequestBodyPipeFeature =>
_features.Fetch(ref _features.Cache.BodyPipe, this.HttpContext, _newRequestBodyPipeFeature);
public override PathString PathBase
{
get { return new PathString(HttpRequestFeature.PathBase); }
set { HttpRequestFeature.PathBase = value.Value; }
}
public override PathString Path
{
get { return new PathString(HttpRequestFeature.Path); }
set { HttpRequestFeature.Path = value.Value; }
}
public override QueryString QueryString
{
get { return new QueryString(HttpRequestFeature.QueryString); }
set { HttpRequestFeature.QueryString = value.Value; }
}
public override long? ContentLength
{
get { return Headers.ContentLength; }
set { Headers.ContentLength = value; }
}
public override Stream Body
{
get { return HttpRequestFeature.Body; }
set { HttpRequestFeature.Body = value; }
}
public override string Method
{
get { return HttpRequestFeature.Method; }
set { HttpRequestFeature.Method = value; }
}
public override string Scheme
{
get { return HttpRequestFeature.Scheme; }
set { HttpRequestFeature.Scheme = value; }
}
public override bool IsHttps
{
get { return string.Equals(Constants.Https, Scheme, StringComparison.OrdinalIgnoreCase); }
set { Scheme = value ? Constants.Https : Constants.Http; }
}
public override HostString Host
{
get { return HostString.FromUriComponent(Headers["Host"]); }
set { Headers["Host"] = value.ToUriComponent(); }
}
public override IQueryCollection Query
{
get { return QueryFeature.Query; }
set { QueryFeature.Query = value; }
}
public override string Protocol
{
get { return HttpRequestFeature.Protocol; }
set { HttpRequestFeature.Protocol = value; }
}
public override IHeaderDictionary Headers
{
get { return HttpRequestFeature.Headers; }
}
public override IRequestCookieCollection Cookies
{
get { return RequestCookiesFeature.Cookies; }
set { RequestCookiesFeature.Cookies = value; }
}
public override string ContentType
{
get { return Headers[HeaderNames.ContentType]; }
set { Headers[HeaderNames.ContentType] = value; }
}
public override bool HasFormContentType
{
get { return FormFeature.HasFormContentType; }
}
public override IFormCollection Form
{
get { return FormFeature.ReadForm(); }
set { FormFeature.Form = value; }
}
public override Task<IFormCollection> ReadFormAsync(CancellationToken cancellationToken)
{
return FormFeature.ReadFormAsync(cancellationToken);
}
public override RouteValueDictionary RouteValues
{
get { return RouteValuesFeature.RouteValues; }
set { RouteValuesFeature.RouteValues = value; }
}
public override PipeReader BodyPipe
{
get { return RequestBodyPipeFeature.RequestBodyPipe; }
set { RequestBodyPipeFeature.RequestBodyPipe = value; }
}
struct FeatureInterfaces
{
public IHttpRequestFeature Request;
public IQueryFeature Query;
public IFormFeature Form;
public IRequestCookiesFeature Cookies;
public IRouteValuesFeature RouteValues;
public IRequestBodyPipeFeature BodyPipe;
}
}
}

View File

@ -1,148 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipelines;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Http.Internal
{
public sealed class ReusableHttpResponse : HttpResponse
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpResponseFeature> _nullResponseFeature = f => null;
private readonly static Func<IFeatureCollection, IResponseCookiesFeature> _newResponseCookiesFeature = f => new ResponseCookiesFeature(f);
private readonly static Func<HttpContext, IResponseBodyPipeFeature> _newResponseBodyPipeFeature = context => new ResponseBodyPipeFeature(context);
private HttpContext _context;
private FeatureReferences<FeatureInterfaces> _features;
public ReusableHttpResponse(HttpContext context)
{
Initialize(context);
}
public void Initialize(HttpContext context)
{
_context = context;
_features = new FeatureReferences<FeatureInterfaces>(context.Features);
}
public void Uninitialize()
{
_context = null;
_features = default;
}
private IHttpResponseFeature HttpResponseFeature =>
_features.Fetch(ref _features.Cache.Response, _nullResponseFeature);
private IResponseCookiesFeature ResponseCookiesFeature =>
_features.Fetch(ref _features.Cache.Cookies, _newResponseCookiesFeature);
private IResponseBodyPipeFeature ResponseBodyPipeFeature =>
_features.Fetch(ref _features.Cache.BodyPipe, this.HttpContext, _newResponseBodyPipeFeature);
public override HttpContext HttpContext { get { return _context; } }
public override int StatusCode
{
get { return HttpResponseFeature.StatusCode; }
set { HttpResponseFeature.StatusCode = value; }
}
public override IHeaderDictionary Headers
{
get { return HttpResponseFeature.Headers; }
}
public override Stream Body
{
get { return HttpResponseFeature.Body; }
set { HttpResponseFeature.Body = value; }
}
public override long? ContentLength
{
get { return Headers.ContentLength; }
set { Headers.ContentLength = value; }
}
public override string ContentType
{
get
{
return Headers[HeaderNames.ContentType];
}
set
{
if (string.IsNullOrEmpty(value))
{
HttpResponseFeature.Headers.Remove(HeaderNames.ContentType);
}
else
{
HttpResponseFeature.Headers[HeaderNames.ContentType] = value;
}
}
}
public override IResponseCookies Cookies
{
get { return ResponseCookiesFeature.Cookies; }
}
public override PipeWriter BodyPipe
{
get { return ResponseBodyPipeFeature.ResponseBodyPipe; }
set { ResponseBodyPipeFeature.ResponseBodyPipe = value; }
}
public override bool HasStarted
{
get { return HttpResponseFeature.HasStarted; }
}
public override void OnStarting(Func<object, Task> callback, object state)
{
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
HttpResponseFeature.OnStarting(callback, state);
}
public override void OnCompleted(Func<object, Task> callback, object state)
{
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
HttpResponseFeature.OnCompleted(callback, state);
}
public override void Redirect(string location, bool permanent)
{
if (permanent)
{
HttpResponseFeature.StatusCode = 301;
}
else
{
HttpResponseFeature.StatusCode = 302;
}
Headers[HeaderNames.Location] = location;
}
struct FeatureInterfaces
{
public IHttpResponseFeature Response;
public IResponseCookiesFeature Cookies;
public IResponseBodyPipeFeature BodyPipe;
}
}
}

View File

@ -1,71 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Http.Internal
{
public sealed class ReusableWebSocketManager : WebSocketManager
{
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
private readonly static Func<IFeatureCollection, IHttpRequestFeature> _nullRequestFeature = f => null;
private readonly static Func<IFeatureCollection, IHttpWebSocketFeature> _nullWebSocketFeature = f => null;
private FeatureReferences<FeatureInterfaces> _features;
public ReusableWebSocketManager(IFeatureCollection features)
{
Initialize(features);
}
public void Initialize(IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
}
public void Uninitialize()
{
_features = default;
}
private IHttpRequestFeature HttpRequestFeature =>
_features.Fetch(ref _features.Cache.Request, _nullRequestFeature);
private IHttpWebSocketFeature WebSocketFeature =>
_features.Fetch(ref _features.Cache.WebSockets, _nullWebSocketFeature);
public override bool IsWebSocketRequest
{
get
{
return WebSocketFeature != null && WebSocketFeature.IsWebSocketRequest;
}
}
public override IList<string> WebSocketRequestedProtocols
{
get
{
return ParsingHelpers.GetHeaderSplit(HttpRequestFeature.Headers, HeaderNames.WebSocketSubProtocols);
}
}
public override Task<WebSocket> AcceptWebSocketAsync(string subProtocol)
{
if (WebSocketFeature == null)
{
throw new NotSupportedException("WebSockets are not supported");
}
return WebSocketFeature.AcceptAsync(new WebSocketAcceptContext() { SubProtocol = subProtocol });
}
struct FeatureInterfaces
{
public IHttpRequestFeature Request;
public IHttpWebSocketFeature WebSockets;
}
}
}

View File

@ -1,104 +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.
#pragma warning disable CS0618 // Type or member is obsolete
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features.Authentication;
using Xunit;
namespace Microsoft.AspNetCore.Http.Authentication.Internal
{
public class DefaultAuthenticationManagerTests
{
[Fact]
public async Task AuthenticateWithNoAuthMiddlewareThrows()
{
var context = CreateContext();
await Assert.ThrowsAsync<InvalidOperationException>(async () => await context.Authentication.AuthenticateAsync("Foo"));
}
[Theory]
[InlineData("Automatic")]
[InlineData("Foo")]
public async Task ChallengeWithNoAuthMiddlewareMayThrow(string scheme)
{
var context = CreateContext();
await Assert.ThrowsAsync<InvalidOperationException>(() => context.Authentication.ChallengeAsync(scheme));
}
[Fact]
public async Task SignInWithNoAuthMiddlewareThrows()
{
var context = CreateContext();
await Assert.ThrowsAsync<InvalidOperationException>(() => context.Authentication.SignInAsync("Foo", new ClaimsPrincipal()));
}
[Fact]
public async Task SignOutWithNoAuthMiddlewareMayThrow()
{
var context = CreateContext();
await Assert.ThrowsAsync<InvalidOperationException>(() => context.Authentication.SignOutAsync("Foo"));
}
[Fact]
public async Task SignInOutIn()
{
var context = CreateContext();
var handler = new AuthHandler();
context.Features.Set<IHttpAuthenticationFeature>(new HttpAuthenticationFeature() { Handler = handler });
var user = new ClaimsPrincipal();
await context.Authentication.SignInAsync("ignored", user);
Assert.True(handler.SignedIn);
await context.Authentication.SignOutAsync("ignored");
Assert.False(handler.SignedIn);
await context.Authentication.SignInAsync("ignored", user);
Assert.True(handler.SignedIn);
await context.Authentication.SignOutAsync("ignored", new AuthenticationProperties() { RedirectUri = "~/logout" });
Assert.False(handler.SignedIn);
}
private class AuthHandler : IAuthenticationHandler
{
public bool SignedIn { get; set; }
public Task AuthenticateAsync(AuthenticateContext context)
{
throw new NotImplementedException();
}
public Task ChallengeAsync(ChallengeContext context)
{
throw new NotImplementedException();
}
public void GetDescriptions(DescribeSchemesContext context)
{
throw new NotImplementedException();
}
public Task SignInAsync(SignInContext context)
{
SignedIn = true;
context.Accept();
return Task.FromResult(0);
}
public Task SignOutAsync(SignOutContext context)
{
SignedIn = false;
context.Accept();
return Task.FromResult(0);
}
}
private HttpContext CreateContext()
{
var context = new DefaultHttpContext();
return context;
}
}
}
#pragma warning restore CS0618 // Type or member is obsolete

View File

@ -193,9 +193,6 @@ namespace System.IO.Pipelines.Tests
TestCachedFeaturesAreNull(context, features);
TestCachedFeaturesAreNull(context.Request, features);
TestCachedFeaturesAreNull(context.Response, features);
#pragma warning disable CS0618 // Type or member is obsolete
TestCachedFeaturesAreNull(context.Authentication, features);
#pragma warning restore CS0618 // Type or member is obsolete
TestCachedFeaturesAreNull(context.Connection, features);
TestCachedFeaturesAreNull(context.WebSockets, features);
}
@ -224,9 +221,6 @@ namespace System.IO.Pipelines.Tests
TestCachedFeaturesAreSet(context, features);
TestCachedFeaturesAreSet(context.Request, features);
TestCachedFeaturesAreSet(context.Response, features);
#pragma warning disable CS0618 // Type or member is obsolete
TestCachedFeaturesAreSet(context.Authentication, features);
#pragma warning restore CS0618 // Type or member is obsolete
TestCachedFeaturesAreSet(context.Connection, features);
TestCachedFeaturesAreSet(context.WebSockets, features);
}
@ -350,4 +344,4 @@ namespace System.IO.Pipelines.Tests
}
}
}
}
}

View File

@ -1,54 +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 Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.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);
return _pooledHttpRequest;
}
return new DefaultHttpRequest(this);
}
protected override void UninitializeHttpRequest(HttpRequest instance)
{
_pooledHttpRequest = instance as DefaultHttpRequest;
_pooledHttpRequest?.Uninitialize();
}
protected override HttpResponse InitializeHttpResponse()
{
if (_pooledHttpResponse != null)
{
_pooledHttpResponse.Initialize(this);
return _pooledHttpResponse;
}
return new DefaultHttpResponse(this);
}
protected override void UninitializeHttpResponse(HttpResponse instance)
{
_pooledHttpResponse = instance as DefaultHttpResponse;
_pooledHttpResponse?.Uninitialize();
}
}
}

View File

@ -1,83 +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;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.ObjectPool;
namespace SampleApp
{
public class PooledHttpContextFactory : IHttpContextFactory
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly Stack<PooledHttpContext> _pool = new Stack<PooledHttpContext>();
public PooledHttpContextFactory(ObjectPoolProvider poolProvider)
: this(poolProvider, httpContextAccessor: null)
{
}
public PooledHttpContextFactory(ObjectPoolProvider poolProvider, IHttpContextAccessor httpContextAccessor)
{
if (poolProvider == null)
{
throw new ArgumentNullException(nameof(poolProvider));
}
_httpContextAccessor = httpContextAccessor;
}
public HttpContext Create(IFeatureCollection featureCollection)
{
if (featureCollection == null)
{
throw new ArgumentNullException(nameof(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);
}
}
}
}
}

View File

@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private long _responseBytesWritten;
private readonly HttpConnectionContext _context;
private ReusableHttpContext _httpContext;
private DefaultHttpContext _httpContext;
protected string _methodText = null;
private string _scheme = null;
@ -283,7 +283,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{
if (_httpContext is null)
{
_httpContext = new ReusableHttpContext(this);
_httpContext = new DefaultHttpContext(this);
}
else
{