API review feedback

Rename middleware components ResponseCache => ResponseCaching

Move ResponseCachingOptions to Microsoft.AspNetCore.ResponseCaching namespace

Rename extension methods
This commit is contained in:
John Luo 2016-10-14 15:44:21 -07:00
parent 151ac2cdcb
commit 8acf71457e
26 changed files with 480 additions and 448 deletions

View File

@ -15,12 +15,12 @@ namespace ResponseCachingSample
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryResponseCacheStore();
services.AddResponseCaching();
}
public void Configure(IApplicationBuilder app)
{
app.UseResponseCache();
app.UseResponseCaching();
app.Run(async (context) =>
{
context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue()

View File

@ -1,18 +1,16 @@
// 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.Extensions.Primitives;
namespace Microsoft.AspNetCore.ResponseCaching
{
/// <summary>
/// A feature for configuring additional response cache options on the HTTP response.
/// </summary>
public interface IResponseCacheFeature
public interface IResponseCachingFeature
{
/// <summary>
/// Gets or sets the query keys used by the response cache middleware for calculating secondary vary keys.
/// </summary>
StringValues VaryByQueryKeys { get; set; }
string[] VaryByQueryKeys { get; set; }
}
}

View File

@ -17,11 +17,13 @@
"caching"
]
},
"dependencies": {
"Microsoft.Extensions.Primitives": "1.0.0"
},
"frameworks": {
"net451": {},
"netstandard1.3": {}
"netstandard1.3": {
"dependencies": {
"System.Runtime": "4.1.0",
"System.Resources.ResourceManager": "4.0.1"
}
}
}
}

View File

@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
public interface IResponseCacheStore
public interface IResponseCache
{
Task<IResponseCacheEntry> GetAsync(string key);
Task SetAsync(string key, IResponseCacheEntry entry, TimeSpan validFor);

View File

@ -5,27 +5,27 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
public interface IResponseCacheKeyProvider
public interface IResponseCachingKeyProvider
{
/// <summary>
/// Create a base key for a response cache entry.
/// </summary>
/// <param name="context">The <see cref="ResponseCacheContext"/>.</param>
/// <param name="context">The <see cref="ResponseCachingContext"/>.</param>
/// <returns>The created base key.</returns>
string CreateBaseKey(ResponseCacheContext context);
string CreateBaseKey(ResponseCachingContext context);
/// <summary>
/// Create a vary key for storing cached responses.
/// </summary>
/// <param name="context">The <see cref="ResponseCacheContext"/>.</param>
/// <param name="context">The <see cref="ResponseCachingContext"/>.</param>
/// <returns>The created vary key.</returns>
string CreateStorageVaryByKey(ResponseCacheContext context);
string CreateStorageVaryByKey(ResponseCachingContext context);
/// <summary>
/// Create one or more vary keys for looking up cached responses.
/// </summary>
/// <param name="context">The <see cref="ResponseCacheContext"/>.</param>
/// <param name="context">The <see cref="ResponseCachingContext"/>.</param>
/// <returns>An ordered <see cref="IEnumerable{T}"/> containing the vary keys to try when looking up items.</returns>
IEnumerable<string> CreateLookupVaryByKeys(ResponseCacheContext context);
IEnumerable<string> CreateLookupVaryByKeys(ResponseCachingContext context);
}
}

View File

@ -3,27 +3,27 @@
namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
public interface IResponseCachePolicyProvider
public interface IResponseCachingPolicyProvider
{
/// <summary>
/// Determine wehther the response cache middleware should be executed for the incoming HTTP request.
/// </summary>
/// <param name="context">The <see cref="ResponseCacheContext"/>.</param>
/// <param name="context">The <see cref="ResponseCachingContext"/>.</param>
/// <returns><c>true</c> if the request is cacheable; otherwise <c>false</c>.</returns>
bool IsRequestCacheable(ResponseCacheContext context);
bool IsRequestCacheable(ResponseCachingContext context);
/// <summary>
/// Determine whether the response received by the middleware be cached for future requests.
/// </summary>
/// <param name="context">The <see cref="ResponseCacheContext"/>.</param>
/// <param name="context">The <see cref="ResponseCachingContext"/>.</param>
/// <returns><c>true</c> if the response is cacheable; otherwise <c>false</c>.</returns>
bool IsResponseCacheable(ResponseCacheContext context);
bool IsResponseCacheable(ResponseCachingContext context);
/// <summary>
/// Determine whether the response retrieved from the response cache is fresh and be served.
/// </summary>
/// <param name="context">The <see cref="ResponseCacheContext"/>.</param>
/// <param name="context">The <see cref="ResponseCachingContext"/>.</param>
/// <returns><c>true</c> if the cached entry is fresh; otherwise <c>false</c>.</returns>
bool IsCachedEntryFresh(ResponseCacheContext context);
bool IsCachedEntryFresh(ResponseCachingContext context);
}
}

View File

@ -7,11 +7,11 @@ using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
public class MemoryResponseCacheStore : IResponseCacheStore
public class MemoryResponseCache : IResponseCache
{
private readonly IMemoryCache _cache;
public MemoryResponseCacheStore(IMemoryCache cache)
public MemoryResponseCache(IMemoryCache cache)
{
if (cache == null)
{

View File

@ -11,7 +11,7 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
public class ResponseCacheContext
public class ResponseCachingContext
{
private static readonly CacheControlHeaderValue EmptyCacheControl = new CacheControlHeaderValue();
@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
private DateTimeOffset? _responseExpires;
private bool _parsedResponseExpires;
internal ResponseCacheContext(HttpContext httpContext, ILogger logger)
internal ResponseCachingContext(HttpContext httpContext, ILogger logger)
{
HttpContext = httpContext;
Logger = logger;
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
internal Stream OriginalResponseStream { get; set; }
internal ResponseCacheStream ResponseCacheStream { get; set; }
internal ResponseCachingStream ResponseCachingStream { get; set; }
internal IHttpSendFileFeature OriginalSendFileFeature { get; set; }

View File

@ -5,23 +5,21 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.ResponseCaching.Internal;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
public class ResponseCacheKeyProvider : IResponseCacheKeyProvider
public class ResponseCachingKeyProvider : IResponseCachingKeyProvider
{
// Use the record separator for delimiting components of the cache key to avoid possible collisions
private static readonly char KeyDelimiter = '\x1e';
private readonly ObjectPool<StringBuilder> _builderPool;
private readonly ResponseCacheOptions _options;
private readonly ResponseCachingOptions _options;
public ResponseCacheKeyProvider(ObjectPoolProvider poolProvider, IOptions<ResponseCacheOptions> options)
public ResponseCachingKeyProvider(ObjectPoolProvider poolProvider, IOptions<ResponseCachingOptions> options)
{
if (poolProvider == null)
{
@ -36,13 +34,13 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
_options = options.Value;
}
public IEnumerable<string> CreateLookupVaryByKeys(ResponseCacheContext context)
public IEnumerable<string> CreateLookupVaryByKeys(ResponseCachingContext context)
{
return new string[] { CreateStorageVaryByKey(context) };
}
// GET<delimiter>/PATH
public string CreateBaseKey(ResponseCacheContext context)
public string CreateBaseKey(ResponseCachingContext context)
{
if (context == null)
{
@ -76,7 +74,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
}
// BaseKey<delimiter>H<delimiter>HeaderName=HeaderValue<delimiter>Q<delimiter>QueryName=QueryValue
public string CreateStorageVaryByKey(ResponseCacheContext context)
public string CreateStorageVaryByKey(ResponseCachingContext context)
{
if (context == null)
{
@ -86,7 +84,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
var varyByRules = context.CachedVaryByRules;
if (varyByRules == null)
{
throw new InvalidOperationException($"{nameof(CachedVaryByRules)} must not be null on the {nameof(ResponseCacheContext)}");
throw new InvalidOperationException($"{nameof(CachedVaryByRules)} must not be null on the {nameof(ResponseCachingContext)}");
}
if ((StringValues.IsNullOrEmpty(varyByRules.Headers) && StringValues.IsNullOrEmpty(varyByRules.QueryKeys)))

View File

@ -8,11 +8,11 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
public class ResponseCachePolicyProvider : IResponseCachePolicyProvider
public class ResponseCachingPolicyProvider : IResponseCachingPolicyProvider
{
private static readonly CacheControlHeaderValue EmptyCacheControl = new CacheControlHeaderValue();
public virtual bool IsRequestCacheable(ResponseCacheContext context)
public virtual bool IsRequestCacheable(ResponseCachingContext context)
{
// Verify the method
var request = context.HttpContext.Request;
@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
return true;
}
public virtual bool IsResponseCacheable(ResponseCacheContext context)
public virtual bool IsResponseCacheable(ResponseCachingContext context)
{
// Only cache pages explicitly marked with public
if (!context.ResponseCacheControlHeaderValue.Public)
@ -156,7 +156,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
return true;
}
public virtual bool IsCachedEntryFresh(ResponseCacheContext context)
public virtual bool IsCachedEntryFresh(ResponseCachingContext context)
{
var age = context.CachedEntryAge.Value;
var cachedControlHeaders = context.CachedResponseHeaders.CacheControl ?? EmptyCacheControl;

View File

@ -10,18 +10,18 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
internal class SendFileFeatureWrapper : IHttpSendFileFeature
{
private readonly IHttpSendFileFeature _originalSendFileFeature;
private readonly ResponseCacheStream _responseCacheStream;
private readonly ResponseCachingStream _responseCachingStream;
public SendFileFeatureWrapper(IHttpSendFileFeature originalSendFileFeature, ResponseCacheStream responseCacheStream)
public SendFileFeatureWrapper(IHttpSendFileFeature originalSendFileFeature, ResponseCachingStream responseCachingStream)
{
_originalSendFileFeature = originalSendFileFeature;
_responseCacheStream = responseCacheStream;
_responseCachingStream = responseCachingStream;
}
// Flush and disable the buffer if anyone tries to call the SendFile feature.
public Task SendFileAsync(string path, long offset, long? length, CancellationToken cancellation)
{
_responseCacheStream.DisableBuffering();
_responseCachingStream.DisableBuffering();
return _originalSendFileFeature.SendFileAsync(path, offset, length, cancellation);
}
}

View File

@ -1,36 +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 Microsoft.AspNetCore.ResponseCaching;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Builder
{
public static class ResponseCacheExtensions
{
public static IApplicationBuilder UseResponseCache(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<ResponseCacheMiddleware>();
}
public static IApplicationBuilder UseResponseCache(this IApplicationBuilder app, ResponseCacheOptions options)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
return app.UseMiddleware<ResponseCacheMiddleware>(Options.Create(options));
}
}
}

View File

@ -1,28 +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 Microsoft.AspNetCore.ResponseCaching;
using Microsoft.AspNetCore.ResponseCaching.Internal;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
public static class ResponseCacheServiceCollectionExtensions
{
public static IServiceCollection AddMemoryResponseCacheStore(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddMemoryCache();
services.TryAdd(ServiceDescriptor.Singleton<IResponseCachePolicyProvider, ResponseCachePolicyProvider>());
services.TryAdd(ServiceDescriptor.Singleton<IResponseCacheKeyProvider, ResponseCacheKeyProvider>());
services.TryAdd(ServiceDescriptor.Singleton<IResponseCacheStore, MemoryResponseCacheStore>());
return services;
}
}
}

View File

@ -0,0 +1,22 @@
// 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 Microsoft.AspNetCore.ResponseCaching;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Builder
{
public static class ResponseCachingExtensions
{
public static IApplicationBuilder UseResponseCaching(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<ResponseCachingMiddleware>();
}
}
}

View File

@ -2,15 +2,14 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.ResponseCaching
{
public class ResponseCacheFeature : IResponseCacheFeature
public class ResponseCachingFeature : IResponseCachingFeature
{
private StringValues _varyByQueryKeys;
private string[] _varyByQueryKeys;
public StringValues VaryByQueryKeys
public string[] VaryByQueryKeys
{
get
{
@ -18,9 +17,9 @@ namespace Microsoft.AspNetCore.ResponseCaching
}
set
{
if (value.Count > 1)
if (value?.Length > 1)
{
for (var i = 0; i < value.Count; i++)
for (var i = 0; i < value.Length; i++)
{
if (string.IsNullOrEmpty(value[i]))
{

View File

@ -4,7 +4,6 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http.Headers;
@ -17,25 +16,25 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.ResponseCaching
{
public class ResponseCacheMiddleware
public class ResponseCachingMiddleware
{
private static readonly TimeSpan DefaultExpirationTimeSpan = TimeSpan.FromSeconds(10);
private readonly RequestDelegate _next;
private readonly ResponseCacheOptions _options;
private readonly ResponseCachingOptions _options;
private readonly ILogger _logger;
private readonly IResponseCachePolicyProvider _policyProvider;
private readonly IResponseCacheStore _store;
private readonly IResponseCacheKeyProvider _keyProvider;
private readonly IResponseCachingPolicyProvider _policyProvider;
private readonly IResponseCache _cache;
private readonly IResponseCachingKeyProvider _keyProvider;
private readonly Func<object, Task> _onStartingCallback;
public ResponseCacheMiddleware(
public ResponseCachingMiddleware(
RequestDelegate next,
IOptions<ResponseCacheOptions> options,
IOptions<ResponseCachingOptions> options,
ILoggerFactory loggerFactory,
IResponseCachePolicyProvider policyProvider,
IResponseCacheStore store,
IResponseCacheKeyProvider keyProvider)
IResponseCachingPolicyProvider policyProvider,
IResponseCache cache,
IResponseCachingKeyProvider keyProvider)
{
if (next == null)
{
@ -53,9 +52,9 @@ namespace Microsoft.AspNetCore.ResponseCaching
{
throw new ArgumentNullException(nameof(policyProvider));
}
if (store == null)
if (cache == null)
{
throw new ArgumentNullException(nameof(store));
throw new ArgumentNullException(nameof(cache));
}
if (keyProvider == null)
{
@ -64,16 +63,16 @@ namespace Microsoft.AspNetCore.ResponseCaching
_next = next;
_options = options.Value;
_logger = loggerFactory.CreateLogger<ResponseCacheMiddleware>();
_logger = loggerFactory.CreateLogger<ResponseCachingMiddleware>();
_policyProvider = policyProvider;
_store = store;
_cache = cache;
_keyProvider = keyProvider;
_onStartingCallback = state => OnResponseStartingAsync((ResponseCacheContext)state);
_onStartingCallback = state => OnResponseStartingAsync((ResponseCachingContext)state);
}
public async Task Invoke(HttpContext httpContext)
{
var context = new ResponseCacheContext(httpContext, _logger);
var context = new ResponseCachingContext(httpContext, _logger);
// Should we attempt any caching logic?
if (_policyProvider.IsRequestCacheable(context))
@ -111,7 +110,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
}
}
internal async Task<bool> TryServeCachedResponseAsync(ResponseCacheContext context, CachedResponse cachedResponse)
internal async Task<bool> TryServeCachedResponseAsync(ResponseCachingContext context, CachedResponse cachedResponse)
{
context.CachedResponse = cachedResponse;
context.CachedResponseHeaders = new ResponseHeaders(cachedResponse.Headers);
@ -166,10 +165,10 @@ namespace Microsoft.AspNetCore.ResponseCaching
return false;
}
internal async Task<bool> TryServeFromCacheAsync(ResponseCacheContext context)
internal async Task<bool> TryServeFromCacheAsync(ResponseCachingContext context)
{
context.BaseKey = _keyProvider.CreateBaseKey(context);
var cacheEntry = await _store.GetAsync(context.BaseKey);
var cacheEntry = await _cache.GetAsync(context.BaseKey);
if (cacheEntry is CachedVaryByRules)
{
@ -178,7 +177,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
foreach (var varyKey in _keyProvider.CreateLookupVaryByKeys(context))
{
cacheEntry = await _store.GetAsync(varyKey);
cacheEntry = await _cache.GetAsync(varyKey);
if (cacheEntry is CachedResponse && await TryServeCachedResponseAsync(context, (CachedResponse)cacheEntry))
{
@ -202,7 +201,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
return false;
}
internal async Task FinalizeCacheHeadersAsync(ResponseCacheContext context)
internal async Task FinalizeCacheHeadersAsync(ResponseCachingContext context)
{
if (_policyProvider.IsResponseCacheable(context))
{
@ -211,7 +210,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
// Create the cache entry now
var response = context.HttpContext.Response;
var varyHeaders = new StringValues(response.Headers.GetCommaSeparatedValues(HeaderNames.Vary));
var varyQueryKeys = context.HttpContext.Features.Get<IResponseCacheFeature>()?.VaryByQueryKeys ?? StringValues.Empty;
var varyQueryKeys = new StringValues(context.HttpContext.Features.Get<IResponseCachingFeature>()?.VaryByQueryKeys);
context.CachedResponseValidFor = context.ResponseCacheControlHeaderValue.SharedMaxAge ??
context.ResponseCacheControlHeaderValue.MaxAge ??
(context.ResponseExpires - context.ResponseTime.Value) ??
@ -239,7 +238,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
// Always overwrite the CachedVaryByRules to update the expiry information
_logger.LogVaryByRulesUpdated(normalizedVaryHeaders, normalizedVaryQueryKeys);
await _store.SetAsync(context.BaseKey, context.CachedVaryByRules, context.CachedResponseValidFor);
await _cache.SetAsync(context.BaseKey, context.CachedVaryByRules, context.CachedResponseValidFor);
context.StorageVaryKey = _keyProvider.CreateStorageVaryByKey(context);
}
@ -269,21 +268,21 @@ namespace Microsoft.AspNetCore.ResponseCaching
}
else
{
context.ResponseCacheStream.DisableBuffering();
context.ResponseCachingStream.DisableBuffering();
}
}
internal async Task FinalizeCacheBodyAsync(ResponseCacheContext context)
internal async Task FinalizeCacheBodyAsync(ResponseCachingContext context)
{
var contentLength = context.TypedResponseHeaders.ContentLength;
if (context.ShouldCacheResponse && context.ResponseCacheStream.BufferingEnabled)
if (context.ShouldCacheResponse && context.ResponseCachingStream.BufferingEnabled)
{
var bufferStream = context.ResponseCacheStream.GetBufferStream();
var bufferStream = context.ResponseCachingStream.GetBufferStream();
if (!contentLength.HasValue || contentLength == bufferStream.Length)
{
context.CachedResponse.Body = bufferStream;
_logger.LogResponseCached();
await _store.SetAsync(context.StorageVaryKey ?? context.BaseKey, context.CachedResponse, context.CachedResponseValidFor);
await _cache.SetAsync(context.StorageVaryKey ?? context.BaseKey, context.CachedResponse, context.CachedResponseValidFor);
}
else
{
@ -296,7 +295,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
}
}
internal Task OnResponseStartingAsync(ResponseCacheContext context)
internal Task OnResponseStartingAsync(ResponseCachingContext context)
{
if (!context.ResponseStarted)
{
@ -311,29 +310,29 @@ namespace Microsoft.AspNetCore.ResponseCaching
}
}
internal void ShimResponseStream(ResponseCacheContext context)
internal void ShimResponseStream(ResponseCachingContext context)
{
// Shim response stream
context.OriginalResponseStream = context.HttpContext.Response.Body;
context.ResponseCacheStream = new ResponseCacheStream(context.OriginalResponseStream, _options.MaximumBodySize, StreamUtilities.BodySegmentSize);
context.HttpContext.Response.Body = context.ResponseCacheStream;
context.ResponseCachingStream = new ResponseCachingStream(context.OriginalResponseStream, _options.MaximumBodySize, StreamUtilities.BodySegmentSize);
context.HttpContext.Response.Body = context.ResponseCachingStream;
// Shim IHttpSendFileFeature
context.OriginalSendFileFeature = context.HttpContext.Features.Get<IHttpSendFileFeature>();
if (context.OriginalSendFileFeature != null)
{
context.HttpContext.Features.Set<IHttpSendFileFeature>(new SendFileFeatureWrapper(context.OriginalSendFileFeature, context.ResponseCacheStream));
context.HttpContext.Features.Set<IHttpSendFileFeature>(new SendFileFeatureWrapper(context.OriginalSendFileFeature, context.ResponseCachingStream));
}
// Add IResponseCacheFeature
if (context.HttpContext.Features.Get<IResponseCacheFeature>() != null)
// Add IResponseCachingFeature
if (context.HttpContext.Features.Get<IResponseCachingFeature>() != null)
{
throw new InvalidOperationException($"Another instance of {nameof(ResponseCacheFeature)} already exists. Only one instance of {nameof(ResponseCacheMiddleware)} can be configured for an application.");
throw new InvalidOperationException($"Another instance of {nameof(ResponseCachingFeature)} already exists. Only one instance of {nameof(ResponseCachingMiddleware)} can be configured for an application.");
}
context.HttpContext.Features.Set<IResponseCacheFeature>(new ResponseCacheFeature());
context.HttpContext.Features.Set<IResponseCachingFeature>(new ResponseCachingFeature());
}
internal static void UnshimResponseStream(ResponseCacheContext context)
internal static void UnshimResponseStream(ResponseCachingContext context)
{
// Unshim response stream
context.HttpContext.Response.Body = context.OriginalResponseStream;
@ -341,11 +340,11 @@ namespace Microsoft.AspNetCore.ResponseCaching
// Unshim IHttpSendFileFeature
context.HttpContext.Features.Set(context.OriginalSendFileFeature);
// Remove IResponseCacheFeature
context.HttpContext.Features.Set<IResponseCacheFeature>(null);
// Remove IResponseCachingFeature
context.HttpContext.Features.Set<IResponseCachingFeature>(null);
}
internal static bool ContentIsNotModified(ResponseCacheContext context)
internal static bool ContentIsNotModified(ResponseCachingContext context)
{
var cachedResponseHeaders = context.CachedResponseHeaders;
var ifNoneMatchHeader = context.TypedRequestHeaders.IfNoneMatch;

View File

@ -4,9 +4,9 @@
using System.ComponentModel;
using Microsoft.AspNetCore.ResponseCaching.Internal;
namespace Microsoft.AspNetCore.Builder
namespace Microsoft.AspNetCore.ResponseCaching
{
public class ResponseCacheOptions
public class ResponseCachingOptions
{
/// <summary>
/// The largest cacheable size for the response body in bytes. The default is set to 64 MB.

View File

@ -0,0 +1,59 @@
// 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 Microsoft.AspNetCore.ResponseCaching;
using Microsoft.AspNetCore.ResponseCaching.Internal;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for the ResponseCaching middleware.
/// </summary>
public static class ResponseCachingServicesExtensions
{
/// <summary>
/// Add response caching services.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> for adding services.</param>
/// <returns></returns>
public static IServiceCollection AddResponseCaching(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddMemoryCache();
services.TryAdd(ServiceDescriptor.Singleton<IResponseCachingPolicyProvider, ResponseCachingPolicyProvider>());
services.TryAdd(ServiceDescriptor.Singleton<IResponseCachingKeyProvider, ResponseCachingKeyProvider>());
services.TryAdd(ServiceDescriptor.Singleton<IResponseCache, MemoryResponseCache>());
return services;
}
/// <summary>
/// Add response caching services and configure the related options.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> for adding services.</param>
/// <param name="configureOptions">A delegate to configure the <see cref="ResponseCachingOptions"/>.</param>
/// <returns></returns>
public static IServiceCollection AddResponseCaching(this IServiceCollection services, Action<ResponseCachingOptions> configureOptions)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
if (configureOptions == null)
{
throw new ArgumentNullException(nameof(configureOptions));
}
services.Configure(configureOptions);
services.AddResponseCaching();
return services;
}
}
}

View File

@ -8,14 +8,14 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
internal class ResponseCacheStream : Stream
internal class ResponseCachingStream : Stream
{
private readonly Stream _innerStream;
private readonly long _maxBufferSize;
private readonly int _segmentSize;
private SegmentWriteStream _segmentWriteStream;
internal ResponseCacheStream(Stream innerStream, long maxBufferSize, int segmentSize)
internal ResponseCachingStream(Stream innerStream, long maxBufferSize, int segmentSize)
{
_innerStream = innerStream;
_maxBufferSize = maxBufferSize;

View File

@ -1,64 +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 Microsoft.Extensions.Primitives;
using Xunit;
namespace Microsoft.AspNetCore.ResponseCaching.Tests
{
public class ResponseCacheFeatureTests
{
public static TheoryData<StringValues> ValidNullOrEmptyVaryRules
{
get
{
return new TheoryData<StringValues>
{
default(StringValues),
StringValues.Empty,
new StringValues((string)null),
new StringValues(string.Empty),
new StringValues((string[])null),
new StringValues(new string[0]),
new StringValues(new string[] { null }),
new StringValues(new string[] { string.Empty })
};
}
}
[Theory]
[MemberData(nameof(ValidNullOrEmptyVaryRules))]
public void VaryByQueryKeys_Set_ValidEmptyValues_Succeeds(StringValues value)
{
// Does not throw
new ResponseCacheFeature().VaryByQueryKeys = value;
}
public static TheoryData<StringValues> InvalidVaryRules
{
get
{
return new TheoryData<StringValues>
{
new StringValues(new string[] { null, null }),
new StringValues(new string[] { null, string.Empty }),
new StringValues(new string[] { string.Empty, null }),
new StringValues(new string[] { string.Empty, "Valid" }),
new StringValues(new string[] { "Valid", string.Empty }),
new StringValues(new string[] { null, "Valid" }),
new StringValues(new string[] { "Valid", null })
};
}
}
[Theory]
[MemberData(nameof(InvalidVaryRules))]
public void VaryByQueryKeys_Set_InValidEmptyValues_Throws(StringValues value)
{
// Throws
Assert.Throws<ArgumentException>(() => new ResponseCacheFeature().VaryByQueryKeys = value);
}
}
}

View File

@ -0,0 +1,59 @@
// 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 Xunit;
namespace Microsoft.AspNetCore.ResponseCaching.Tests
{
public class ResponseCachingFeatureTests
{
public static TheoryData<string[]> ValidNullOrEmptyVaryRules
{
get
{
return new TheoryData<string[]>
{
null,
new string[0],
new string[] { null },
new string[] { string.Empty }
};
}
}
[Theory]
[MemberData(nameof(ValidNullOrEmptyVaryRules))]
public void VaryByQueryKeys_Set_ValidEmptyValues_Succeeds(string[] value)
{
// Does not throw
new ResponseCachingFeature().VaryByQueryKeys = value;
}
public static TheoryData<string[]> InvalidVaryRules
{
get
{
return new TheoryData<string[]>
{
new string[] { null, null },
new string[] { null, string.Empty },
new string[] { string.Empty, null },
new string[] { string.Empty, "Valid" },
new string[] { "Valid", string.Empty },
new string[] { null, "Valid" },
new string[] { "Valid", null }
};
}
}
[Theory]
[MemberData(nameof(InvalidVaryRules))]
public void VaryByQueryKeys_Set_InValidEmptyValues_Throws(string[] value)
{
// Throws
Assert.Throws<ArgumentException>(() => new ResponseCachingFeature().VaryByQueryKeys = value);
}
}
}

View File

@ -2,19 +2,18 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.ResponseCaching.Internal;
using Xunit;
namespace Microsoft.AspNetCore.ResponseCaching.Tests
{
public class ResponseCacheKeyProviderTests
public class ResponseCachingKeyProviderTests
{
private static readonly char KeyDelimiter = '\x1e';
[Fact]
public void ResponseCacheKeyProvider_CreateStorageBaseKey_IncludesOnlyNormalizedMethodAndPath()
public void ResponseCachingKeyProvider_CreateStorageBaseKey_IncludesOnlyNormalizedMethodAndPath()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();
@ -29,9 +28,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageBaseKey_CaseInsensitivePath_NormalizesPath()
public void ResponseCachingKeyProvider_CreateStorageBaseKey_CaseInsensitivePath_NormalizesPath()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider(new ResponseCacheOptions()
var cacheKeyProvider = TestUtils.CreateTestKeyProvider(new ResponseCachingOptions()
{
UseCaseSensitivePaths = false
});
@ -43,9 +42,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageBaseKey_CaseSensitivePath_PreservesPathCase()
public void ResponseCachingKeyProvider_CreateStorageBaseKey_CaseSensitivePath_PreservesPathCase()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider(new ResponseCacheOptions()
var cacheKeyProvider = TestUtils.CreateTestKeyProvider(new ResponseCachingOptions()
{
UseCaseSensitivePaths = true
});
@ -57,7 +56,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageVaryByKey_Throws_IfVaryByRulesIsNull()
public void ResponseCachingKeyProvider_CreateStorageVaryByKey_Throws_IfVaryByRulesIsNull()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();
@ -66,7 +65,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageVaryKey_ReturnsCachedVaryByGuid_IfVaryByRulesIsEmpty()
public void ResponseCachingKeyProvider_CreateStorageVaryKey_ReturnsCachedVaryByGuid_IfVaryByRulesIsEmpty()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();
@ -79,7 +78,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesListedHeadersOnly()
public void ResponseCachingKeyProvider_CreateStorageVaryKey_IncludesListedHeadersOnly()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();
@ -95,7 +94,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesListedQueryKeysOnly()
public void ResponseCachingKeyProvider_CreateStorageVaryKey_IncludesListedQueryKeysOnly()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();
@ -111,7 +110,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesQueryKeys_QueryKeyCaseInsensitive_UseQueryKeyCasing()
public void ResponseCachingKeyProvider_CreateStorageVaryKey_IncludesQueryKeys_QueryKeyCaseInsensitive_UseQueryKeyCasing()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();
@ -127,7 +126,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesAllQueryKeysGivenAsterisk()
public void ResponseCachingKeyProvider_CreateStorageVaryKey_IncludesAllQueryKeysGivenAsterisk()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();
@ -145,7 +144,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
[Fact]
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesListedHeadersAndQueryKeys()
public void ResponseCachingKeyProvider_CreateStorageVaryKey_IncludesListedHeadersAndQueryKeys()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();

View File

@ -14,14 +14,14 @@ using Xunit;
namespace Microsoft.AspNetCore.ResponseCaching.Tests
{
public class ResponseCacheMiddlewareTests
public class ResponseCachingMiddlewareTests
{
[Fact]
public async Task TryServeFromCacheAsync_OnlyIfCached_Serves504()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store, keyProvider: new TestResponseCacheKeyProvider());
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider());
var context = TestUtils.CreateTestContext();
context.TypedRequestHeaders.CacheControl = new CacheControlHeaderValue()
{
@ -38,13 +38,13 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task TryServeFromCacheAsync_CachedResponseNotFound_Fails()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store, keyProvider: new TestResponseCacheKeyProvider("BaseKey"));
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider("BaseKey"));
var context = TestUtils.CreateTestContext();
Assert.False(await middleware.TryServeFromCacheAsync(context));
Assert.Equal(1, store.GetCount);
Assert.Equal(1, cache.GetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.NoResponseServed);
@ -53,12 +53,12 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task TryServeFromCacheAsync_CachedResponseFound_Succeeds()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store, keyProvider: new TestResponseCacheKeyProvider("BaseKey"));
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider("BaseKey"));
var context = TestUtils.CreateTestContext();
await store.SetAsync(
await cache.SetAsync(
"BaseKey",
new CachedResponse()
{
@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
TimeSpan.Zero);
Assert.True(await middleware.TryServeFromCacheAsync(context));
Assert.Equal(1, store.GetCount);
Assert.Equal(1, cache.GetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.CachedResponseServed);
@ -76,18 +76,18 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task TryServeFromCacheAsync_VaryByRuleFound_CachedResponseNotFound_Fails()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store, keyProvider: new TestResponseCacheKeyProvider("BaseKey", "VaryKey"));
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider("BaseKey", "VaryKey"));
var context = TestUtils.CreateTestContext();
await store.SetAsync(
await cache.SetAsync(
"BaseKey",
new CachedVaryByRules(),
TimeSpan.Zero);
Assert.False(await middleware.TryServeFromCacheAsync(context));
Assert.Equal(2, store.GetCount);
Assert.Equal(2, cache.GetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.NoResponseServed);
@ -96,16 +96,16 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task TryServeFromCacheAsync_VaryByRuleFound_CachedResponseFound_Succeeds()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store, keyProvider: new TestResponseCacheKeyProvider("BaseKey", new[] { "VaryKey", "VaryKey2" }));
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider("BaseKey", new[] { "VaryKey", "VaryKey2" }));
var context = TestUtils.CreateTestContext();
await store.SetAsync(
await cache.SetAsync(
"BaseKey",
new CachedVaryByRules(),
TimeSpan.Zero);
await store.SetAsync(
await cache.SetAsync(
"BaseKeyVaryKey2",
new CachedResponse()
{
@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
TimeSpan.Zero);
Assert.True(await middleware.TryServeFromCacheAsync(context));
Assert.Equal(3, store.GetCount);
Assert.Equal(3, cache.GetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.CachedResponseServed);
@ -123,13 +123,13 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task TryServeFromCacheAsync_CachedResponseFound_Serves304IfPossible()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store, keyProvider: new TestResponseCacheKeyProvider("BaseKey"));
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider("BaseKey"));
var context = TestUtils.CreateTestContext();
context.HttpContext.Request.Headers[HeaderNames.IfNoneMatch] = "*";
await store.SetAsync(
await cache.SetAsync(
"BaseKey",
new CachedResponse()
{
@ -138,7 +138,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
TimeSpan.Zero);
Assert.True(await middleware.TryServeFromCacheAsync(context));
Assert.Equal(1, store.GetCount);
Assert.Equal(1, cache.GetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.NotModifiedServed);
@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var context = TestUtils.CreateTestContext(sink);
context.CachedResponseHeaders = new ResponseHeaders(new HeaderDictionary());
Assert.False(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.False(ResponseCachingMiddleware.ContentIsNotModified(context));
Assert.Empty(sink.Writes);
}
@ -167,17 +167,17 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
// Verify modifications in the past succeeds
context.CachedResponseHeaders.Date = utcNow - TimeSpan.FromSeconds(10);
Assert.True(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.True(ResponseCachingMiddleware.ContentIsNotModified(context));
Assert.Equal(1, sink.Writes.Count);
// Verify modifications at present succeeds
context.CachedResponseHeaders.Date = utcNow;
Assert.True(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.True(ResponseCachingMiddleware.ContentIsNotModified(context));
Assert.Equal(2, sink.Writes.Count);
// Verify modifications in the future fails
context.CachedResponseHeaders.Date = utcNow + TimeSpan.FromSeconds(10);
Assert.False(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.False(ResponseCachingMiddleware.ContentIsNotModified(context));
// Verify logging
TestUtils.AssertLoggedMessages(
@ -199,19 +199,19 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
// Verify modifications in the past succeeds
context.CachedResponseHeaders.Date = utcNow + TimeSpan.FromSeconds(10);
context.CachedResponseHeaders.LastModified = utcNow - TimeSpan.FromSeconds(10);
Assert.True(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.True(ResponseCachingMiddleware.ContentIsNotModified(context));
Assert.Equal(1, sink.Writes.Count);
// Verify modifications at present
context.CachedResponseHeaders.Date = utcNow + TimeSpan.FromSeconds(10);
context.CachedResponseHeaders.LastModified = utcNow;
Assert.True(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.True(ResponseCachingMiddleware.ContentIsNotModified(context));
Assert.Equal(2, sink.Writes.Count);
// Verify modifications in the future fails
context.CachedResponseHeaders.Date = utcNow - TimeSpan.FromSeconds(10);
context.CachedResponseHeaders.LastModified = utcNow + TimeSpan.FromSeconds(10);
Assert.False(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.False(ResponseCachingMiddleware.ContentIsNotModified(context));
// Verify logging
TestUtils.AssertLoggedMessages(
@ -233,7 +233,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.CachedResponseHeaders.LastModified = utcNow + TimeSpan.FromSeconds(10);
context.TypedRequestHeaders.IfNoneMatch = new List<EntityTagHeaderValue>(new[] { EntityTagHeaderValue.Any });
Assert.True(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.True(ResponseCachingMiddleware.ContentIsNotModified(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.NotModifiedIfNoneMatchStar);
@ -252,7 +252,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.CachedResponseHeaders.LastModified = utcNow - TimeSpan.FromSeconds(10);
context.TypedRequestHeaders.IfNoneMatch = new List<EntityTagHeaderValue>(new[] { new EntityTagHeaderValue("\"E1\"") });
Assert.False(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.False(ResponseCachingMiddleware.ContentIsNotModified(context));
Assert.Empty(sink.Writes);
}
@ -265,7 +265,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedRequestHeaders.IfNoneMatch = new List<EntityTagHeaderValue>(new[] { new EntityTagHeaderValue("\"E1\"") });
Assert.False(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.False(ResponseCachingMiddleware.ContentIsNotModified(context));
Assert.Empty(sink.Writes);
}
@ -296,7 +296,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedRequestHeaders.IfNoneMatch = new List<EntityTagHeaderValue>(new[] { requestETag });
Assert.True(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.True(ResponseCachingMiddleware.ContentIsNotModified(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.NotModifiedIfNoneMatchMatched);
@ -314,7 +314,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedRequestHeaders.IfNoneMatch = new List<EntityTagHeaderValue>(new[] { new EntityTagHeaderValue("\"E1\"") });
Assert.False(ResponseCacheMiddleware.ContentIsNotModified(context));
Assert.False(ResponseCachingMiddleware.ContentIsNotModified(context));
Assert.Empty(sink.Writes);
}
@ -322,7 +322,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
public async Task FinalizeCacheHeaders_DoNotUpdateShouldCacheResponse_IfResponseIsNotCacheable()
{
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, policyProvider: new ResponseCachePolicyProvider());
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, policyProvider: new ResponseCachingPolicyProvider());
var context = TestUtils.CreateTestContext();
Assert.False(context.ShouldCacheResponse);
@ -338,7 +338,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
public async Task FinalizeCacheHeaders_UpdateShouldCacheResponse_IfResponseIsCacheable()
{
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, policyProvider: new ResponseCachePolicyProvider());
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, policyProvider: new ResponseCachingPolicyProvider());
var context = TestUtils.CreateTestContext();
context.TypedResponseHeaders.CacheControl = new CacheControlHeaderValue()
{
@ -425,13 +425,13 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task FinalizeCacheHeaders_UpdateCachedVaryByRules_IfNotEquivalentToPrevious()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store);
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache);
var context = TestUtils.CreateTestContext();
context.HttpContext.Response.Headers[HeaderNames.Vary] = new StringValues(new[] { "headerA", "HEADERB", "HEADERc" });
context.HttpContext.Features.Set<IResponseCacheFeature>(new ResponseCacheFeature()
context.HttpContext.Features.Set<IResponseCachingFeature>(new ResponseCachingFeature()
{
VaryByQueryKeys = new StringValues(new[] { "queryB", "QUERYA" })
});
@ -445,7 +445,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
await middleware.TryServeFromCacheAsync(context);
await middleware.FinalizeCacheHeadersAsync(context);
Assert.Equal(1, store.SetCount);
Assert.Equal(1, cache.SetCount);
Assert.NotSame(cachedVaryByRules, context.CachedVaryByRules);
TestUtils.AssertLoggedMessages(
sink.Writes,
@ -456,13 +456,13 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task FinalizeCacheHeaders_UpdateCachedVaryByRules_IfEquivalentToPrevious()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store);
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache);
var context = TestUtils.CreateTestContext();
context.HttpContext.Response.Headers[HeaderNames.Vary] = new StringValues(new[] { "headerA", "HEADERB" });
context.HttpContext.Features.Set<IResponseCacheFeature>(new ResponseCacheFeature()
context.HttpContext.Features.Set<IResponseCachingFeature>(new ResponseCachingFeature()
{
VaryByQueryKeys = new StringValues(new[] { "queryB", "QUERYA" })
});
@ -478,7 +478,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
await middleware.FinalizeCacheHeadersAsync(context);
// An update to the cache is always made but the entry should be the same
Assert.Equal(1, store.SetCount);
Assert.Equal(1, cache.SetCount);
Assert.Same(cachedVaryByRules, context.CachedVaryByRules);
TestUtils.AssertLoggedMessages(
sink.Writes,
@ -508,13 +508,13 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[MemberData(nameof(NullOrEmptyVaryRules))]
public async Task FinalizeCacheHeaders_UpdateCachedVaryByRules_NullOrEmptyRules(StringValues vary)
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store);
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache);
var context = TestUtils.CreateTestContext();
context.HttpContext.Response.Headers[HeaderNames.Vary] = vary;
context.HttpContext.Features.Set<IResponseCacheFeature>(new ResponseCacheFeature()
context.HttpContext.Features.Set<IResponseCachingFeature>(new ResponseCachingFeature()
{
VaryByQueryKeys = vary
});
@ -523,7 +523,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
await middleware.FinalizeCacheHeadersAsync(context);
// Vary rules should not be updated
Assert.Equal(0, store.SetCount);
Assert.Equal(0, cache.SetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.NoResponseServed);
@ -600,9 +600,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task FinalizeCacheBody_Cache_IfContentLengthMatches()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store);
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache);
var context = TestUtils.CreateTestContext();
middleware.ShimResponseStream(context);
@ -616,7 +616,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
await middleware.FinalizeCacheBodyAsync(context);
Assert.Equal(1, store.SetCount);
Assert.Equal(1, cache.SetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseCached);
@ -625,9 +625,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task FinalizeCacheBody_DoNotCache_IfContentLengthMismatches()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store);
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache);
var context = TestUtils.CreateTestContext();
middleware.ShimResponseStream(context);
@ -641,7 +641,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
await middleware.FinalizeCacheBodyAsync(context);
Assert.Equal(0, store.SetCount);
Assert.Equal(0, cache.SetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseContentLengthMismatchNotCached);
@ -650,9 +650,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task FinalizeCacheBody_Cache_IfContentLengthAbsent()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store);
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache);
var context = TestUtils.CreateTestContext();
middleware.ShimResponseStream(context);
@ -665,7 +665,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
await middleware.FinalizeCacheBodyAsync(context);
Assert.Equal(1, store.SetCount);
Assert.Equal(1, cache.SetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseCached);
@ -674,9 +674,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task FinalizeCacheBody_DoNotCache_IfShouldCacheResponseFalse()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store);
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache);
var context = TestUtils.CreateTestContext();
middleware.ShimResponseStream(context);
@ -686,7 +686,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
await middleware.FinalizeCacheBodyAsync(context);
Assert.Equal(0, store.SetCount);
Assert.Equal(0, cache.SetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseNotCached);
@ -695,20 +695,20 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async Task FinalizeCacheBody_DoNotCache_IfBufferingDisabled()
{
var store = new TestResponseCacheStore();
var cache = new TestResponseCache();
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, store: store);
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache);
var context = TestUtils.CreateTestContext();
middleware.ShimResponseStream(context);
await context.HttpContext.Response.WriteAsync(new string('0', 10));
context.ShouldCacheResponse = true;
context.ResponseCacheStream.DisableBuffering();
context.ResponseCachingStream.DisableBuffering();
await middleware.FinalizeCacheBodyAsync(context);
Assert.Equal(0, store.SetCount);
Assert.Equal(0, cache.SetCount);
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseNotCached);
@ -733,7 +733,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var uppercaseStrings = new StringValues(new[] { "STRINGA", "STRINGB" });
var lowercaseStrings = new StringValues(new[] { "stringA", "stringB" });
var normalizedStrings = ResponseCacheMiddleware.GetOrderCasingNormalizedStringValues(lowercaseStrings);
var normalizedStrings = ResponseCachingMiddleware.GetOrderCasingNormalizedStringValues(lowercaseStrings);
Assert.Equal(uppercaseStrings, normalizedStrings);
}
@ -744,7 +744,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var orderedStrings = new StringValues(new[] { "STRINGA", "STRINGB" });
var reverseOrderStrings = new StringValues(new[] { "STRINGB", "STRINGA" });
var normalizedStrings = ResponseCacheMiddleware.GetOrderCasingNormalizedStringValues(reverseOrderStrings);
var normalizedStrings = ResponseCachingMiddleware.GetOrderCasingNormalizedStringValues(reverseOrderStrings);
Assert.Equal(orderedStrings, normalizedStrings);
}
@ -754,7 +754,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
{
var originalStrings = new StringValues(new[] { "STRINGA, STRINGB" });
var normalizedStrings = ResponseCacheMiddleware.GetOrderCasingNormalizedStringValues(originalStrings);
var normalizedStrings = ResponseCachingMiddleware.GetOrderCasingNormalizedStringValues(originalStrings);
Assert.Equal(originalStrings, normalizedStrings);
}

View File

@ -11,7 +11,7 @@ using Xunit;
namespace Microsoft.AspNetCore.ResponseCaching.Tests
{
public class ResponseCachePolicyProviderTests
public class ResponseCachingPolicyProviderTests
{
public static TheoryData<string> CacheableMethods
{
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = method;
Assert.True(new ResponseCachePolicyProvider().IsRequestCacheable(context));
Assert.True(new ResponseCachingPolicyProvider().IsRequestCacheable(context));
Assert.Empty(sink.Writes);
}
public static TheoryData<string> NonCacheableMethods
@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = method;
Assert.False(new ResponseCachePolicyProvider().IsRequestCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsRequestCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.RequestMethodNotCacheable);
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.HttpContext.Request.Method = HttpMethods.Get;
context.HttpContext.Request.Headers[HeaderNames.Authorization] = "Basic plaintextUN:plaintextPW";
Assert.False(new ResponseCachePolicyProvider().IsRequestCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsRequestCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.RequestWithAuthorizationNotCacheable);
@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
NoCache = true
};
Assert.False(new ResponseCachePolicyProvider().IsRequestCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsRequestCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.RequestWithNoCacheNotCacheable);
@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
NoStore = true
};
Assert.True(new ResponseCachePolicyProvider().IsRequestCacheable(context));
Assert.True(new ResponseCachingPolicyProvider().IsRequestCacheable(context));
Assert.Empty(sink.Writes);
}
@ -122,7 +122,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.HttpContext.Request.Method = HttpMethods.Get;
context.HttpContext.Request.Headers[HeaderNames.Pragma] = "no-cache";
Assert.False(new ResponseCachePolicyProvider().IsRequestCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsRequestCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.RequestWithPragmaNoCacheNotCacheable);
@ -137,7 +137,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.HttpContext.Request.Headers[HeaderNames.Pragma] = "no-cache";
context.HttpContext.Request.Headers[HeaderNames.CacheControl] = "max-age=10";
Assert.True(new ResponseCachePolicyProvider().IsRequestCacheable(context));
Assert.True(new ResponseCachingPolicyProvider().IsRequestCacheable(context));
Assert.Empty(sink.Writes);
}
@ -147,7 +147,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithoutPublicNotCacheable);
@ -163,7 +163,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Public = true
};
Assert.True(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
@ -178,7 +178,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
NoCache = true
};
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithNoCacheNotCacheable);
@ -198,7 +198,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Public = true
};
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithNoStoreNotCacheable);
@ -215,7 +215,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
NoStore = true
};
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithNoStoreNotCacheable);
@ -232,7 +232,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
context.HttpContext.Response.Headers[HeaderNames.SetCookie] = "cookieName=cookieValue";
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithSetCookieNotCacheable);
@ -249,7 +249,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
context.HttpContext.Response.Headers[HeaderNames.Vary] = "*";
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithVaryStarNotCacheable);
@ -266,7 +266,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Private = true
};
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithPrivateNotCacheable);
@ -284,7 +284,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Public = true
};
Assert.True(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
@ -340,7 +340,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Public = true
};
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithUnsuccessfulStatusCodeNotCacheable);
@ -361,7 +361,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedResponseHeaders.Date = utcNow;
context.ResponseTime = DateTimeOffset.MaxValue;
Assert.True(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
@ -381,7 +381,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedResponseHeaders.Date = utcNow;
context.ResponseTime = utcNow;
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationExpiresExceeded);
@ -403,7 +403,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedResponseHeaders.Date = utcNow;
context.ResponseTime = utcNow + TimeSpan.FromSeconds(9);
Assert.True(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
@ -423,7 +423,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedResponseHeaders.Date = utcNow;
context.ResponseTime = utcNow + TimeSpan.FromSeconds(10);
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxAgeExceeded);
@ -445,7 +445,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedResponseHeaders.Date = utcNow;
context.ResponseTime = utcNow + TimeSpan.FromSeconds(11);
Assert.True(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
@ -465,7 +465,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.TypedResponseHeaders.Date = utcNow;
context.ResponseTime = utcNow + TimeSpan.FromSeconds(5);
Assert.False(new ResponseCachePolicyProvider().IsResponseCacheable(context));
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationSharedMaxAgeExceeded);
@ -481,7 +481,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
context.CachedEntryAge = TimeSpan.MaxValue;
context.CachedResponseHeaders = new ResponseHeaders(new HeaderDictionary());
Assert.True(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
Assert.Empty(sink.Writes);
}
@ -501,7 +501,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
};
Assert.True(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
Assert.Empty(sink.Writes);
}
@ -522,7 +522,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Expires = utcNow
};
Assert.False(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationExpiresExceeded);
@ -546,7 +546,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Expires = utcNow
};
Assert.True(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
Assert.Empty(sink.Writes);
}
@ -568,7 +568,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Expires = utcNow
};
Assert.False(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxAgeExceeded);
@ -593,7 +593,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Expires = utcNow
};
Assert.True(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
Assert.Empty(sink.Writes);
}
@ -616,7 +616,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Expires = utcNow
};
Assert.False(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationSharedMaxAgeExceeded);
@ -641,7 +641,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
context.CachedEntryAge = TimeSpan.FromSeconds(3);
Assert.False(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMinFreshAdded,
@ -666,7 +666,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
context.CachedEntryAge = TimeSpan.FromSeconds(5);
Assert.False(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxAgeExceeded);
@ -692,7 +692,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
context.CachedEntryAge = TimeSpan.FromSeconds(6);
Assert.True(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxStaleSatisfied);
@ -718,7 +718,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
context.CachedEntryAge = TimeSpan.FromSeconds(6);
Assert.False(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxAgeExceeded);
@ -745,7 +745,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
context.CachedEntryAge = TimeSpan.FromSeconds(6);
Assert.False(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMustRevalidate);

View File

@ -14,12 +14,12 @@ using Xunit;
namespace Microsoft.AspNetCore.ResponseCaching.Tests
{
public class ResponseCacheTests
public class ResponseCachingTests
{
[Fact]
public async void ServesCachedContent_IfAvailable()
{
var builders = TestUtils.CreateBuildersWithResponseCache();
var builders = TestUtils.CreateBuildersWithResponseCaching();
foreach (var builder in builders)
{
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfNotAvailable()
{
var builders = TestUtils.CreateBuildersWithResponseCache();
var builders = TestUtils.CreateBuildersWithResponseCaching();
foreach (var builder in builders)
{
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("/different");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfVaryHeader_Matches()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Response.Headers[HeaderNames.Vary] = HeaderNames.From;
await TestUtils.TestRequestDelegate(context);
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfVaryHeader_Mismatches()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Response.Headers[HeaderNames.Vary] = HeaderNames.From;
await TestUtils.TestRequestDelegate(context);
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
client.DefaultRequestHeaders.From = "user2@example.com";
var subsequentResponse = await client.GetAsync("");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -102,9 +102,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfVaryQueryKeys_Matches()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Features.Get<IResponseCacheFeature>().VaryByQueryKeys = "query";
context.Features.Get<IResponseCachingFeature>().VaryByQueryKeys = new[] { "query" };
await TestUtils.TestRequestDelegate(context);
});
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("?query=value");
var subsequentResponse = await client.GetAsync("?query=value");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -124,9 +124,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfVaryQueryKeysExplicit_Matches_QueryKeyCaseInsensitive()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Features.Get<IResponseCacheFeature>().VaryByQueryKeys = new[] { "QueryA", "queryb" };
context.Features.Get<IResponseCachingFeature>().VaryByQueryKeys = new[] { "QueryA", "queryb" };
await TestUtils.TestRequestDelegate(context);
});
@ -138,7 +138,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("?querya=valuea&queryb=valueb");
var subsequentResponse = await client.GetAsync("?QueryA=valuea&QueryB=valueb");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -146,9 +146,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfVaryQueryKeyStar_Matches_QueryKeyCaseInsensitive()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Features.Get<IResponseCacheFeature>().VaryByQueryKeys = new[] { "*" };
context.Features.Get<IResponseCachingFeature>().VaryByQueryKeys = new[] { "*" };
await TestUtils.TestRequestDelegate(context);
});
@ -160,7 +160,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("?querya=valuea&queryb=valueb");
var subsequentResponse = await client.GetAsync("?QueryA=valuea&QueryB=valueb");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -168,9 +168,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfVaryQueryKeyExplicit_Matches_OrderInsensitive()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Features.Get<IResponseCacheFeature>().VaryByQueryKeys = new[] { "QueryB", "QueryA" };
context.Features.Get<IResponseCachingFeature>().VaryByQueryKeys = new[] { "QueryB", "QueryA" };
await TestUtils.TestRequestDelegate(context);
});
@ -182,7 +182,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("?QueryA=ValueA&QueryB=ValueB");
var subsequentResponse = await client.GetAsync("?QueryB=ValueB&QueryA=ValueA");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -190,9 +190,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfVaryQueryKeyStar_Matches_OrderInsensitive()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Features.Get<IResponseCacheFeature>().VaryByQueryKeys = new[] { "*" };
context.Features.Get<IResponseCachingFeature>().VaryByQueryKeys = new[] { "*" };
await TestUtils.TestRequestDelegate(context);
});
@ -204,7 +204,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("?QueryA=ValueA&QueryB=ValueB");
var subsequentResponse = await client.GetAsync("?QueryB=ValueB&QueryA=ValueA");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -212,9 +212,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfVaryQueryKey_Mismatches()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Features.Get<IResponseCacheFeature>().VaryByQueryKeys = "query";
context.Features.Get<IResponseCachingFeature>().VaryByQueryKeys = new[] { "query" };
await TestUtils.TestRequestDelegate(context);
});
@ -226,7 +226,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("?query=value");
var subsequentResponse = await client.GetAsync("?query=value2");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -234,9 +234,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfVaryQueryKeyExplicit_Mismatch_QueryKeyCaseSensitive()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Features.Get<IResponseCacheFeature>().VaryByQueryKeys = new[] { "QueryA", "QueryB" };
context.Features.Get<IResponseCachingFeature>().VaryByQueryKeys = new[] { "QueryA", "QueryB" };
await TestUtils.TestRequestDelegate(context);
});
@ -248,7 +248,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("?querya=valuea&queryb=valueb");
var subsequentResponse = await client.GetAsync("?querya=ValueA&queryb=ValueB");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -256,9 +256,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfVaryQueryKeyStar_Mismatch_QueryKeyValueCaseSensitive()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Features.Get<IResponseCacheFeature>().VaryByQueryKeys = new[] { "*" };
context.Features.Get<IResponseCachingFeature>().VaryByQueryKeys = new[] { "*" };
await TestUtils.TestRequestDelegate(context);
});
@ -270,7 +270,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("?querya=valuea&queryb=valueb");
var subsequentResponse = await client.GetAsync("?querya=ValueA&queryb=ValueB");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -278,7 +278,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfRequestRequirements_NotMet()
{
var builders = TestUtils.CreateBuildersWithResponseCache();
var builders = TestUtils.CreateBuildersWithResponseCaching();
foreach (var builder in builders)
{
@ -292,7 +292,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
var subsequentResponse = await client.GetAsync("");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -300,7 +300,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void Serves504_IfOnlyIfCachedHeader_IsSpecified()
{
var builders = TestUtils.CreateBuildersWithResponseCache();
var builders = TestUtils.CreateBuildersWithResponseCaching();
foreach (var builder in builders)
{
@ -323,7 +323,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfSetCookie_IsSpecified()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
var headers = context.Response.Headers[HeaderNames.SetCookie] = "cookieName=cookieValue";
await TestUtils.TestRequestDelegate(context);
@ -337,7 +337,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -345,7 +345,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfIHttpSendFileFeature_NotUsed()
{
var builders = TestUtils.CreateBuildersWithResponseCache(app =>
var builders = TestUtils.CreateBuildersWithResponseCaching(app =>
{
app.Use(async (context, next) =>
{
@ -362,7 +362,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -370,7 +370,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfIHttpSendFileFeature_Used()
{
var builders = TestUtils.CreateBuildersWithResponseCache(
var builders = TestUtils.CreateBuildersWithResponseCaching(
app =>
{
app.Use(async (context, next) =>
@ -393,7 +393,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -401,7 +401,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfSubsequentRequest_ContainsNoStore()
{
var builders = TestUtils.CreateBuildersWithResponseCache();
var builders = TestUtils.CreateBuildersWithResponseCaching();
foreach (var builder in builders)
{
@ -415,7 +415,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
};
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -423,7 +423,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfInitialRequestContains_NoStore()
{
var builders = TestUtils.CreateBuildersWithResponseCache();
var builders = TestUtils.CreateBuildersWithResponseCaching();
foreach (var builder in builders)
{
@ -437,7 +437,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -445,7 +445,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void Serves304_IfIfModifiedSince_Satisfied()
{
var builders = TestUtils.CreateBuildersWithResponseCache();
var builders = TestUtils.CreateBuildersWithResponseCaching();
foreach (var builder in builders)
{
@ -465,7 +465,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfIfModifiedSince_NotSatisfied()
{
var builders = TestUtils.CreateBuildersWithResponseCache();
var builders = TestUtils.CreateBuildersWithResponseCaching();
foreach (var builder in builders)
{
@ -476,7 +476,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
client.DefaultRequestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue;
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -484,7 +484,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void Serves304_IfIfNoneMatch_Satisfied()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
var headers = context.Response.GetTypedHeaders().ETag = new EntityTagHeaderValue("\"E1\"");
await TestUtils.TestRequestDelegate(context);
@ -508,7 +508,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfIfNoneMatch_NotSatisfied()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
var headers = context.Response.GetTypedHeaders().ETag = new EntityTagHeaderValue("\"E1\"");
await TestUtils.TestRequestDelegate(context);
@ -523,7 +523,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
client.DefaultRequestHeaders.IfNoneMatch.Add(new System.Net.Http.Headers.EntityTagHeaderValue("\"E2\""));
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -531,7 +531,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfBodySize_IsCacheable()
{
var builders = TestUtils.CreateBuildersWithResponseCache(options: new ResponseCacheOptions()
var builders = TestUtils.CreateBuildersWithResponseCaching(options: new ResponseCachingOptions()
{
MaximumBodySize = 100
});
@ -544,7 +544,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -552,7 +552,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfBodySize_IsNotCacheable()
{
var builders = TestUtils.CreateBuildersWithResponseCache(options: new ResponseCacheOptions()
var builders = TestUtils.CreateBuildersWithResponseCaching(options: new ResponseCachingOptions()
{
MaximumBodySize = 1
});
@ -565,7 +565,28 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
var initialResponse = await client.GetAsync("");
var subsequentResponse = await client.GetAsync("/different");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
[Fact]
public async void ServesFreshContent_CaseSensitivePaths_IsNotCacheable()
{
var builders = TestUtils.CreateBuildersWithResponseCaching(options: new ResponseCachingOptions()
{
UseCaseSensitivePaths = true
});
foreach (var builder in builders)
{
using (var server = new TestServer(builder))
{
var client = server.CreateClient();
var initialResponse = await client.GetAsync("/path");
var subsequentResponse = await client.GetAsync("/Path");
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -573,7 +594,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_WithoutReplacingCachedVaryBy_OnCacheMiss()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Response.Headers[HeaderNames.Vary] = HeaderNames.From;
await TestUtils.TestRequestDelegate(context);
@ -591,7 +612,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
client.DefaultRequestHeaders.From = "user@example.com";
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -599,7 +620,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesFreshContent_IfCachedVaryByUpdated_OnCacheMiss()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Response.Headers[HeaderNames.Vary] = context.Request.Headers[HeaderNames.Pragma];
await TestUtils.TestRequestDelegate(context);
@ -626,7 +647,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
client.DefaultRequestHeaders.MaxForwards = 1;
var subsequentResponse = await client.GetAsync("");
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
await AssertFreshResponseAsync(initialResponse, subsequentResponse);
}
}
}
@ -634,7 +655,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
[Fact]
public async void ServesCachedContent_IfCachedVaryByNotUpdated_OnCacheMiss()
{
var builders = TestUtils.CreateBuildersWithResponseCache(requestDelegate: async (context) =>
var builders = TestUtils.CreateBuildersWithResponseCaching(requestDelegate: async (context) =>
{
context.Response.Headers[HeaderNames.Vary] = context.Request.Headers[HeaderNames.Pragma];
await TestUtils.TestRequestDelegate(context);
@ -661,12 +682,12 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
client.DefaultRequestHeaders.MaxForwards = 1;
var subsequentResponse = await client.GetAsync("");
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
await AssertCachedResponseAsync(initialResponse, subsequentResponse);
}
}
}
private static async Task AssertResponseCachedAsync(HttpResponseMessage initialResponse, HttpResponseMessage subsequentResponse)
private static async Task AssertCachedResponseAsync(HttpResponseMessage initialResponse, HttpResponseMessage subsequentResponse)
{
initialResponse.EnsureSuccessStatusCode();
subsequentResponse.EnsureSuccessStatusCode();
@ -679,7 +700,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
Assert.Equal(await initialResponse.Content.ReadAsStringAsync(), await subsequentResponse.Content.ReadAsStringAsync());
}
private static async Task AssertResponseNotCachedAsync(HttpResponseMessage initialResponse, HttpResponseMessage subsequentResponse)
private static async Task AssertFreshResponseAsync(HttpResponseMessage initialResponse, HttpResponseMessage subsequentResponse)
{
initialResponse.EnsureSuccessStatusCode();
subsequentResponse.EnsureSuccessStatusCode();

View File

@ -44,92 +44,96 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
await context.Response.WriteAsync(uniqueId);
};
internal static IResponseCacheKeyProvider CreateTestKeyProvider()
internal static IResponseCachingKeyProvider CreateTestKeyProvider()
{
return CreateTestKeyProvider(new ResponseCacheOptions());
return CreateTestKeyProvider(new ResponseCachingOptions());
}
internal static IResponseCacheKeyProvider CreateTestKeyProvider(ResponseCacheOptions options)
internal static IResponseCachingKeyProvider CreateTestKeyProvider(ResponseCachingOptions options)
{
return new ResponseCacheKeyProvider(new DefaultObjectPoolProvider(), Options.Create(options));
return new ResponseCachingKeyProvider(new DefaultObjectPoolProvider(), Options.Create(options));
}
internal static IEnumerable<IWebHostBuilder> CreateBuildersWithResponseCache(
internal static IEnumerable<IWebHostBuilder> CreateBuildersWithResponseCaching(
Action<IApplicationBuilder> configureDelegate = null,
ResponseCacheOptions options = null,
ResponseCachingOptions options = null,
RequestDelegate requestDelegate = null)
{
if (configureDelegate == null)
{
configureDelegate = app => { };
}
if (options == null)
{
options = new ResponseCacheOptions();
}
if (requestDelegate == null)
{
requestDelegate = TestRequestDelegate;
}
// Test with MemoryResponseCacheStore
// Test with in memory ResponseCache
yield return new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddMemoryResponseCacheStore();
services.AddResponseCaching(responseCachingOptions =>
{
if (options != null)
{
responseCachingOptions.MaximumBodySize = options.MaximumBodySize;
responseCachingOptions.UseCaseSensitivePaths = options.UseCaseSensitivePaths;
responseCachingOptions.SystemClock = options.SystemClock;
}
});
})
.Configure(app =>
{
configureDelegate(app);
app.UseResponseCache(options);
app.UseResponseCaching();
app.Run(requestDelegate);
});
}
internal static ResponseCacheMiddleware CreateTestMiddleware(
IResponseCacheStore store = null,
ResponseCacheOptions options = null,
internal static ResponseCachingMiddleware CreateTestMiddleware(
IResponseCache cache = null,
ResponseCachingOptions options = null,
TestSink testSink = null,
IResponseCacheKeyProvider keyProvider = null,
IResponseCachePolicyProvider policyProvider = null)
IResponseCachingKeyProvider keyProvider = null,
IResponseCachingPolicyProvider policyProvider = null)
{
if (store == null)
if (cache == null)
{
store = new TestResponseCacheStore();
cache = new TestResponseCache();
}
if (options == null)
{
options = new ResponseCacheOptions();
options = new ResponseCachingOptions();
}
if (keyProvider == null)
{
keyProvider = new ResponseCacheKeyProvider(new DefaultObjectPoolProvider(), Options.Create(options));
keyProvider = new ResponseCachingKeyProvider(new DefaultObjectPoolProvider(), Options.Create(options));
}
if (policyProvider == null)
{
policyProvider = new TestResponseCachePolicyProvider();
policyProvider = new TestResponseCachingPolicyProvider();
}
return new ResponseCacheMiddleware(
return new ResponseCachingMiddleware(
httpContext => TaskCache.CompletedTask,
Options.Create(options),
testSink == null ? (ILoggerFactory)NullLoggerFactory.Instance : new TestLoggerFactory(testSink, true),
policyProvider,
store,
cache,
keyProvider);
}
internal static ResponseCacheContext CreateTestContext()
internal static ResponseCachingContext CreateTestContext()
{
return new ResponseCacheContext(new DefaultHttpContext(), NullLogger.Instance)
return new ResponseCachingContext(new DefaultHttpContext(), NullLogger.Instance)
{
ResponseTime = DateTimeOffset.UtcNow
};
}
internal static ResponseCacheContext CreateTestContext(TestSink testSink)
internal static ResponseCachingContext CreateTestContext(TestSink testSink)
{
return new ResponseCacheContext(new DefaultHttpContext(), new TestLogger("ResponseCachingTests", testSink, true))
return new ResponseCachingContext(new DefaultHttpContext(), new TestLogger("ResponseCachingTests", testSink, true))
{
ResponseTime = DateTimeOffset.UtcNow
};
@ -208,21 +212,21 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
}
internal class TestResponseCachePolicyProvider : IResponseCachePolicyProvider
internal class TestResponseCachingPolicyProvider : IResponseCachingPolicyProvider
{
public bool IsCachedEntryFresh(ResponseCacheContext context) => true;
public bool IsCachedEntryFresh(ResponseCachingContext context) => true;
public bool IsRequestCacheable(ResponseCacheContext context) => true;
public bool IsRequestCacheable(ResponseCachingContext context) => true;
public bool IsResponseCacheable(ResponseCacheContext context) => true;
public bool IsResponseCacheable(ResponseCachingContext context) => true;
}
internal class TestResponseCacheKeyProvider : IResponseCacheKeyProvider
internal class TestResponseCachingKeyProvider : IResponseCachingKeyProvider
{
private readonly string _baseKey;
private readonly StringValues _varyKey;
public TestResponseCacheKeyProvider(string lookupBaseKey = null, StringValues? lookupVaryKey = null)
public TestResponseCachingKeyProvider(string lookupBaseKey = null, StringValues? lookupVaryKey = null)
{
_baseKey = lookupBaseKey;
if (lookupVaryKey.HasValue)
@ -231,7 +235,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
}
public IEnumerable<string> CreateLookupVaryByKeys(ResponseCacheContext context)
public IEnumerable<string> CreateLookupVaryByKeys(ResponseCachingContext context)
{
foreach (var varyKey in _varyKey)
{
@ -239,18 +243,18 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
}
}
public string CreateBaseKey(ResponseCacheContext context)
public string CreateBaseKey(ResponseCachingContext context)
{
return _baseKey;
}
public string CreateStorageVaryByKey(ResponseCacheContext context)
public string CreateStorageVaryByKey(ResponseCachingContext context)
{
throw new NotImplementedException();
}
}
internal class TestResponseCacheStore : IResponseCacheStore
internal class TestResponseCache : IResponseCache
{
private readonly IDictionary<string, IResponseCacheEntry> _storage = new Dictionary<string, IResponseCacheEntry>();
public int GetCount { get; private set; }