diff --git a/src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs b/src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs index 7feb5324..1128adb1 100644 --- a/src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs +++ b/src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs @@ -15,6 +15,9 @@ namespace Microsoft.AspNetCore.Http { public class DefaultHttpContext : HttpContext { + private readonly Func _formFeatureFactory; + private readonly Func _responseCookiesFeatureFactory; + private FeatureReferences _features; private HttpRequest _request; @@ -31,7 +34,14 @@ public DefaultHttpContext() } public DefaultHttpContext(IFeatureCollection features) + : this(features, null, null) + { + } + + public DefaultHttpContext(IFeatureCollection features, Func responseCookiesFeatureFactory, Func formFeatureFactory) { + _formFeatureFactory = formFeatureFactory; + _responseCookiesFeatureFactory = responseCookiesFeatureFactory; Initialize(features); } @@ -172,10 +182,10 @@ public override void Abort() } - protected virtual HttpRequest InitializeHttpRequest() => new DefaultHttpRequest(this); + protected virtual HttpRequest InitializeHttpRequest() => new DefaultHttpRequest(this, _formFeatureFactory); protected virtual void UninitializeHttpRequest(HttpRequest instance) { } - protected virtual HttpResponse InitializeHttpResponse() => new DefaultHttpResponse(this); + protected virtual HttpResponse InitializeHttpResponse() => new DefaultHttpResponse(this, _responseCookiesFeatureFactory); protected virtual void UninitializeHttpResponse(HttpResponse instance) { } protected virtual ConnectionInfo InitializeConnectionInfo() => new DefaultConnectionInfo(Features); diff --git a/src/Microsoft.AspNetCore.Http/Features/FormFeature.cs b/src/Microsoft.AspNetCore.Http/Features/FormFeature.cs index cd8b491f..ffeee4da 100644 --- a/src/Microsoft.AspNetCore.Http/Features/FormFeature.cs +++ b/src/Microsoft.AspNetCore.Http/Features/FormFeature.cs @@ -41,13 +41,9 @@ public FormFeature(HttpRequest request, FormOptions options) { throw new ArgumentNullException(nameof(request)); } - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } _request = request; - _options = options; + _options = options ?? DefaultFormOptions; } private MediaTypeHeaderValue ContentType diff --git a/src/Microsoft.AspNetCore.Http/HttpContextFactory.cs b/src/Microsoft.AspNetCore.Http/HttpContextFactory.cs index f2abfa81..74111388 100644 --- a/src/Microsoft.AspNetCore.Http/HttpContextFactory.cs +++ b/src/Microsoft.AspNetCore.Http/HttpContextFactory.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Text; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.Options; @@ -11,9 +10,9 @@ namespace Microsoft.AspNetCore.Http { public class HttpContextFactory : IHttpContextFactory { - private readonly ObjectPool _builderPool; private readonly IHttpContextAccessor _httpContextAccessor; - private readonly FormOptions _formOptions; + private readonly Func _responseCookiesFeatureFactory; + private readonly Func _formFeatureFactory; public HttpContextFactory(ObjectPoolProvider poolProvider, IOptions formOptions) : this(poolProvider, formOptions, httpContextAccessor: null) @@ -31,8 +30,13 @@ public HttpContextFactory(ObjectPoolProvider poolProvider, IOptions throw new ArgumentNullException(nameof(formOptions)); } - _builderPool = poolProvider.CreateStringBuilderPool(); - _formOptions = formOptions.Value; + + var options = formOptions.Value; + var builderPool = poolProvider.CreateStringBuilderPool(); + + _responseCookiesFeatureFactory = features => new ResponseCookiesFeature(features, builderPool); + _formFeatureFactory = request => new FormFeature(request, options); + _httpContextAccessor = httpContextAccessor; } @@ -43,18 +47,12 @@ public HttpContext Create(IFeatureCollection featureCollection) throw new ArgumentNullException(nameof(featureCollection)); } - var responseCookiesFeature = new ResponseCookiesFeature(featureCollection, _builderPool); - featureCollection.Set(responseCookiesFeature); - - var httpContext = new DefaultHttpContext(featureCollection); + var httpContext = new DefaultHttpContext(featureCollection, _responseCookiesFeatureFactory, _formFeatureFactory); if (_httpContextAccessor != null) { _httpContextAccessor.HttpContext = httpContext; } - var formFeature = new FormFeature(httpContext.Request, _formOptions); - featureCollection.Set(formFeature); - return httpContext; } diff --git a/src/Microsoft.AspNetCore.Http/Internal/DefaultHttpRequest.cs b/src/Microsoft.AspNetCore.Http/Internal/DefaultHttpRequest.cs index f761cec1..0674325f 100644 --- a/src/Microsoft.AspNetCore.Http/Internal/DefaultHttpRequest.cs +++ b/src/Microsoft.AspNetCore.Http/Internal/DefaultHttpRequest.cs @@ -12,11 +12,22 @@ namespace Microsoft.AspNetCore.Http.Internal { public class DefaultHttpRequest : HttpRequest { + private static readonly Func _defaultFormFeatureFactory + = request => new FormFeature(request); + + private readonly Func _formFeatureFactory; + private HttpContext _context; private FeatureReferences _features; public DefaultHttpRequest(HttpContext context) + : this(context, _defaultFormFeatureFactory) + { + } + + public DefaultHttpRequest(HttpContext context, Func formFeatureFactory) { + _formFeatureFactory = formFeatureFactory ?? _defaultFormFeatureFactory; Initialize(context); } @@ -41,7 +52,7 @@ public virtual void Uninitialize() _features.Fetch(ref _features.Cache.Query, f => new QueryFeature(f)); private IFormFeature FormFeature => - _features.Fetch(ref _features.Cache.Form, this, f => new FormFeature(f)); + _features.Fetch(ref _features.Cache.Form, this, request => _formFeatureFactory(request)); private IRequestCookiesFeature RequestCookiesFeature => _features.Fetch(ref _features.Cache.Cookies, f => new RequestCookiesFeature(f)); diff --git a/src/Microsoft.AspNetCore.Http/Internal/DefaultHttpResponse.cs b/src/Microsoft.AspNetCore.Http/Internal/DefaultHttpResponse.cs index 2073f825..6c1a427a 100644 --- a/src/Microsoft.AspNetCore.Http/Internal/DefaultHttpResponse.cs +++ b/src/Microsoft.AspNetCore.Http/Internal/DefaultHttpResponse.cs @@ -11,11 +11,22 @@ namespace Microsoft.AspNetCore.Http.Internal { public class DefaultHttpResponse : HttpResponse { + private static readonly Func _defaultResponseCookiesFeatureFactory + = features => new ResponseCookiesFeature(features); + + private readonly Func _responseCookiesFeatureFactory; + private HttpContext _context; private FeatureReferences _features; public DefaultHttpResponse(HttpContext context) + : this(context, null) + { + } + + public DefaultHttpResponse(HttpContext context, Func responseCookiesFeatureFactory) { + _responseCookiesFeatureFactory = responseCookiesFeatureFactory ?? _defaultResponseCookiesFeatureFactory; Initialize(context); } @@ -35,7 +46,7 @@ public virtual void Uninitialize() _features.Fetch(ref _features.Cache.Response, f => null); private IResponseCookiesFeature ResponseCookiesFeature => - _features.Fetch(ref _features.Cache.Cookies, f => new ResponseCookiesFeature(f)); + _features.Fetch(ref _features.Cache.Cookies, f => _responseCookiesFeatureFactory(f)); public override HttpContext HttpContext { get { return _context; } }