Adding options to specify maximum response body size
This commit is contained in:
parent
3b0f01a8ec
commit
d72ef128dd
|
|
@ -11,10 +11,12 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
|
||||||
internal class ResponseCacheStream : Stream
|
internal class ResponseCacheStream : Stream
|
||||||
{
|
{
|
||||||
private readonly Stream _innerStream;
|
private readonly Stream _innerStream;
|
||||||
|
private readonly long _maxBufferSize;
|
||||||
|
|
||||||
public ResponseCacheStream(Stream innerStream)
|
public ResponseCacheStream(Stream innerStream, long maxBufferSize)
|
||||||
{
|
{
|
||||||
_innerStream = innerStream;
|
_innerStream = innerStream;
|
||||||
|
_maxBufferSize = maxBufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemoryStream BufferedStream { get; } = new MemoryStream();
|
public MemoryStream BufferedStream { get; } = new MemoryStream();
|
||||||
|
|
@ -38,6 +40,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
|
||||||
public void DisableBuffering()
|
public void DisableBuffering()
|
||||||
{
|
{
|
||||||
BufferingEnabled = false;
|
BufferingEnabled = false;
|
||||||
|
BufferedStream.SetLength(0);
|
||||||
|
BufferedStream.Capacity = 0;
|
||||||
BufferedStream.Dispose();
|
BufferedStream.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,7 +81,14 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
|
||||||
|
|
||||||
if (BufferingEnabled)
|
if (BufferingEnabled)
|
||||||
{
|
{
|
||||||
BufferedStream.Write(buffer, offset, count);
|
if (BufferedStream.Length + count > _maxBufferSize)
|
||||||
|
{
|
||||||
|
DisableBuffering();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BufferedStream.Write(buffer, offset, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,7 +106,14 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
|
||||||
|
|
||||||
if (BufferingEnabled)
|
if (BufferingEnabled)
|
||||||
{
|
{
|
||||||
await BufferedStream.WriteAsync(buffer, offset, count, cancellationToken);
|
if (BufferedStream.Length + count > _maxBufferSize)
|
||||||
|
{
|
||||||
|
DisableBuffering();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await BufferedStream.WriteAsync(buffer, offset, count, cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,7 +131,14 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
|
||||||
|
|
||||||
if (BufferingEnabled)
|
if (BufferingEnabled)
|
||||||
{
|
{
|
||||||
BufferedStream.WriteByte(value);
|
if (BufferedStream.Length + 1 > _maxBufferSize)
|
||||||
|
{
|
||||||
|
DisableBuffering();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BufferedStream.WriteByte(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Http.Headers;
|
using Microsoft.AspNetCore.Http.Headers;
|
||||||
|
|
@ -25,7 +26,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
private readonly HttpContext _httpContext;
|
private readonly HttpContext _httpContext;
|
||||||
private readonly IResponseCache _cache;
|
private readonly IResponseCache _cache;
|
||||||
private readonly ISystemClock _clock;
|
private readonly ResponseCachingOptions _options;
|
||||||
private readonly ObjectPool<StringBuilder> _builderPool;
|
private readonly ObjectPool<StringBuilder> _builderPool;
|
||||||
private readonly IResponseCachingCacheabilityValidator _cacheabilityValidator;
|
private readonly IResponseCachingCacheabilityValidator _cacheabilityValidator;
|
||||||
private readonly IResponseCachingCacheKeyModifier _cacheKeyModifier;
|
private readonly IResponseCachingCacheKeyModifier _cacheKeyModifier;
|
||||||
|
|
@ -40,29 +41,19 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
private CachedResponse _cachedResponse;
|
private CachedResponse _cachedResponse;
|
||||||
private TimeSpan _cachedResponseValidFor;
|
private TimeSpan _cachedResponseValidFor;
|
||||||
internal DateTimeOffset _responseTime;
|
internal DateTimeOffset _responseTime;
|
||||||
|
|
||||||
internal ResponseCachingContext(
|
|
||||||
HttpContext httpContext,
|
|
||||||
IResponseCache cache,
|
|
||||||
ObjectPool<StringBuilder> builderPool,
|
|
||||||
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
|
||||||
IResponseCachingCacheKeyModifier cacheKeyModifier)
|
|
||||||
: this(httpContext, cache, new SystemClock(), builderPool, cacheabilityValidator, cacheKeyModifier)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal ResponseCachingContext(
|
internal ResponseCachingContext(
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
IResponseCache cache,
|
IResponseCache cache,
|
||||||
ISystemClock clock,
|
ResponseCachingOptions options,
|
||||||
ObjectPool<StringBuilder> builderPool,
|
ObjectPool<StringBuilder> builderPool,
|
||||||
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
||||||
IResponseCachingCacheKeyModifier cacheKeyModifier)
|
IResponseCachingCacheKeyModifier cacheKeyModifier)
|
||||||
{
|
{
|
||||||
_httpContext = httpContext;
|
_httpContext = httpContext;
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
_clock = clock;
|
_options = options;
|
||||||
_builderPool = builderPool;
|
_builderPool = builderPool;
|
||||||
_cacheabilityValidator = cacheabilityValidator;
|
_cacheabilityValidator = cacheabilityValidator;
|
||||||
_cacheKeyModifier = cacheKeyModifier;
|
_cacheKeyModifier = cacheKeyModifier;
|
||||||
|
|
@ -74,10 +65,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
{
|
{
|
||||||
if (_cacheResponse == null)
|
if (_cacheResponse == null)
|
||||||
{
|
{
|
||||||
// TODO: apparent age vs corrected age value
|
_cacheResponse = ResponseIsCacheable();
|
||||||
var responseAge = _responseTime - ResponseHeaders.Date ?? TimeSpan.Zero;
|
|
||||||
|
|
||||||
_cacheResponse = ResponseIsCacheable() && EntryIsFresh(ResponseHeaders, responseAge, verifyAgainstRequest: false);
|
|
||||||
}
|
}
|
||||||
return _cacheResponse.Value;
|
return _cacheResponse.Value;
|
||||||
}
|
}
|
||||||
|
|
@ -363,6 +351,14 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check response freshness
|
||||||
|
// TODO: apparent age vs corrected age value
|
||||||
|
var responseAge = _responseTime - ResponseHeaders.Date ?? TimeSpan.Zero;
|
||||||
|
if (!EntryIsFresh(ResponseHeaders, responseAge, verifyAgainstRequest: false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -433,7 +429,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
var cachedResponse = cacheEntry as CachedResponse;
|
var cachedResponse = cacheEntry as CachedResponse;
|
||||||
var cachedResponseHeaders = new ResponseHeaders(cachedResponse.Headers);
|
var cachedResponseHeaders = new ResponseHeaders(cachedResponse.Headers);
|
||||||
|
|
||||||
_responseTime = _clock.UtcNow;
|
_responseTime = _options.SystemClock.UtcNow;
|
||||||
var age = _responseTime - cachedResponse.Created;
|
var age = _responseTime - cachedResponse.Created;
|
||||||
age = age > TimeSpan.Zero ? age : TimeSpan.Zero;
|
age = age > TimeSpan.Zero ? age : TimeSpan.Zero;
|
||||||
|
|
||||||
|
|
@ -607,7 +603,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
if (!ResponseStarted)
|
if (!ResponseStarted)
|
||||||
{
|
{
|
||||||
ResponseStarted = true;
|
ResponseStarted = true;
|
||||||
_responseTime = _clock.UtcNow;
|
_responseTime = _options.SystemClock.UtcNow;
|
||||||
|
|
||||||
FinalizeCachingHeaders();
|
FinalizeCachingHeaders();
|
||||||
}
|
}
|
||||||
|
|
@ -619,7 +615,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
// Shim response stream
|
// Shim response stream
|
||||||
OriginalResponseStream = _httpContext.Response.Body;
|
OriginalResponseStream = _httpContext.Response.Body;
|
||||||
ResponseCacheStream = new ResponseCacheStream(OriginalResponseStream);
|
ResponseCacheStream = new ResponseCacheStream(OriginalResponseStream, _options.MaximumCachedBodySize);
|
||||||
_httpContext.Response.Body = ResponseCacheStream;
|
_httpContext.Response.Body = ResponseCacheStream;
|
||||||
|
|
||||||
// Shim IHttpSendFileFeature
|
// Shim IHttpSendFileFeature
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.ResponseCaching;
|
using Microsoft.AspNetCore.ResponseCaching;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Builder
|
namespace Microsoft.AspNetCore.Builder
|
||||||
{
|
{
|
||||||
|
|
@ -17,5 +18,19 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
|
|
||||||
return app.UseMiddleware<ResponseCachingMiddleware>();
|
return app.UseMiddleware<ResponseCachingMiddleware>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IApplicationBuilder UseResponseCaching(this IApplicationBuilder app, ResponseCachingOptions options)
|
||||||
|
{
|
||||||
|
if (app == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(app));
|
||||||
|
}
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.UseMiddleware<ResponseCachingMiddleware>(Options.Create(options));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.ObjectPool;
|
using Microsoft.Extensions.ObjectPool;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
@ -20,13 +21,15 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IResponseCache _cache;
|
private readonly IResponseCache _cache;
|
||||||
|
private readonly ResponseCachingOptions _options;
|
||||||
private readonly ObjectPool<StringBuilder> _builderPool;
|
private readonly ObjectPool<StringBuilder> _builderPool;
|
||||||
private readonly IResponseCachingCacheabilityValidator _cacheabilityValidator;
|
private readonly IResponseCachingCacheabilityValidator _cacheabilityValidator;
|
||||||
private readonly IResponseCachingCacheKeyModifier _cacheKeyModifier;
|
private readonly IResponseCachingCacheKeyModifier _cacheKeyModifier;
|
||||||
|
|
||||||
public ResponseCachingMiddleware(
|
public ResponseCachingMiddleware(
|
||||||
RequestDelegate next,
|
RequestDelegate next,
|
||||||
IResponseCache cache,
|
IResponseCache cache,
|
||||||
|
IOptions<ResponseCachingOptions> options,
|
||||||
ObjectPoolProvider poolProvider,
|
ObjectPoolProvider poolProvider,
|
||||||
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
IResponseCachingCacheabilityValidator cacheabilityValidator,
|
||||||
IResponseCachingCacheKeyModifier cacheKeyModifier)
|
IResponseCachingCacheKeyModifier cacheKeyModifier)
|
||||||
|
|
@ -39,6 +42,10 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(cache));
|
throw new ArgumentNullException(nameof(cache));
|
||||||
}
|
}
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
if (poolProvider == null)
|
if (poolProvider == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(poolProvider));
|
throw new ArgumentNullException(nameof(poolProvider));
|
||||||
|
|
@ -54,6 +61,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
|
|
||||||
_next = next;
|
_next = next;
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
|
_options = options.Value;
|
||||||
_builderPool = poolProvider.CreateStringBuilderPool();
|
_builderPool = poolProvider.CreateStringBuilderPool();
|
||||||
_cacheabilityValidator = cacheabilityValidator;
|
_cacheabilityValidator = cacheabilityValidator;
|
||||||
_cacheKeyModifier = cacheKeyModifier;
|
_cacheKeyModifier = cacheKeyModifier;
|
||||||
|
|
@ -64,6 +72,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
||||||
var cachingContext = new ResponseCachingContext(
|
var cachingContext = new ResponseCachingContext(
|
||||||
context,
|
context,
|
||||||
_cache,
|
_cache,
|
||||||
|
_options,
|
||||||
_builderPool,
|
_builderPool,
|
||||||
_cacheabilityValidator,
|
_cacheabilityValidator,
|
||||||
_cacheKeyModifier);
|
_cacheKeyModifier);
|
||||||
|
|
|
||||||
|
|
@ -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.ComponentModel;
|
||||||
|
using Microsoft.AspNetCore.ResponseCaching.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Builder
|
||||||
|
{
|
||||||
|
public class ResponseCachingOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The largest cacheable size for the response body in bytes.
|
||||||
|
/// </summary>
|
||||||
|
public long MaximumCachedBodySize { get; set; } = 1024 * 1024;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For testing purposes only.
|
||||||
|
/// </summary>
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
internal ISystemClock SystemClock { get; set; } = new SystemClock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Http.Headers;
|
using Microsoft.AspNetCore.Http.Headers;
|
||||||
|
|
@ -859,7 +860,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
return new ResponseCachingContext(
|
return new ResponseCachingContext(
|
||||||
httpContext,
|
httpContext,
|
||||||
new TestResponseCache(),
|
new TestResponseCache(),
|
||||||
new SystemClock(),
|
new ResponseCachingOptions(),
|
||||||
new DefaultObjectPool<StringBuilder>(new StringBuilderPooledObjectPolicy()),
|
new DefaultObjectPool<StringBuilder>(new StringBuilderPooledObjectPolicy()),
|
||||||
cacheabilityValidator,
|
cacheabilityValidator,
|
||||||
cacheKeyModifier);
|
cacheKeyModifier);
|
||||||
|
|
|
||||||
|
|
@ -21,19 +21,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void ServesCachedContent_IfAvailable()
|
public async void ServesCachedContent_IfAvailable()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching();
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
{
|
{
|
||||||
|
|
@ -48,19 +36,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void ServesFreshContent_IfNotAvailable()
|
public async void ServesFreshContent_IfNotAvailable()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching();
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
{
|
{
|
||||||
|
|
@ -77,17 +53,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.Response.Headers[HeaderNames.Vary] = HeaderNames.From;
|
context.Response.Headers[HeaderNames.Vary] = HeaderNames.From;
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -106,17 +73,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.Response.Headers[HeaderNames.Vary] = HeaderNames.From;
|
context.Response.Headers[HeaderNames.Vary] = HeaderNames.From;
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -136,17 +94,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.GetResponseCachingFeature().VaryByParams = "param";
|
context.GetResponseCachingFeature().VaryByParams = "param";
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -162,28 +111,10 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void ServesCachedContent_IfVaryByParamsExplicit_Matches_ParamNameCaseInsensitive()
|
public async void ServesCachedContent_IfVaryByParamsExplicit_Matches_ParamNameCaseInsensitive()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
app =>
|
|
||||||
{
|
{
|
||||||
app.Use(async (context, next) =>
|
|
||||||
{
|
|
||||||
context.Features.Set<IHttpSendFileFeature>(new DummySendFileFeature());
|
|
||||||
await next.Invoke();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
async (context) =>
|
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.GetResponseCachingFeature().VaryByParams = new[] { "ParamA", "paramb" };
|
context.GetResponseCachingFeature().VaryByParams = new[] { "ParamA", "paramb" };
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -199,28 +130,10 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void ServesCachedContent_IfVaryByParamsStar_Matches_ParamNameCaseInsensitive()
|
public async void ServesCachedContent_IfVaryByParamsStar_Matches_ParamNameCaseInsensitive()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
app =>
|
|
||||||
{
|
{
|
||||||
app.Use(async (context, next) =>
|
|
||||||
{
|
|
||||||
context.Features.Set<IHttpSendFileFeature>(new DummySendFileFeature());
|
|
||||||
await next.Invoke();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
async (context) =>
|
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.GetResponseCachingFeature().VaryByParams = new[] { "*" };
|
context.GetResponseCachingFeature().VaryByParams = new[] { "*" };
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -238,17 +151,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.GetResponseCachingFeature().VaryByParams = new[] { "ParamB", "ParamA" };
|
context.GetResponseCachingFeature().VaryByParams = new[] { "ParamB", "ParamA" };
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -266,17 +170,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.GetResponseCachingFeature().VaryByParams = new[] { "*" };
|
context.GetResponseCachingFeature().VaryByParams = new[] { "*" };
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -294,17 +189,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.GetResponseCachingFeature().VaryByParams = "param";
|
context.GetResponseCachingFeature().VaryByParams = "param";
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -322,17 +208,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.GetResponseCachingFeature().VaryByParams = new[] { "ParamA", "ParamB" };
|
context.GetResponseCachingFeature().VaryByParams = new[] { "ParamA", "ParamB" };
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -350,17 +227,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
context.GetResponseCachingFeature().VaryByParams = new[] { "*" };
|
context.GetResponseCachingFeature().VaryByParams = new[] { "*" };
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -376,19 +244,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void ServesFreshContent_IfRequestRequirements_NotMet()
|
public async void ServesFreshContent_IfRequestRequirements_NotMet()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching();
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
{
|
{
|
||||||
|
|
@ -407,19 +263,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void Serves504_IfOnlyIfCachedHeader_IsSpecified()
|
public async void Serves504_IfOnlyIfCachedHeader_IsSpecified()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching();
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
{
|
{
|
||||||
|
|
@ -441,17 +285,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
var headers = context.Response.Headers[HeaderNames.SetCookie] = "cookieName=cookieValue";
|
||||||
var headers = context.Response.GetTypedHeaders();
|
await DefaultRequestDelegate(context);
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
headers.Headers[HeaderNames.SetCookie] = "cookieName=cookieValue";
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -480,28 +315,14 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void ServesCachedContent_IfIHttpSendFileFeature_NotUsed()
|
public async void ServesCachedContent_IfIHttpSendFileFeature_NotUsed()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(
|
var builder = CreateBuilderWithResponseCaching(app =>
|
||||||
app =>
|
{
|
||||||
|
app.Use(async (context, next) =>
|
||||||
{
|
{
|
||||||
app.Use(async (context, next) =>
|
context.Features.Set<IHttpSendFileFeature>(new DummySendFileFeature());
|
||||||
{
|
await next.Invoke();
|
||||||
context.Features.Set<IHttpSendFileFeature>(new DummySendFileFeature());
|
|
||||||
await next.Invoke();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
async (context) =>
|
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
{
|
{
|
||||||
|
|
@ -527,17 +348,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
},
|
},
|
||||||
async (context) =>
|
async (context) =>
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Features.Get<IHttpSendFileFeature>().SendFileAsync("dummy", 0, 0, CancellationToken.None);
|
await context.Features.Get<IHttpSendFileFeature>().SendFileAsync("dummy", 0, 0, CancellationToken.None);
|
||||||
await context.Response.WriteAsync(uniqueId);
|
await DefaultRequestDelegate(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
|
|
@ -553,20 +365,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void ServesCachedContent_IfSubsequentRequest_ContainsNoStore()
|
public async void ServesCachedContent_IfSubsequentRequest_ContainsNoStore()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(
|
var builder = CreateBuilderWithResponseCaching();
|
||||||
async (context) =>
|
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
{
|
{
|
||||||
|
|
@ -585,20 +384,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void ServesFreshContent_IfInitialRequestContains_NoStore()
|
public async void ServesFreshContent_IfInitialRequestContains_NoStore()
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(
|
var builder = CreateBuilderWithResponseCaching();
|
||||||
async (context) =>
|
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
using (var server = new TestServer(builder))
|
||||||
{
|
{
|
||||||
|
|
@ -614,6 +400,116 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void Serves304_IfIfModifiedSince_Satisfied()
|
||||||
|
{
|
||||||
|
var builder = CreateBuilderWithResponseCaching();
|
||||||
|
|
||||||
|
using (var server = new TestServer(builder))
|
||||||
|
{
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var initialResponse = await client.GetAsync("");
|
||||||
|
client.DefaultRequestHeaders.IfUnmodifiedSince = DateTimeOffset.MaxValue;
|
||||||
|
var subsequentResponse = await client.GetAsync("");
|
||||||
|
|
||||||
|
initialResponse.EnsureSuccessStatusCode();
|
||||||
|
Assert.Equal(System.Net.HttpStatusCode.NotModified, subsequentResponse.StatusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ServesCachedContent_IfIfModifiedSince_NotSatisfied()
|
||||||
|
{
|
||||||
|
var builder = CreateBuilderWithResponseCaching();
|
||||||
|
|
||||||
|
using (var server = new TestServer(builder))
|
||||||
|
{
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var initialResponse = await client.GetAsync("");
|
||||||
|
client.DefaultRequestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue;
|
||||||
|
var subsequentResponse = await client.GetAsync("");
|
||||||
|
|
||||||
|
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void Serves304_IfIfNoneMatch_Satisfied()
|
||||||
|
{
|
||||||
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
|
{
|
||||||
|
var headers = context.Response.GetTypedHeaders().ETag = new EntityTagHeaderValue("\"E1\"");
|
||||||
|
await DefaultRequestDelegate(context);
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var server = new TestServer(builder))
|
||||||
|
{
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var initialResponse = await client.GetAsync("");
|
||||||
|
client.DefaultRequestHeaders.IfNoneMatch.Add(new System.Net.Http.Headers.EntityTagHeaderValue("\"E1\""));
|
||||||
|
var subsequentResponse = await client.GetAsync("");
|
||||||
|
|
||||||
|
initialResponse.EnsureSuccessStatusCode();
|
||||||
|
Assert.Equal(System.Net.HttpStatusCode.NotModified, subsequentResponse.StatusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ServesCachedContent_IfIfNoneMatch_NotSatisfied()
|
||||||
|
{
|
||||||
|
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
||||||
|
{
|
||||||
|
var headers = context.Response.GetTypedHeaders().ETag = new EntityTagHeaderValue("\"E1\"");
|
||||||
|
await DefaultRequestDelegate(context);
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var server = new TestServer(builder))
|
||||||
|
{
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var initialResponse = await client.GetAsync("");
|
||||||
|
client.DefaultRequestHeaders.IfNoneMatch.Add(new System.Net.Http.Headers.EntityTagHeaderValue("\"E2\""));
|
||||||
|
var subsequentResponse = await client.GetAsync("");
|
||||||
|
|
||||||
|
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ServesCachedContent_IfBodySize_IsCacheable()
|
||||||
|
{
|
||||||
|
var builder = CreateBuilderWithResponseCaching(new ResponseCachingOptions()
|
||||||
|
{
|
||||||
|
MaximumCachedBodySize = 100
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var server = new TestServer(builder))
|
||||||
|
{
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var initialResponse = await client.GetAsync("");
|
||||||
|
var subsequentResponse = await client.GetAsync("");
|
||||||
|
|
||||||
|
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ServesFreshContent_IfBodySize_IsNotCacheable()
|
||||||
|
{
|
||||||
|
var builder = CreateBuilderWithResponseCaching(new ResponseCachingOptions()
|
||||||
|
{
|
||||||
|
MaximumCachedBodySize = 1
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var server = new TestServer(builder))
|
||||||
|
{
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var initialResponse = await client.GetAsync("");
|
||||||
|
var subsequentResponse = await client.GetAsync("/different");
|
||||||
|
|
||||||
|
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static async Task AssertResponseCachedAsync(HttpResponseMessage initialResponse, HttpResponseMessage subsequentResponse)
|
private static async Task AssertResponseCachedAsync(HttpResponseMessage initialResponse, HttpResponseMessage subsequentResponse)
|
||||||
{
|
{
|
||||||
initialResponse.EnsureSuccessStatusCode();
|
initialResponse.EnsureSuccessStatusCode();
|
||||||
|
|
@ -636,126 +532,36 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
Assert.NotEqual(await initialResponse.Content.ReadAsStringAsync(), await subsequentResponse.Content.ReadAsStringAsync());
|
Assert.NotEqual(await initialResponse.Content.ReadAsStringAsync(), await subsequentResponse.Content.ReadAsStringAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
private static RequestDelegate DefaultRequestDelegate = async (context) =>
|
||||||
public async void Serves304_IfIfModifiedSince_Satisfied()
|
|
||||||
{
|
{
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
var uniqueId = Guid.NewGuid().ToString();
|
||||||
|
var headers = context.Response.GetTypedHeaders();
|
||||||
|
headers.CacheControl = new CacheControlHeaderValue()
|
||||||
{
|
{
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
Public = true,
|
||||||
var headers = context.Response.GetTypedHeaders();
|
MaxAge = TimeSpan.FromSeconds(10)
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
};
|
||||||
{
|
headers.Date = DateTimeOffset.UtcNow;
|
||||||
Public = true,
|
headers.Headers["X-Value"] = uniqueId;
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
await context.Response.WriteAsync(uniqueId);
|
||||||
};
|
};
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
private static IWebHostBuilder CreateBuilderWithResponseCaching() =>
|
||||||
{
|
CreateBuilderWithResponseCaching(app => { }, new ResponseCachingOptions(), DefaultRequestDelegate);
|
||||||
var client = server.CreateClient();
|
|
||||||
var initialResponse = await client.GetAsync("");
|
|
||||||
client.DefaultRequestHeaders.IfUnmodifiedSince = DateTimeOffset.MaxValue;
|
|
||||||
var subsequentResponse = await client.GetAsync("");
|
|
||||||
|
|
||||||
initialResponse.EnsureSuccessStatusCode();
|
private static IWebHostBuilder CreateBuilderWithResponseCaching(ResponseCachingOptions options) =>
|
||||||
Assert.Equal(System.Net.HttpStatusCode.NotModified, subsequentResponse.StatusCode);
|
CreateBuilderWithResponseCaching(app => { }, options, DefaultRequestDelegate);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async void ServesCachedContent_IfIfModifiedSince_NotSatisfied()
|
|
||||||
{
|
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
|
||||||
{
|
|
||||||
var client = server.CreateClient();
|
|
||||||
var initialResponse = await client.GetAsync("");
|
|
||||||
client.DefaultRequestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue;
|
|
||||||
var subsequentResponse = await client.GetAsync("");
|
|
||||||
|
|
||||||
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async void Serves304_IfIfNoneMatch_Satisfied()
|
|
||||||
{
|
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
headers.ETag = new EntityTagHeaderValue("\"E1\"");
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
|
||||||
{
|
|
||||||
var client = server.CreateClient();
|
|
||||||
var initialResponse = await client.GetAsync("");
|
|
||||||
client.DefaultRequestHeaders.IfNoneMatch.Add(new System.Net.Http.Headers.EntityTagHeaderValue("\"E1\""));
|
|
||||||
var subsequentResponse = await client.GetAsync("");
|
|
||||||
|
|
||||||
initialResponse.EnsureSuccessStatusCode();
|
|
||||||
Assert.Equal(System.Net.HttpStatusCode.NotModified, subsequentResponse.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async void ServesCachedContent_IfIfNoneMatch_NotSatisfied()
|
|
||||||
{
|
|
||||||
var builder = CreateBuilderWithResponseCaching(async (context) =>
|
|
||||||
{
|
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
|
||||||
var headers = context.Response.GetTypedHeaders();
|
|
||||||
headers.CacheControl = new CacheControlHeaderValue()
|
|
||||||
{
|
|
||||||
Public = true,
|
|
||||||
MaxAge = TimeSpan.FromSeconds(10)
|
|
||||||
};
|
|
||||||
headers.Date = DateTimeOffset.UtcNow;
|
|
||||||
headers.Headers["X-Value"] = uniqueId;
|
|
||||||
headers.ETag = new EntityTagHeaderValue("\"E1\"");
|
|
||||||
await context.Response.WriteAsync(uniqueId);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var server = new TestServer(builder))
|
|
||||||
{
|
|
||||||
var client = server.CreateClient();
|
|
||||||
var initialResponse = await client.GetAsync("");
|
|
||||||
client.DefaultRequestHeaders.IfNoneMatch.Add(new System.Net.Http.Headers.EntityTagHeaderValue("\"E2\""));
|
|
||||||
var subsequentResponse = await client.GetAsync("");
|
|
||||||
|
|
||||||
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IWebHostBuilder CreateBuilderWithResponseCaching(RequestDelegate requestDelegate) =>
|
private static IWebHostBuilder CreateBuilderWithResponseCaching(RequestDelegate requestDelegate) =>
|
||||||
CreateBuilderWithResponseCaching(app => { }, requestDelegate);
|
CreateBuilderWithResponseCaching(app => { }, new ResponseCachingOptions(), requestDelegate);
|
||||||
|
|
||||||
private static IWebHostBuilder CreateBuilderWithResponseCaching(Action<IApplicationBuilder> configureDelegate, RequestDelegate requestDelegate)
|
private static IWebHostBuilder CreateBuilderWithResponseCaching(Action<IApplicationBuilder> configureDelegate) =>
|
||||||
|
CreateBuilderWithResponseCaching(configureDelegate, new ResponseCachingOptions(), DefaultRequestDelegate);
|
||||||
|
|
||||||
|
private static IWebHostBuilder CreateBuilderWithResponseCaching(Action<IApplicationBuilder> configureDelegate, RequestDelegate requestDelegate) =>
|
||||||
|
CreateBuilderWithResponseCaching(configureDelegate, new ResponseCachingOptions(), requestDelegate);
|
||||||
|
|
||||||
|
private static IWebHostBuilder CreateBuilderWithResponseCaching(Action<IApplicationBuilder> configureDelegate, ResponseCachingOptions options, RequestDelegate requestDelegate)
|
||||||
{
|
{
|
||||||
return new WebHostBuilder()
|
return new WebHostBuilder()
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
|
|
@ -765,7 +571,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
configureDelegate(app);
|
configureDelegate(app);
|
||||||
app.UseResponseCaching();
|
app.UseResponseCaching(options);
|
||||||
app.Run(requestDelegate);
|
app.Run(requestDelegate);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue