public async Task TryServeFromCacheAsync_CachedResponseFound_OverwritesExistingHeaders() { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider("BaseKey")); var context = TestUtils.CreateTestContext(); context.HttpContext.Response.Headers["MyHeader"] = "OldValue"; cache.Set( "BaseKey", new CachedResponse() { Headers = new HeaderDictionary() { { "MyHeader", "NewValue" } }, Body = new CachedResponseBody(new List <byte[]>(0), 0) }, TimeSpan.Zero); Assert.True(await middleware.TryServeFromCacheAsync(context)); Assert.Equal("NewValue", context.HttpContext.Response.Headers["MyHeader"]); Assert.Equal(1, cache.GetCount); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.CachedResponseServed); }
public async Task FinalizeCacheBody_Cache_IfContentLengthAbsent() { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache); var context = TestUtils.CreateTestContext(); context.ShouldCacheResponse = true; middleware.ShimResponseStream(context); await context.HttpContext.Response.WriteAsync(new string('0', 10)); context.CachedResponse = new CachedResponse() { Headers = new HeaderDictionary() }; context.BaseKey = "BaseKey"; context.CachedResponseValidFor = TimeSpan.FromSeconds(10); middleware.FinalizeCacheBody(context); Assert.Equal(1, cache.SetCount); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.ResponseCached); }
public async Task FinalizeCacheBody_DoNotCache_IfContentLengthMismatches(string method) { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache); var context = TestUtils.CreateTestContext(); context.ShouldCacheResponse = true; middleware.ShimResponseStream(context); context.HttpContext.Response.ContentLength = 9; context.HttpContext.Request.Method = method; await context.HttpContext.Response.WriteAsync(new string('0', 10)); context.CachedResponse = new CachedResponse(); context.BaseKey = "BaseKey"; context.CachedResponseValidFor = TimeSpan.FromSeconds(10); middleware.FinalizeCacheBody(context); Assert.Equal(0, cache.SetCount); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.ResponseContentLengthMismatchNotCached); }
public async Task FinalizeCacheBody_RequestHead_Cache_IfContentLengthPresent_AndBodyAbsentOrOfSameLength(bool includeBody) { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache); var context = TestUtils.CreateTestContext(); context.ShouldCacheResponse = true; middleware.ShimResponseStream(context); context.HttpContext.Response.ContentLength = 10; context.HttpContext.Request.Method = "HEAD"; if (includeBody) { // A response to HEAD should not include a body, but it may be present await context.HttpContext.Response.WriteAsync(new string('0', 10)); } context.CachedResponse = new CachedResponse(); context.BaseKey = "BaseKey"; context.CachedResponseValidFor = TimeSpan.FromSeconds(10); middleware.FinalizeCacheBody(context); Assert.Equal(1, cache.SetCount); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.ResponseCached); }
public void FinalizeCacheHeadersAsync_UpdateCachedVaryByRules_IfEquivalentToPrevious() { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache); var context = TestUtils.CreateTestContext(); context.HttpContext.Response.Headers.Vary = new StringValues(new[] { "headerA", "HEADERB" }); context.HttpContext.Features.Set <IResponseCachingFeature>(new ResponseCachingFeature() { VaryByQueryKeys = new StringValues(new[] { "queryB", "QUERYA" }) }); var cachedVaryByRules = new CachedVaryByRules() { VaryByKeyPrefix = FastGuid.NewGuid().IdString, Headers = new StringValues(new[] { "HEADERA", "HEADERB" }), QueryKeys = new StringValues(new[] { "QUERYA", "QUERYB" }) }; context.CachedVaryByRules = cachedVaryByRules; middleware.FinalizeCacheHeaders(context); // An update to the cache is always made but the entry should be the same Assert.Equal(1, cache.SetCount); Assert.Same(cachedVaryByRules, context.CachedVaryByRules); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.VaryByRulesUpdated); }
public void FinalizeCacheHeadersAsync_UpdateCachedVaryByRules_IfNotEquivalentToPrevious() { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache); var context = TestUtils.CreateTestContext(); context.HttpContext.Response.Headers.Vary = new StringValues(new[] { "headerA", "HEADERB", "HEADERc" }); context.HttpContext.Features.Set <IResponseCachingFeature>(new ResponseCachingFeature() { VaryByQueryKeys = new StringValues(new[] { "queryB", "QUERYA" }) }); var cachedVaryByRules = new CachedVaryByRules() { Headers = new StringValues(new[] { "HeaderA", "HeaderB" }), QueryKeys = new StringValues(new[] { "QueryA", "QueryB" }) }; context.CachedVaryByRules = cachedVaryByRules; middleware.FinalizeCacheHeaders(context); Assert.Equal(1, cache.SetCount); Assert.NotSame(cachedVaryByRules, context.CachedVaryByRules); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.VaryByRulesUpdated); }
public async Task TryServeFromCacheAsync_VaryByRuleFound_CachedResponseFound_Succeeds() { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider("BaseKey", new[] { "VaryKey", "VaryKey2" })); var context = TestUtils.CreateTestContext(); cache.Set( "BaseKey", new CachedVaryByRules(), TimeSpan.Zero); cache.Set( "BaseKeyVaryKey2", new CachedResponse() { Headers = new HeaderDictionary(), Body = new CachedResponseBody(new List <byte[]>(0), 0) }, TimeSpan.Zero); Assert.True(await middleware.TryServeFromCacheAsync(context)); Assert.Equal(3, cache.GetCount); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.CachedResponseServed); }
public async Task TryServeFromCacheAsync_CachedResponseNotFound_Fails() { var cache = new TestResponseCache(); var sink = new TestSink(); 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, cache.GetCount); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.NoResponseServed); }
public async Task TryServeFromCacheAsync_OnlyIfCached_Serves504() { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider()); var context = TestUtils.CreateTestContext(); context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue() { OnlyIfCached = true }.ToString(); Assert.True(await middleware.TryServeFromCacheAsync(context)); Assert.Equal(StatusCodes.Status504GatewayTimeout, context.HttpContext.Response.StatusCode); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.GatewayTimeoutServed); }
public async Task FinalizeCacheBody_DoNotCache_IfShouldCacheResponseFalse() { var cache = new TestResponseCache(); var sink = new TestSink(); 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 = false; middleware.FinalizeCacheBody(context); Assert.Equal(0, cache.SetCount); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.ResponseNotCached); }
public void FinalizeCacheHeadersAsync_UpdateCachedVaryByRules_NullOrEmptyRules(StringValues vary) { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache); var context = TestUtils.CreateTestContext(); context.HttpContext.Response.Headers.Vary = vary; context.HttpContext.Features.Set <IResponseCachingFeature>(new ResponseCachingFeature() { VaryByQueryKeys = vary }); middleware.FinalizeCacheHeaders(context); // Vary rules should not be updated Assert.Equal(0, cache.SetCount); Assert.Empty(sink.Writes); }
public async Task TryServeFromCacheAsync_CachedResponseFound_Serves304IfPossible() { var cache = new TestResponseCache(); var sink = new TestSink(); var middleware = TestUtils.CreateTestMiddleware(testSink: sink, cache: cache, keyProvider: new TestResponseCachingKeyProvider("BaseKey")); var context = TestUtils.CreateTestContext(); context.HttpContext.Request.Headers.IfNoneMatch = "*"; cache.Set( "BaseKey", new CachedResponse() { Body = new CachedResponseBody(new List <byte[]>(0), 0) }, TimeSpan.Zero); Assert.True(await middleware.TryServeFromCacheAsync(context)); Assert.Equal(1, cache.GetCount); TestUtils.AssertLoggedMessages( sink.Writes, LoggedMessage.NotModifiedServed); }
internal static ResponseCachingMiddleware CreateTestMiddleware( RequestDelegate next = null, IResponseCache cache = null, ResponseCachingOptions options = null, TestSink testSink = null, IResponseCachingKeyProvider keyProvider = null, IResponseCachingPolicyProvider policyProvider = null) { if (next == null) { next = httpContext => Task.CompletedTask; } if (cache == null) { cache = new TestResponseCache(); } if (options == null) { options = new ResponseCachingOptions(); } if (keyProvider == null) { keyProvider = new ResponseCachingKeyProvider(new DefaultObjectPoolProvider(), Options.Create(options)); } if (policyProvider == null) { policyProvider = new TestResponseCachingPolicyProvider(); } return(new ResponseCachingMiddleware( next, Options.Create(options), testSink == null ? (ILoggerFactory)NullLoggerFactory.Instance : new TestLoggerFactory(testSink, true), policyProvider, cache, keyProvider)); }