Use ObjectPool for StringBuilder
This commit is contained in:
parent
fb724a71de
commit
8c5a5f7394
|
|
@ -10,14 +10,23 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Http.Headers;
|
using Microsoft.AspNetCore.Http.Headers;
|
||||||
using Microsoft.AspNetCore.ResponseCaching.Internal;
|
using Microsoft.AspNetCore.ResponseCaching.Internal;
|
||||||
|
using Microsoft.Extensions.ObjectPool;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.ResponseCaching
|
namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
{
|
{
|
||||||
public class ResponseCachingContext
|
internal class ResponseCachingContext
|
||||||
{
|
{
|
||||||
private static readonly CacheControlHeaderValue EmptyCacheControl = new CacheControlHeaderValue();
|
private static readonly CacheControlHeaderValue EmptyCacheControl = new CacheControlHeaderValue();
|
||||||
|
|
||||||
|
private readonly HttpContext _httpContext;
|
||||||
|
private readonly IResponseCache _cache;
|
||||||
|
private readonly ISystemClock _clock;
|
||||||
|
private readonly ObjectPool<StringBuilder> _builderPool;
|
||||||
|
private readonly IResponseCachingCacheabilityValidator _cacheabilityValidator;
|
||||||
|
private readonly IResponseCachingCacheKeySuffixProvider _cacheKeySuffixProvider;
|
||||||
|
|
||||||
private string _cacheKey;
|
private string _cacheKey;
|
||||||
private ResponseType? _responseType;
|
private ResponseType? _responseType;
|
||||||
private RequestHeaders _requestHeaders;
|
private RequestHeaders _requestHeaders;
|
||||||
|
|
@ -29,12 +38,13 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
private TimeSpan _cachedResponseValidFor;
|
private TimeSpan _cachedResponseValidFor;
|
||||||
internal DateTimeOffset _responseTime;
|
internal DateTimeOffset _responseTime;
|
||||||
|
|
||||||
public ResponseCachingContext(
|
internal ResponseCachingContext(
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
IResponseCache cache,
|
IResponseCache cache,
|
||||||
|
ObjectPool<StringBuilder> builderPool,
|
||||||
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
||||||
IResponseCachingCacheKeySuffixProvider cacheKeySuffixProvider)
|
IResponseCachingCacheKeySuffixProvider cacheKeySuffixProvider)
|
||||||
: this(httpContext, cache, new SystemClock(), cacheabilityValidator, cacheKeySuffixProvider)
|
: this(httpContext, cache, new SystemClock(), builderPool, cacheabilityValidator, cacheKeySuffixProvider)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,14 +53,16 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
IResponseCache cache,
|
IResponseCache cache,
|
||||||
ISystemClock clock,
|
ISystemClock clock,
|
||||||
|
ObjectPool<StringBuilder> builderPool,
|
||||||
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
||||||
IResponseCachingCacheKeySuffixProvider cacheKeySuffixProvider)
|
IResponseCachingCacheKeySuffixProvider cacheKeySuffixProvider)
|
||||||
{
|
{
|
||||||
HttpContext = httpContext;
|
_httpContext = httpContext;
|
||||||
Cache = cache;
|
_cache = cache;
|
||||||
Clock = clock;
|
_clock = clock;
|
||||||
CacheabilityValidator = cacheabilityValidator;
|
_builderPool = builderPool;
|
||||||
CacheKeySuffixProvider = cacheKeySuffixProvider;
|
_cacheabilityValidator = cacheabilityValidator;
|
||||||
|
_cacheKeySuffixProvider = cacheKeySuffixProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool CacheResponse
|
internal bool CacheResponse
|
||||||
|
|
@ -70,16 +82,6 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
internal bool ResponseStarted { get; set; }
|
internal bool ResponseStarted { get; set; }
|
||||||
|
|
||||||
private HttpContext HttpContext { get; }
|
|
||||||
|
|
||||||
private IResponseCache Cache { get; }
|
|
||||||
|
|
||||||
private ISystemClock Clock { get; }
|
|
||||||
|
|
||||||
private IResponseCachingCacheabilityValidator CacheabilityValidator { get; }
|
|
||||||
|
|
||||||
private IResponseCachingCacheKeySuffixProvider CacheKeySuffixProvider { get; }
|
|
||||||
|
|
||||||
private Stream OriginalResponseStream { get; set; }
|
private Stream OriginalResponseStream { get; set; }
|
||||||
|
|
||||||
private ResponseCacheStream ResponseCacheStream { get; set; }
|
private ResponseCacheStream ResponseCacheStream { get; set; }
|
||||||
|
|
@ -92,7 +94,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
{
|
{
|
||||||
if (_requestHeaders == null)
|
if (_requestHeaders == null)
|
||||||
{
|
{
|
||||||
_requestHeaders = HttpContext.Request.GetTypedHeaders();
|
_requestHeaders = _httpContext.Request.GetTypedHeaders();
|
||||||
}
|
}
|
||||||
return _requestHeaders;
|
return _requestHeaders;
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +106,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
{
|
{
|
||||||
if (_responseHeaders == null)
|
if (_responseHeaders == null)
|
||||||
{
|
{
|
||||||
_responseHeaders = HttpContext.Response.GetTypedHeaders();
|
_responseHeaders = _httpContext.Response.GetTypedHeaders();
|
||||||
}
|
}
|
||||||
return _responseHeaders;
|
return _responseHeaders;
|
||||||
}
|
}
|
||||||
|
|
@ -143,49 +145,58 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
internal string CreateCacheKey(CachedVaryBy varyBy)
|
internal string CreateCacheKey(CachedVaryBy varyBy)
|
||||||
{
|
{
|
||||||
var request = HttpContext.Request;
|
var request = _httpContext.Request;
|
||||||
var builder = new StringBuilder()
|
var builder = _builderPool.Get();
|
||||||
.Append(request.Method.ToUpperInvariant())
|
|
||||||
.Append(";")
|
|
||||||
.Append(request.Path.Value.ToUpperInvariant());
|
|
||||||
|
|
||||||
if (varyBy?.Headers.Count > 0)
|
try
|
||||||
{
|
{
|
||||||
// TODO: resolve key format and delimiters
|
builder
|
||||||
foreach (var header in varyBy.Headers)
|
.Append(request.Method.ToUpperInvariant())
|
||||||
|
.Append(";")
|
||||||
|
.Append(request.Path.Value.ToUpperInvariant());
|
||||||
|
|
||||||
|
if (varyBy?.Headers.Count > 0)
|
||||||
{
|
{
|
||||||
// TODO: Normalization of order, case?
|
// TODO: resolve key format and delimiters
|
||||||
var value = HttpContext.Request.Headers[header];
|
foreach (var header in varyBy.Headers)
|
||||||
|
|
||||||
// TODO: How to handle null/empty string?
|
|
||||||
if (StringValues.IsNullOrEmpty(value))
|
|
||||||
{
|
{
|
||||||
value = "null";
|
// TODO: Normalization of order, case?
|
||||||
|
var value = _httpContext.Request.Headers[header];
|
||||||
|
|
||||||
|
// TODO: How to handle null/empty string?
|
||||||
|
if (StringValues.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
value = "null";
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(";")
|
||||||
|
.Append(header)
|
||||||
|
.Append("=")
|
||||||
|
.Append(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append(";")
|
|
||||||
.Append(header)
|
|
||||||
.Append("=")
|
|
||||||
.Append(value);
|
|
||||||
}
|
}
|
||||||
}
|
// TODO: Parse querystring params
|
||||||
// TODO: Parse querystring params
|
|
||||||
|
|
||||||
// Append custom cache key segment
|
// Append custom cache key segment
|
||||||
var customKey = CacheKeySuffixProvider.CreateCustomKeySuffix(HttpContext);
|
var customKey = _cacheKeySuffixProvider.CreateCustomKeySuffix(_httpContext);
|
||||||
if (!string.IsNullOrEmpty(customKey))
|
if (!string.IsNullOrEmpty(customKey))
|
||||||
|
{
|
||||||
|
builder.Append(";")
|
||||||
|
.Append(customKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
finally
|
||||||
{
|
{
|
||||||
builder.Append(";")
|
_builderPool.Return(builder);
|
||||||
.Append(customKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool RequestIsCacheable()
|
internal bool RequestIsCacheable()
|
||||||
{
|
{
|
||||||
// Use optional override if specified by user
|
// Use optional override if specified by user
|
||||||
switch(CacheabilityValidator.RequestIsCacheableOverride(HttpContext))
|
switch(_cacheabilityValidator.RequestIsCacheableOverride(_httpContext))
|
||||||
{
|
{
|
||||||
case OverrideResult.UseDefaultLogic:
|
case OverrideResult.UseDefaultLogic:
|
||||||
break;
|
break;
|
||||||
|
|
@ -194,12 +205,12 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
case OverrideResult.Cache:
|
case OverrideResult.Cache:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException($"Unrecognized result from {nameof(CacheabilityValidator.RequestIsCacheableOverride)}.");
|
throw new NotSupportedException($"Unrecognized result from {nameof(_cacheabilityValidator.RequestIsCacheableOverride)}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the method
|
// Verify the method
|
||||||
// TODO: RFC lists POST as a cacheable method when explicit freshness information is provided, but this is not widely implemented. Will revisit.
|
// TODO: RFC lists POST as a cacheable method when explicit freshness information is provided, but this is not widely implemented. Will revisit.
|
||||||
var request = HttpContext.Request;
|
var request = _httpContext.Request;
|
||||||
if (string.Equals("GET", request.Method, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals("GET", request.Method, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_responseType = ResponseType.FullReponse;
|
_responseType = ResponseType.FullReponse;
|
||||||
|
|
@ -249,7 +260,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
internal bool ResponseIsCacheable()
|
internal bool ResponseIsCacheable()
|
||||||
{
|
{
|
||||||
// Use optional override if specified by user
|
// Use optional override if specified by user
|
||||||
switch (CacheabilityValidator.ResponseIsCacheableOverride(HttpContext))
|
switch (_cacheabilityValidator.ResponseIsCacheableOverride(_httpContext))
|
||||||
{
|
{
|
||||||
case OverrideResult.UseDefaultLogic:
|
case OverrideResult.UseDefaultLogic:
|
||||||
break;
|
break;
|
||||||
|
|
@ -258,7 +269,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
case OverrideResult.Cache:
|
case OverrideResult.Cache:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException($"Unrecognized result from {nameof(CacheabilityValidator.ResponseIsCacheableOverride)}.");
|
throw new NotSupportedException($"Unrecognized result from {nameof(_cacheabilityValidator.ResponseIsCacheableOverride)}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only cache pages explicitly marked with public
|
// Only cache pages explicitly marked with public
|
||||||
|
|
@ -281,7 +292,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = HttpContext.Response;
|
var response = _httpContext.Response;
|
||||||
|
|
||||||
// Do not cache responses varying by *
|
// Do not cache responses varying by *
|
||||||
if (string.Equals(response.Headers[HeaderNames.Vary], "*", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(response.Headers[HeaderNames.Vary], "*", StringComparison.OrdinalIgnoreCase))
|
||||||
|
|
@ -359,14 +370,14 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
internal async Task<bool> TryServeFromCacheAsync()
|
internal async Task<bool> TryServeFromCacheAsync()
|
||||||
{
|
{
|
||||||
_cacheKey = CreateCacheKey();
|
_cacheKey = CreateCacheKey();
|
||||||
var cacheEntry = Cache.Get(_cacheKey);
|
var cacheEntry = _cache.Get(_cacheKey);
|
||||||
var responseServed = false;
|
var responseServed = false;
|
||||||
|
|
||||||
if (cacheEntry is CachedVaryBy)
|
if (cacheEntry is CachedVaryBy)
|
||||||
{
|
{
|
||||||
// Request contains VaryBy rules, recompute key and try again
|
// Request contains VaryBy rules, recompute key and try again
|
||||||
_cacheKey = CreateCacheKey(cacheEntry as CachedVaryBy);
|
_cacheKey = CreateCacheKey(cacheEntry as CachedVaryBy);
|
||||||
cacheEntry = Cache.Get(_cacheKey);
|
cacheEntry = _cache.Get(_cacheKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheEntry is CachedResponse)
|
if (cacheEntry is CachedResponse)
|
||||||
|
|
@ -374,13 +385,13 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
var cachedResponse = cacheEntry as CachedResponse;
|
var cachedResponse = cacheEntry as CachedResponse;
|
||||||
var cachedResponseHeaders = new ResponseHeaders(cachedResponse.Headers);
|
var cachedResponseHeaders = new ResponseHeaders(cachedResponse.Headers);
|
||||||
|
|
||||||
_responseTime = Clock.UtcNow;
|
_responseTime = _clock.UtcNow;
|
||||||
var age = _responseTime - cachedResponse.Created;
|
var age = _responseTime - cachedResponse.Created;
|
||||||
age = age > TimeSpan.Zero ? age : TimeSpan.Zero;
|
age = age > TimeSpan.Zero ? age : TimeSpan.Zero;
|
||||||
|
|
||||||
if (EntryIsFresh(cachedResponseHeaders, age, verifyAgainstRequest: true))
|
if (EntryIsFresh(cachedResponseHeaders, age, verifyAgainstRequest: true))
|
||||||
{
|
{
|
||||||
var response = HttpContext.Response;
|
var response = _httpContext.Response;
|
||||||
// Copy the cached status code and response headers
|
// Copy the cached status code and response headers
|
||||||
response.StatusCode = cachedResponse.StatusCode;
|
response.StatusCode = cachedResponse.StatusCode;
|
||||||
foreach (var header in cachedResponse.Headers)
|
foreach (var header in cachedResponse.Headers)
|
||||||
|
|
@ -425,7 +436,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
if (!responseServed && RequestCacheControl.OnlyIfCached)
|
if (!responseServed && RequestCacheControl.OnlyIfCached)
|
||||||
{
|
{
|
||||||
HttpContext.Response.StatusCode = StatusCodes.Status504GatewayTimeout;
|
_httpContext.Response.StatusCode = StatusCodes.Status504GatewayTimeout;
|
||||||
|
|
||||||
responseServed = true;
|
responseServed = true;
|
||||||
}
|
}
|
||||||
|
|
@ -438,7 +449,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
if (CacheResponse)
|
if (CacheResponse)
|
||||||
{
|
{
|
||||||
// Create the cache entry now
|
// Create the cache entry now
|
||||||
var response = HttpContext.Response;
|
var response = _httpContext.Response;
|
||||||
var varyHeaderValue = response.Headers[HeaderNames.Vary];
|
var varyHeaderValue = response.Headers[HeaderNames.Vary];
|
||||||
_cachedResponseValidFor = ResponseCacheControl.SharedMaxAge
|
_cachedResponseValidFor = ResponseCacheControl.SharedMaxAge
|
||||||
?? ResponseCacheControl.MaxAge
|
?? ResponseCacheControl.MaxAge
|
||||||
|
|
@ -457,7 +468,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Overwrite?
|
// TODO: Overwrite?
|
||||||
Cache.Set(_cacheKey, cachedVaryBy, _cachedResponseValidFor);
|
_cache.Set(_cacheKey, cachedVaryBy, _cachedResponseValidFor);
|
||||||
_cacheKey = CreateCacheKey(cachedVaryBy);
|
_cacheKey = CreateCacheKey(cachedVaryBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,7 +482,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
_cachedResponse = new CachedResponse
|
_cachedResponse = new CachedResponse
|
||||||
{
|
{
|
||||||
Created = ResponseHeaders.Date.Value,
|
Created = ResponseHeaders.Date.Value,
|
||||||
StatusCode = HttpContext.Response.StatusCode
|
StatusCode = _httpContext.Response.StatusCode
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var header in ResponseHeaders.Headers)
|
foreach (var header in ResponseHeaders.Headers)
|
||||||
|
|
@ -495,7 +506,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
{
|
{
|
||||||
_cachedResponse.Body = ResponseCacheStream.BufferedStream.ToArray();
|
_cachedResponse.Body = ResponseCacheStream.BufferedStream.ToArray();
|
||||||
|
|
||||||
Cache.Set(_cacheKey, _cachedResponse, _cachedResponseValidFor);
|
_cache.Set(_cacheKey, _cachedResponse, _cachedResponseValidFor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -504,7 +515,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
if (!ResponseStarted)
|
if (!ResponseStarted)
|
||||||
{
|
{
|
||||||
ResponseStarted = true;
|
ResponseStarted = true;
|
||||||
_responseTime = Clock.UtcNow;
|
_responseTime = _clock.UtcNow;
|
||||||
|
|
||||||
FinalizeCachingHeaders();
|
FinalizeCachingHeaders();
|
||||||
}
|
}
|
||||||
|
|
@ -515,25 +526,25 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
// TODO: Consider caching large responses on disk and serving them from there.
|
// TODO: Consider caching large responses on disk and serving them from there.
|
||||||
|
|
||||||
// Shim response stream
|
// Shim response stream
|
||||||
OriginalResponseStream = HttpContext.Response.Body;
|
OriginalResponseStream = _httpContext.Response.Body;
|
||||||
ResponseCacheStream = new ResponseCacheStream(OriginalResponseStream);
|
ResponseCacheStream = new ResponseCacheStream(OriginalResponseStream);
|
||||||
HttpContext.Response.Body = ResponseCacheStream;
|
_httpContext.Response.Body = ResponseCacheStream;
|
||||||
|
|
||||||
// Shim IHttpSendFileFeature
|
// Shim IHttpSendFileFeature
|
||||||
OriginalSendFileFeature = HttpContext.Features.Get<IHttpSendFileFeature>();
|
OriginalSendFileFeature = _httpContext.Features.Get<IHttpSendFileFeature>();
|
||||||
if (OriginalSendFileFeature != null)
|
if (OriginalSendFileFeature != null)
|
||||||
{
|
{
|
||||||
HttpContext.Features.Set<IHttpSendFileFeature>(new SendFileFeatureWrapper(OriginalSendFileFeature, ResponseCacheStream));
|
_httpContext.Features.Set<IHttpSendFileFeature>(new SendFileFeatureWrapper(OriginalSendFileFeature, ResponseCacheStream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UnshimResponseStream()
|
internal void UnshimResponseStream()
|
||||||
{
|
{
|
||||||
// Unshim response stream
|
// Unshim response stream
|
||||||
HttpContext.Response.Body = OriginalResponseStream;
|
_httpContext.Response.Body = OriginalResponseStream;
|
||||||
|
|
||||||
// Unshim IHttpSendFileFeature
|
// Unshim IHttpSendFileFeature
|
||||||
HttpContext.Features.Set(OriginalSendFileFeature);
|
_httpContext.Features.Set(OriginalSendFileFeature);
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum ResponseType
|
private enum ResponseType
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,11 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.ObjectPool;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.ResponseCaching
|
namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
{
|
{
|
||||||
|
|
@ -17,22 +20,28 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IResponseCache _cache;
|
private readonly IResponseCache _cache;
|
||||||
IResponseCachingCacheabilityValidator _cacheabilityValidator;
|
private readonly ObjectPool<StringBuilder> _builderPool;
|
||||||
IResponseCachingCacheKeySuffixProvider _cacheKeySuffixProvider;
|
private readonly IResponseCachingCacheabilityValidator _cacheabilityValidator;
|
||||||
|
private readonly IResponseCachingCacheKeySuffixProvider _cacheKeySuffixProvider;
|
||||||
|
|
||||||
public ResponseCachingMiddleware(
|
public ResponseCachingMiddleware(
|
||||||
RequestDelegate next,
|
RequestDelegate next,
|
||||||
IResponseCache cache,
|
IResponseCache cache,
|
||||||
|
ObjectPoolProvider poolProvider,
|
||||||
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
||||||
IResponseCachingCacheKeySuffixProvider cacheKeySuffixProvider)
|
IResponseCachingCacheKeySuffixProvider cacheKeySuffixProvider)
|
||||||
{
|
{
|
||||||
|
if (next == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(next));
|
||||||
|
}
|
||||||
if (cache == null)
|
if (cache == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(cache));
|
throw new ArgumentNullException(nameof(cache));
|
||||||
}
|
}
|
||||||
if (next == null)
|
if (poolProvider == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(next));
|
throw new ArgumentNullException(nameof(poolProvider));
|
||||||
}
|
}
|
||||||
if (cacheabilityValidator == null)
|
if (cacheabilityValidator == null)
|
||||||
{
|
{
|
||||||
|
|
@ -45,6 +54,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
_next = next;
|
_next = next;
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
|
_builderPool = poolProvider.CreateStringBuilderPool();
|
||||||
_cacheabilityValidator = cacheabilityValidator;
|
_cacheabilityValidator = cacheabilityValidator;
|
||||||
_cacheKeySuffixProvider = cacheKeySuffixProvider;
|
_cacheKeySuffixProvider = cacheKeySuffixProvider;
|
||||||
}
|
}
|
||||||
|
|
@ -54,6 +64,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
var cachingContext = new ResponseCachingContext(
|
var cachingContext = new ResponseCachingContext(
|
||||||
context,
|
context,
|
||||||
_cache,
|
_cache,
|
||||||
|
_builderPool,
|
||||||
_cacheabilityValidator,
|
_cacheabilityValidator,
|
||||||
_cacheKeySuffixProvider);
|
_cacheKeySuffixProvider);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,14 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Http.Headers;
|
using Microsoft.AspNetCore.Http.Headers;
|
||||||
using Microsoft.AspNetCore.ResponseCaching.Internal;
|
using Microsoft.AspNetCore.ResponseCaching.Internal;
|
||||||
|
using Microsoft.Extensions.ObjectPool;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -656,6 +658,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
httpContext,
|
httpContext,
|
||||||
new TestResponseCache(),
|
new TestResponseCache(),
|
||||||
new SystemClock(),
|
new SystemClock(),
|
||||||
|
new DefaultObjectPool<StringBuilder>(new StringBuilderPooledObjectPolicy()),
|
||||||
cacheabilityValidator,
|
cacheabilityValidator,
|
||||||
cacheKeySuffixProvider);
|
cacheKeySuffixProvider);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue