diff --git a/samples/ResponseCachingSample/Startup.cs b/samples/ResponseCachingSample/Startup.cs index 66708440a9..376443ef0b 100644 --- a/samples/ResponseCachingSample/Startup.cs +++ b/samples/ResponseCachingSample/Startup.cs @@ -15,7 +15,7 @@ namespace ResponseCachingSample { public void ConfigureServices(IServiceCollection services) { - services.AddDistributedResponseCacheStore(); + services.AddMemoryResponseCacheStore(); } public void Configure(IApplicationBuilder app) @@ -23,7 +23,6 @@ namespace ResponseCachingSample app.UseResponseCache(); app.Run(async (context) => { - // These settings should be configured by context.Response.Cache.* context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue() { Public = true, diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Extensions/ResponseCacheServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.ResponseCaching/Extensions/ResponseCacheServiceCollectionExtensions.cs index d85e45d3fc..b8020b56f9 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/Extensions/ResponseCacheServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Extensions/ResponseCacheServiceCollectionExtensions.cs @@ -18,29 +18,9 @@ namespace Microsoft.Extensions.DependencyInjection } services.AddMemoryCache(); - services.AddResponseCacheServices(); - services.TryAdd(ServiceDescriptor.Singleton()); - - return services; - } - - public static IServiceCollection AddDistributedResponseCacheStore(this IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.AddDistributedMemoryCache(); - services.AddResponseCacheServices(); - services.TryAdd(ServiceDescriptor.Singleton()); - - return services; - } - - private static IServiceCollection AddResponseCacheServices(this IServiceCollection services) - { services.TryAdd(ServiceDescriptor.Singleton()); + services.TryAdd(ServiceDescriptor.Singleton()); + services.TryAdd(ServiceDescriptor.Singleton()); return services; } diff --git a/src/Microsoft.AspNetCore.ResponseCaching/CacheEntry/CachedResponse.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/CacheEntry/CachedResponse.cs similarity index 90% rename from src/Microsoft.AspNetCore.ResponseCaching/CacheEntry/CachedResponse.cs rename to src/Microsoft.AspNetCore.ResponseCaching/Internal/CacheEntry/CachedResponse.cs index 1accf9a759..51083e40d2 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/CacheEntry/CachedResponse.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/CacheEntry/CachedResponse.cs @@ -5,7 +5,7 @@ using System; using System.IO; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching.Internal { public class CachedResponse : IResponseCacheEntry { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/CacheEntry/CachedVaryByRules.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/CacheEntry/CachedVaryByRules.cs similarity index 88% rename from src/Microsoft.AspNetCore.ResponseCaching/CacheEntry/CachedVaryByRules.cs rename to src/Microsoft.AspNetCore.ResponseCaching/Internal/CacheEntry/CachedVaryByRules.cs index e0e82bd60a..d183724628 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/CacheEntry/CachedVaryByRules.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/CacheEntry/CachedVaryByRules.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Primitives; -namespace Microsoft.AspNetCore.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching.Internal { public class CachedVaryByRules : IResponseCacheEntry { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Internal/DistributedResponseCacheStore.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/DistributedResponseCacheStore.cs deleted file mode 100644 index ab708fc81b..0000000000 --- a/src/Microsoft.AspNetCore.ResponseCaching/Internal/DistributedResponseCacheStore.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Distributed; - -namespace Microsoft.AspNetCore.ResponseCaching.Internal -{ - public class DistributedResponseCacheStore : IResponseCacheStore - { - private readonly IDistributedCache _cache; - - public DistributedResponseCacheStore(IDistributedCache cache) - { - if (cache == null) - { - throw new ArgumentNullException(nameof(cache)); - } - - _cache = cache; - } - - public async Task GetAsync(string key) - { - try - { - return ResponseCacheEntrySerializer.Deserialize(await _cache.GetAsync(key)); - } - catch - { - return null; - } - } - - public async Task SetAsync(string key, IResponseCacheEntry entry, TimeSpan validFor) - { - try - { - await _cache.SetAsync( - key, - ResponseCacheEntrySerializer.Serialize(entry), - new DistributedCacheEntryOptions() - { - AbsoluteExpirationRelativeToNow = validFor - }); - } - catch { } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Internal/FastGuid.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/FastGuid.cs index 075403f35c..76cac184ae 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/Internal/FastGuid.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/FastGuid.cs @@ -54,7 +54,6 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal private static unsafe string GenerateGuidString(FastGuid guid) { - // stackalloc to allocate array on stack rather than heap char* charBuffer = stackalloc char[13]; diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCacheEntry.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheEntry.cs similarity index 80% rename from src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCacheEntry.cs rename to src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheEntry.cs index d09fd4da48..a8227fe243 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCacheEntry.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheEntry.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching.Internal { public interface IResponseCacheEntry { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Internal/IResponseCacheKeyProvider.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheKeyProvider.cs similarity index 96% rename from src/Microsoft.AspNetCore.ResponseCaching/Internal/IResponseCacheKeyProvider.cs rename to src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheKeyProvider.cs index 199f1a837b..eb9d626824 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/Internal/IResponseCacheKeyProvider.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheKeyProvider.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; namespace Microsoft.AspNetCore.ResponseCaching.Internal { - internal interface IResponseCacheKeyProvider + public interface IResponseCacheKeyProvider { /// /// Create a base key for a response cache entry. diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCachePolicyProvider.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCachePolicyProvider.cs similarity index 96% rename from src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCachePolicyProvider.cs rename to src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCachePolicyProvider.cs index 91ab9c5e14..0560212018 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCachePolicyProvider.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCachePolicyProvider.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching.Internal { public interface IResponseCachePolicyProvider { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCacheStore.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheStore.cs similarity index 87% rename from src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCacheStore.cs rename to src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheStore.cs index 9a12b9b6df..2deaa41708 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/Interfaces/IResponseCacheStore.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/Interfaces/IResponseCacheStore.cs @@ -4,7 +4,7 @@ using System; using System.Threading.Tasks; -namespace Microsoft.AspNetCore.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching.Internal { public interface IResponseCacheStore { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/ResponseCacheContext.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheContext.cs similarity index 97% rename from src/Microsoft.AspNetCore.ResponseCaching/ResponseCacheContext.cs rename to src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheContext.cs index ac86b028ad..c11ff159f3 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/ResponseCacheContext.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheContext.cs @@ -6,10 +6,9 @@ using System.IO; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Headers; -using Microsoft.AspNetCore.ResponseCaching.Internal; using Microsoft.Net.Http.Headers; -namespace Microsoft.AspNetCore.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching.Internal { public class ResponseCacheContext { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheEntrySerializer.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheEntrySerializer.cs deleted file mode 100644 index 46c679d241..0000000000 --- a/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheEntrySerializer.cs +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Microsoft.AspNetCore.Http; - -namespace Microsoft.AspNetCore.ResponseCaching.Internal -{ - internal static class ResponseCacheEntrySerializer - { - private const int FormatVersion = 1; - - internal static IResponseCacheEntry Deserialize(byte[] serializedEntry) - { - if (serializedEntry == null) - { - return null; - } - - using (var memory = new MemoryStream(serializedEntry)) - { - using (var reader = new BinaryReader(memory)) - { - return Read(reader); - } - } - } - - internal static byte[] Serialize(IResponseCacheEntry entry) - { - using (var memory = new MemoryStream()) - { - using (var writer = new BinaryWriter(memory)) - { - Write(writer, entry); - writer.Flush(); - return memory.ToArray(); - } - } - } - - // Serialization Format - // Format version (int) - // Type (char: 'R' for CachedResponse, 'V' for CachedVaryByRules) - // Type-dependent data (see CachedResponse and CachedVaryByRules) - private static IResponseCacheEntry Read(BinaryReader reader) - { - if (reader == null) - { - throw new ArgumentNullException(nameof(reader)); - } - - if (reader.ReadInt32() != FormatVersion) - { - return null; - } - - var type = reader.ReadChar(); - - if (type == 'R') - { - return ReadCachedResponse(reader); - } - else if (type == 'V') - { - return ReadCachedVaryByRules(reader); - } - - // Unable to read as CachedResponse or CachedVaryByRules - return null; - } - - // Serialization Format - // Creation time - UtcTicks (long) - // Status code (int) - // Header count (int) - // Header(s) - // Key (string) - // ValueCount (int) - // Value(s) - // Value (string) - // BodyLength (int) - // Body (byte[]) - private static CachedResponse ReadCachedResponse(BinaryReader reader) - { - var created = new DateTimeOffset(reader.ReadInt64(), TimeSpan.Zero); - var statusCode = reader.ReadInt32(); - var headerCount = reader.ReadInt32(); - var headers = new HeaderDictionary(); - for (var index = 0; index < headerCount; index++) - { - var key = reader.ReadString(); - var headerValueCount = reader.ReadInt32(); - if (headerValueCount > 1) - { - var headerValues = new string[headerValueCount]; - for (var valueIndex = 0; valueIndex < headerValueCount; valueIndex++) - { - headerValues[valueIndex] = reader.ReadString(); - } - headers[key] = headerValues; - } - else if (headerValueCount == 1) - { - headers[key] = reader.ReadString(); - } - } - - var bodyLength = reader.ReadInt32(); - var bodyBytes = reader.ReadBytes(bodyLength); - - return new CachedResponse - { - Created = created, - StatusCode = statusCode, - Headers = headers, - Body = new MemoryStream(bodyBytes, writable: false) - }; - } - - // Serialization Format - // VaryKeyPrefix (string) - // Headers count - // Header(s) (comma separated string) - // QueryKey count - // QueryKey(s) (comma separated string) - private static CachedVaryByRules ReadCachedVaryByRules(BinaryReader reader) - { - var varyKeyPrefix = reader.ReadString(); - - var headerCount = reader.ReadInt32(); - var headers = new string[headerCount]; - for (var index = 0; index < headerCount; index++) - { - headers[index] = reader.ReadString(); - } - var queryKeysCount = reader.ReadInt32(); - var queryKeys = new string[queryKeysCount]; - for (var index = 0; index < queryKeysCount; index++) - { - queryKeys[index] = reader.ReadString(); - } - - return new CachedVaryByRules { VaryByKeyPrefix = varyKeyPrefix, Headers = headers, QueryKeys = queryKeys }; - } - - // See serialization format above - private static void Write(BinaryWriter writer, IResponseCacheEntry entry) - { - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } - - if (entry == null) - { - throw new ArgumentNullException(nameof(entry)); - } - - writer.Write(FormatVersion); - - if (entry is CachedResponse) - { - writer.Write('R'); - WriteCachedResponse(writer, (CachedResponse)entry); - } - else if (entry is CachedVaryByRules) - { - writer.Write('V'); - WriteCachedVaryByRules(writer, (CachedVaryByRules)entry); - } - else - { - throw new NotSupportedException($"Unrecognized entry type for {nameof(entry)}."); - } - } - - // See serialization format above - private static void WriteCachedResponse(BinaryWriter writer, CachedResponse entry) - { - writer.Write(entry.Created.UtcTicks); - writer.Write(entry.StatusCode); - writer.Write(entry.Headers.Count); - foreach (var header in entry.Headers) - { - writer.Write(header.Key); - writer.Write(header.Value.Count); - foreach (var headerValue in header.Value) - { - writer.Write(headerValue); - } - } - - if (entry.Body.CanSeek) - { - if (entry.Body.Length > int.MaxValue) - { - throw new NotSupportedException($"{nameof(entry.Body)} is too large to serialized."); - } - - var bodyLength = (int)entry.Body.Length; - var bodyBytes = new byte[bodyLength]; - var bytesRead = entry.Body.Read(bodyBytes, 0, bodyLength); - - if (bytesRead != bodyLength) - { - throw new InvalidOperationException($"Failed to fully read {nameof(entry.Body)}."); - } - - writer.Write(bodyLength); - writer.Write(bodyBytes); - } - else - { - var stream = new MemoryStream(); - entry.Body.CopyTo(stream); - - if (stream.Length > int.MaxValue) - { - throw new NotSupportedException($"{nameof(entry.Body)} is too large to serialized."); - } - - var bodyLength = (int)stream.Length; - writer.Write(bodyLength); - writer.Write(stream.ToArray()); - - } - } - - // See serialization format above - private static void WriteCachedVaryByRules(BinaryWriter writer, CachedVaryByRules varyByRules) - { - writer.Write(varyByRules.VaryByKeyPrefix); - - writer.Write(varyByRules.Headers.Count); - foreach (var header in varyByRules.Headers) - { - writer.Write(header); - } - - writer.Write(varyByRules.QueryKeys.Count); - foreach (var queryKey in varyByRules.QueryKeys) - { - writer.Write(queryKey); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheKeyProvider.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheKeyProvider.cs index b7df0decc0..ed586946d1 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheKeyProvider.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCacheKeyProvider.cs @@ -12,7 +12,7 @@ using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.ResponseCaching.Internal { - internal class ResponseCacheKeyProvider : IResponseCacheKeyProvider + public class ResponseCacheKeyProvider : IResponseCacheKeyProvider { // Use the record separator for delimiting components of the cache key to avoid possible collisions private static readonly char KeyDelimiter = '\x1e'; @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal private readonly ObjectPool _builderPool; private readonly ResponseCacheOptions _options; - internal ResponseCacheKeyProvider(ObjectPoolProvider poolProvider, IOptions options) + public ResponseCacheKeyProvider(ObjectPoolProvider poolProvider, IOptions options) { if (poolProvider == null) { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachePolicyProvider.cs b/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCachePolicyProvider.cs similarity index 99% rename from src/Microsoft.AspNetCore.ResponseCaching/ResponseCachePolicyProvider.cs rename to src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCachePolicyProvider.cs index 341c2e0d00..ab331ff311 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachePolicyProvider.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCachePolicyProvider.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; -namespace Microsoft.AspNetCore.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching.Internal { public class ResponseCachePolicyProvider : IResponseCachePolicyProvider { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/ResponseCacheMiddleware.cs b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCacheMiddleware.cs index c49ac77e0b..da7251d108 100644 --- a/src/Microsoft.AspNetCore.ResponseCaching/ResponseCacheMiddleware.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCacheMiddleware.cs @@ -30,20 +30,9 @@ namespace Microsoft.AspNetCore.ResponseCaching public ResponseCacheMiddleware( RequestDelegate next, - IResponseCacheStore store, IOptions options, IResponseCachePolicyProvider policyProvider, - ObjectPoolProvider poolProvider) - :this (next, store, options, policyProvider, new ResponseCacheKeyProvider(poolProvider, options)) - { - } - - // Internal for testing - internal ResponseCacheMiddleware( - RequestDelegate next, IResponseCacheStore store, - IOptions options, - IResponseCachePolicyProvider policyProvider, IResponseCacheKeyProvider keyProvider) { if (next == null) diff --git a/test/Microsoft.AspNetCore.ResponseCaching.Tests/CacheEntrySerializerTests.cs b/test/Microsoft.AspNetCore.ResponseCaching.Tests/CacheEntrySerializerTests.cs deleted file mode 100644 index 7664e437cb..0000000000 --- a/test/Microsoft.AspNetCore.ResponseCaching.Tests/CacheEntrySerializerTests.cs +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.ResponseCaching.Internal; -using Microsoft.Extensions.Primitives; -using Xunit; - -namespace Microsoft.AspNetCore.ResponseCaching.Tests -{ - public class CacheEntrySerializerTests - { - [Fact] - public void Serialize_NullObject_Throws() - { - Assert.Throws(() => ResponseCacheEntrySerializer.Serialize(null)); - } - - private class UnknownResponseCacheEntry : IResponseCacheEntry - { - } - - [Fact] - public void Serialize_UnknownObject_Throws() - { - Assert.Throws(() => ResponseCacheEntrySerializer.Serialize(new UnknownResponseCacheEntry())); - } - - [Fact] - public void Deserialize_NullObject_ReturnsNull() - { - Assert.Null(ResponseCacheEntrySerializer.Deserialize(null)); - } - - [Fact] - public void RoundTrip_CachedResponseWithBody_Succeeds() - { - var headers = new HeaderDictionary(); - headers["keyA"] = "valueA"; - headers["keyB"] = "valueB"; - var body = Encoding.ASCII.GetBytes("Hello world"); - var cachedResponse = new CachedResponse() - { - Created = DateTimeOffset.UtcNow, - StatusCode = StatusCodes.Status200OK, - Body = new SegmentReadStream(new List(new[] { body }), body.Length), - Headers = headers - }; - - AssertCachedResponseEqual(cachedResponse, (CachedResponse)ResponseCacheEntrySerializer.Deserialize(ResponseCacheEntrySerializer.Serialize(cachedResponse))); - } - - [Fact] - public void RoundTrip_CachedResponseWithMultivalueHeaders_Succeeds() - { - var headers = new HeaderDictionary(); - headers["keyA"] = new StringValues(new[] { "ValueA", "ValueB" }); - var body = Encoding.ASCII.GetBytes("Hello world"); - var cachedResponse = new CachedResponse() - { - Created = DateTimeOffset.UtcNow, - StatusCode = StatusCodes.Status200OK, - Body = new SegmentReadStream(new List(new[] { body }), body.Length), - Headers = headers - }; - - AssertCachedResponseEqual(cachedResponse, (CachedResponse)ResponseCacheEntrySerializer.Deserialize(ResponseCacheEntrySerializer.Serialize(cachedResponse))); - } - - [Fact] - public void RoundTrip_CachedResponseWithEmptyHeaders_Succeeds() - { - var headers = new HeaderDictionary(); - headers["keyA"] = StringValues.Empty; - var body = Encoding.ASCII.GetBytes("Hello world"); - var cachedResponse = new CachedResponse() - { - Created = DateTimeOffset.UtcNow, - StatusCode = StatusCodes.Status200OK, - Body = new SegmentReadStream(new List(new[] { body }), body.Length), - Headers = headers - }; - - AssertCachedResponseEqual(cachedResponse, (CachedResponse)ResponseCacheEntrySerializer.Deserialize(ResponseCacheEntrySerializer.Serialize(cachedResponse))); - } - - [Fact] - public void RoundTrip_CachedVaryByRule_EmptyRules_Succeeds() - { - var cachedVaryByRule = new CachedVaryByRules() - { - VaryByKeyPrefix = FastGuid.NewGuid().IdString - }; - - AssertCachedVaryByRuleEqual(cachedVaryByRule, (CachedVaryByRules)ResponseCacheEntrySerializer.Deserialize(ResponseCacheEntrySerializer.Serialize(cachedVaryByRule))); - } - - [Fact] - public void RoundTrip_CachedVaryByRule_HeadersOnly_Succeeds() - { - var headers = new[] { "headerA", "headerB" }; - var cachedVaryByRule = new CachedVaryByRules() - { - VaryByKeyPrefix = FastGuid.NewGuid().IdString, - Headers = headers - }; - - AssertCachedVaryByRuleEqual(cachedVaryByRule, (CachedVaryByRules)ResponseCacheEntrySerializer.Deserialize(ResponseCacheEntrySerializer.Serialize(cachedVaryByRule))); - } - - [Fact] - public void RoundTrip_CachedVaryByRule_QueryKeysOnly_Succeeds() - { - var queryKeys = new[] { "queryA", "queryB" }; - var cachedVaryByRule = new CachedVaryByRules() - { - VaryByKeyPrefix = FastGuid.NewGuid().IdString, - QueryKeys = queryKeys - }; - - AssertCachedVaryByRuleEqual(cachedVaryByRule, (CachedVaryByRules)ResponseCacheEntrySerializer.Deserialize(ResponseCacheEntrySerializer.Serialize(cachedVaryByRule))); - } - - [Fact] - public void RoundTrip_CachedVaryByRule_HeadersAndQueryKeys_Succeeds() - { - var headers = new[] { "headerA", "headerB" }; - var queryKeys = new[] { "queryA", "queryB" }; - var cachedVaryByRule = new CachedVaryByRules() - { - VaryByKeyPrefix = FastGuid.NewGuid().IdString, - Headers = headers, - QueryKeys = queryKeys - }; - - AssertCachedVaryByRuleEqual(cachedVaryByRule, (CachedVaryByRules)ResponseCacheEntrySerializer.Deserialize(ResponseCacheEntrySerializer.Serialize(cachedVaryByRule))); - } - - [Fact] - public void Deserialize_InvalidEntries_ReturnsNull() - { - var headers = new[] { "headerA", "headerB" }; - var cachedVaryByRule = new CachedVaryByRules() - { - VaryByKeyPrefix = FastGuid.NewGuid().IdString, - Headers = headers - }; - var serializedEntry = ResponseCacheEntrySerializer.Serialize(cachedVaryByRule); - Array.Reverse(serializedEntry); - - Assert.Null(ResponseCacheEntrySerializer.Deserialize(serializedEntry)); - } - - private static void AssertCachedResponseEqual(CachedResponse expected, CachedResponse actual) - { - Assert.NotNull(actual); - Assert.NotNull(expected); - Assert.Equal(expected.Created, actual.Created); - Assert.Equal(expected.StatusCode, actual.StatusCode); - Assert.Equal(expected.Headers.Count, actual.Headers.Count); - foreach (var expectedHeader in expected.Headers) - { - Assert.Equal(expectedHeader.Value, actual.Headers[expectedHeader.Key]); - } - - Assert.Equal(expected.Body.Length, actual.Body.Length); - var bodyLength = (int)expected.Body.Length; - var expectedBytes = new byte[bodyLength]; - var actualBytes = new byte[bodyLength]; - expected.Body.Position = 0; // Rewind - Assert.Equal(bodyLength, expected.Body.Read(expectedBytes, 0, bodyLength)); - Assert.Equal(bodyLength, actual.Body.Read(actualBytes, 0, bodyLength)); - Assert.True(expectedBytes.SequenceEqual(actualBytes)); - } - - private static void AssertCachedVaryByRuleEqual(CachedVaryByRules expected, CachedVaryByRules actual) - { - Assert.NotNull(actual); - Assert.NotNull(expected); - Assert.Equal(expected.VaryByKeyPrefix, actual.VaryByKeyPrefix); - Assert.Equal(expected.Headers, actual.Headers); - Assert.Equal(expected.QueryKeys, actual.QueryKeys); - } - } -} diff --git a/test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachePolicyProviderTests.cs b/test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachePolicyProviderTests.cs index 65bbf5434b..d9a914fda2 100644 --- a/test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachePolicyProviderTests.cs +++ b/test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachePolicyProviderTests.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Headers; +using Microsoft.AspNetCore.ResponseCaching.Internal; using Microsoft.Net.Http.Headers; using Xunit; diff --git a/test/Microsoft.AspNetCore.ResponseCaching.Tests/TestUtils.cs b/test/Microsoft.AspNetCore.ResponseCaching.Tests/TestUtils.cs index f6f0ed2db1..f21912ad77 100644 --- a/test/Microsoft.AspNetCore.ResponseCaching.Tests/TestUtils.cs +++ b/test/Microsoft.AspNetCore.ResponseCaching.Tests/TestUtils.cs @@ -81,19 +81,6 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests app.UseResponseCache(options); app.Run(requestDelegate); }); - - // Test with DistributedResponseCacheStore - yield return new WebHostBuilder() - .ConfigureServices(services => - { - services.AddDistributedResponseCacheStore(); - }) - .Configure(app => - { - configureDelegate(app); - app.UseResponseCache(options); - app.Run(requestDelegate); - }); } internal static ResponseCacheMiddleware CreateTestMiddleware( @@ -121,9 +108,9 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests return new ResponseCacheMiddleware( httpContext => TaskCache.CompletedTask, - store, Options.Create(options), policyProvider, + store, keyProvider); }