API updates
- Internalize properties on ResponseCacheContext unless required by extension points - Rename VaryByParams -> VaryByQueryKeys
This commit is contained in:
parent
6891d00032
commit
5e12a103a4
|
|
@ -127,8 +127,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
|
|||
// Guid (long)
|
||||
// Headers count
|
||||
// Header(s) (comma separated string)
|
||||
// Params count
|
||||
// Param(s) (comma separated string)
|
||||
// QueryKey count
|
||||
// QueryKey(s) (comma separated string)
|
||||
private static CachedVaryByRules ReadCachedVaryByRules(BinaryReader reader)
|
||||
{
|
||||
var varyKeyPrefix = reader.ReadString();
|
||||
|
|
@ -139,14 +139,14 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
|
|||
{
|
||||
headers[index] = reader.ReadString();
|
||||
}
|
||||
var paramCount = reader.ReadInt32();
|
||||
var param = new string[paramCount];
|
||||
for (var index = 0; index < paramCount; index++)
|
||||
var queryKeysCount = reader.ReadInt32();
|
||||
var queryKeys = new string[queryKeysCount];
|
||||
for (var index = 0; index < queryKeysCount; index++)
|
||||
{
|
||||
param[index] = reader.ReadString();
|
||||
queryKeys[index] = reader.ReadString();
|
||||
}
|
||||
|
||||
return new CachedVaryByRules { VaryByKeyPrefix = varyKeyPrefix, Headers = headers, Params = param };
|
||||
return new CachedVaryByRules { VaryByKeyPrefix = varyKeyPrefix, Headers = headers, QueryKeys = queryKeys };
|
||||
}
|
||||
|
||||
// See serialization format above
|
||||
|
|
@ -228,10 +228,10 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
|
|||
writer.Write(header);
|
||||
}
|
||||
|
||||
writer.Write(varyByRules.Params.Count);
|
||||
foreach (var param in varyByRules.Params)
|
||||
writer.Write(varyByRules.QueryKeys.Count);
|
||||
foreach (var queryKey in varyByRules.QueryKeys)
|
||||
{
|
||||
writer.Write(param);
|
||||
writer.Write(queryKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
|
||||
public StringValues Headers { get; set; }
|
||||
|
||||
public StringValues Params { get; set; }
|
||||
public StringValues QueryKeys { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,22 +32,22 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
|
||||
public HttpContext HttpContext { get; }
|
||||
|
||||
public bool ShouldCacheResponse { get; internal set; }
|
||||
public DateTimeOffset? ResponseTime { get; internal set; }
|
||||
|
||||
public string BaseKey { get; internal set; }
|
||||
|
||||
public string StorageVaryKey { get; internal set; }
|
||||
|
||||
public DateTimeOffset ResponseTime { get; internal set; }
|
||||
|
||||
public TimeSpan CachedEntryAge { get; internal set; }
|
||||
|
||||
public TimeSpan CachedResponseValidFor { get; internal set; }
|
||||
|
||||
public CachedResponse CachedResponse { get; internal set; }
|
||||
public TimeSpan? CachedEntryAge { get; internal set; }
|
||||
|
||||
public CachedVaryByRules CachedVaryByRules { get; internal set; }
|
||||
|
||||
internal bool ShouldCacheResponse { get; set; }
|
||||
|
||||
internal string BaseKey { get; set; }
|
||||
|
||||
internal string StorageVaryKey { get; set; }
|
||||
|
||||
internal TimeSpan CachedResponseValidFor { get; set; }
|
||||
|
||||
internal CachedResponse CachedResponse { get; set; }
|
||||
|
||||
internal bool ResponseStarted { get; set; }
|
||||
|
||||
internal Stream OriginalResponseStream { get; set; }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
{
|
||||
public class ResponseCacheFeature
|
||||
{
|
||||
public StringValues VaryByParams { get; set; }
|
||||
public StringValues VaryByQueryKeys { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,12 +75,12 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
}
|
||||
|
||||
var varyByRules = context.CachedVaryByRules;
|
||||
if (varyByRules == null)
|
||||
if (varyByRules == null)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(CachedVaryByRules)} must not be null on the {nameof(ResponseCacheContext)}");
|
||||
}
|
||||
|
||||
if ((StringValues.IsNullOrEmpty(varyByRules.Headers) && StringValues.IsNullOrEmpty(varyByRules.Params)))
|
||||
if ((StringValues.IsNullOrEmpty(varyByRules.Headers) && StringValues.IsNullOrEmpty(varyByRules.QueryKeys)))
|
||||
{
|
||||
return varyByRules.VaryByKeyPrefix;
|
||||
}
|
||||
|
|
@ -110,16 +110,16 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
}
|
||||
}
|
||||
|
||||
// Vary by query params
|
||||
if (varyByRules?.Params.Count > 0)
|
||||
// Vary by query keys
|
||||
if (varyByRules?.QueryKeys.Count > 0)
|
||||
{
|
||||
// Append a group separator for the query parameter segment of the cache key
|
||||
// Append a group separator for the query key segment of the cache key
|
||||
builder.Append(KeyDelimiter)
|
||||
.Append('Q');
|
||||
|
||||
if (varyByRules.Params.Count == 1 && string.Equals(varyByRules.Params[0], "*", StringComparison.Ordinal))
|
||||
if (varyByRules.QueryKeys.Count == 1 && string.Equals(varyByRules.QueryKeys[0], "*", StringComparison.Ordinal))
|
||||
{
|
||||
// Vary by all available query params
|
||||
// Vary by all available query keys
|
||||
foreach (var query in context.HttpContext.Request.Query.OrderBy(q => q.Key, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
builder.Append(KeyDelimiter)
|
||||
|
|
@ -130,13 +130,13 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
}
|
||||
else
|
||||
{
|
||||
foreach (var param in varyByRules.Params)
|
||||
foreach (var queryKey in varyByRules.QueryKeys)
|
||||
{
|
||||
builder.Append(KeyDelimiter)
|
||||
.Append(param)
|
||||
.Append(queryKey)
|
||||
.Append("=")
|
||||
// TODO: Perf - iterate the string values instead?
|
||||
.Append(context.HttpContext.Request.Query[param]);
|
||||
.Append(context.HttpContext.Request.Query[queryKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
context.CachedResponse = cachedResponse;
|
||||
context.CachedResponseHeaders = new ResponseHeaders(cachedResponse.Headers);
|
||||
context.ResponseTime = _options.SystemClock.UtcNow;
|
||||
var cachedEntryAge = context.ResponseTime - context.CachedResponse.Created;
|
||||
var cachedEntryAge = context.ResponseTime.Value - context.CachedResponse.Created;
|
||||
context.CachedEntryAge = cachedEntryAge > TimeSpan.Zero ? cachedEntryAge : TimeSpan.Zero;
|
||||
|
||||
if (_policyProvider.IsCachedEntryFresh(context))
|
||||
|
|
@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
response.Headers.Add(header);
|
||||
}
|
||||
|
||||
response.Headers[HeaderNames.Age] = context.CachedEntryAge.TotalSeconds.ToString("F0", CultureInfo.InvariantCulture);
|
||||
response.Headers[HeaderNames.Age] = context.CachedEntryAge.Value.TotalSeconds.ToString("F0", CultureInfo.InvariantCulture);
|
||||
|
||||
var body = context.CachedResponse.Body ??
|
||||
((CachedResponseBody) await _store.GetAsync(context.CachedResponse.BodyKeyPrefix))?.Body;
|
||||
|
|
@ -200,30 +200,30 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
|
||||
// Create the cache entry now
|
||||
var response = context.HttpContext.Response;
|
||||
var varyHeaderValue = new StringValues(response.Headers.GetCommaSeparatedValues(HeaderNames.Vary));
|
||||
var varyParamsValue = context.HttpContext.GetResponseCacheFeature()?.VaryByParams ?? StringValues.Empty;
|
||||
var varyHeaders = new StringValues(response.Headers.GetCommaSeparatedValues(HeaderNames.Vary));
|
||||
var varyQueryKeys = context.HttpContext.GetResponseCacheFeature()?.VaryByQueryKeys ?? StringValues.Empty;
|
||||
context.CachedResponseValidFor = context.ResponseCacheControlHeaderValue.SharedMaxAge ??
|
||||
context.ResponseCacheControlHeaderValue.MaxAge ??
|
||||
(context.ResponseExpires - context.ResponseTime) ??
|
||||
(context.ResponseExpires - context.ResponseTime.Value) ??
|
||||
DefaultExpirationTimeSpan;
|
||||
|
||||
// Check if any vary rules exist
|
||||
if (!StringValues.IsNullOrEmpty(varyHeaderValue) || !StringValues.IsNullOrEmpty(varyParamsValue))
|
||||
if (!StringValues.IsNullOrEmpty(varyHeaders) || !StringValues.IsNullOrEmpty(varyQueryKeys))
|
||||
{
|
||||
// Normalize order and casing of vary by rules
|
||||
var normalizedVaryHeaderValue = GetOrderCasingNormalizedStringValues(varyHeaderValue);
|
||||
var normalizedVaryParamsValue = GetOrderCasingNormalizedStringValues(varyParamsValue);
|
||||
var normalizedVaryHeaders = GetOrderCasingNormalizedStringValues(varyHeaders);
|
||||
var normalizedVaryQueryKeys = GetOrderCasingNormalizedStringValues(varyQueryKeys);
|
||||
|
||||
// Update vary rules if they are different
|
||||
if (context.CachedVaryByRules == null ||
|
||||
!StringValues.Equals(context.CachedVaryByRules.Params, normalizedVaryParamsValue) ||
|
||||
!StringValues.Equals(context.CachedVaryByRules.Headers, normalizedVaryHeaderValue))
|
||||
!StringValues.Equals(context.CachedVaryByRules.QueryKeys, normalizedVaryQueryKeys) ||
|
||||
!StringValues.Equals(context.CachedVaryByRules.Headers, normalizedVaryHeaders))
|
||||
{
|
||||
context.CachedVaryByRules = new CachedVaryByRules
|
||||
{
|
||||
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
|
||||
Headers = normalizedVaryHeaderValue,
|
||||
Params = normalizedVaryParamsValue
|
||||
Headers = normalizedVaryHeaders,
|
||||
QueryKeys = normalizedVaryQueryKeys
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
// Ensure date header is set
|
||||
if (!context.ResponseDate.HasValue)
|
||||
{
|
||||
context.ResponseDate = context.ResponseTime;
|
||||
context.ResponseDate = context.ResponseTime.Value;
|
||||
// Setting the date on the raw response headers.
|
||||
context.TypedResponseHeaders.Date = context.ResponseDate;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,14 +104,14 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
{
|
||||
if (!context.ResponseCacheControlHeaderValue.SharedMaxAge.HasValue &&
|
||||
!context.ResponseCacheControlHeaderValue.MaxAge.HasValue &&
|
||||
context.ResponseTime >= context.ResponseExpires)
|
||||
context.ResponseTime.Value >= context.ResponseExpires)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var age = context.ResponseTime - context.ResponseDate.Value;
|
||||
var age = context.ResponseTime.Value - context.ResponseDate.Value;
|
||||
|
||||
// Validate shared max age
|
||||
if (age >= context.ResponseCacheControlHeaderValue.SharedMaxAge)
|
||||
|
|
@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
else if (!context.ResponseCacheControlHeaderValue.MaxAge.HasValue)
|
||||
{
|
||||
// Validate expiration
|
||||
if (context.ResponseTime >= context.ResponseExpires)
|
||||
if (context.ResponseTime.Value >= context.ResponseExpires)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
|
||||
public virtual bool IsCachedEntryFresh(ResponseCacheContext context)
|
||||
{
|
||||
var age = context.CachedEntryAge;
|
||||
var age = context.CachedEntryAge.Value;
|
||||
var cachedControlHeaders = context.CachedResponseHeaders.CacheControl ?? EmptyCacheControl;
|
||||
|
||||
// Add min-fresh requirements
|
||||
|
|
@ -178,7 +178,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
|
|||
else if (!cachedControlHeaders.MaxAge.HasValue && !context.RequestCacheControlHeaderValue.MaxAge.HasValue)
|
||||
{
|
||||
// Validate expiration
|
||||
if (context.ResponseTime >= context.CachedResponseHeaders.Expires)
|
||||
if (context.ResponseTime.Value >= context.CachedResponseHeaders.Expires)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,28 +101,28 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTrip_CachedVaryByRule_ParamsOnly_Succeeds()
|
||||
public void RoundTrip_CachedVaryByRule_QueryKeysOnly_Succeeds()
|
||||
{
|
||||
var param = new[] { "paramA", "paramB" };
|
||||
var queryKeys = new[] { "queryA", "queryB" };
|
||||
var cachedVaryByRule = new CachedVaryByRules()
|
||||
{
|
||||
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
|
||||
Params = param
|
||||
QueryKeys = queryKeys
|
||||
};
|
||||
|
||||
AssertCachedVaryByRuleEqual(cachedVaryByRule, (CachedVaryByRules)CacheEntrySerializer.Deserialize(CacheEntrySerializer.Serialize(cachedVaryByRule)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTrip_CachedVaryByRule_HeadersAndParams_Succeeds()
|
||||
public void RoundTrip_CachedVaryByRule_HeadersAndQueryKeys_Succeeds()
|
||||
{
|
||||
var headers = new[] { "headerA", "headerB" };
|
||||
var param = new[] { "paramA", "paramB" };
|
||||
var queryKeys = new[] { "queryA", "queryB" };
|
||||
var cachedVaryByRule = new CachedVaryByRules()
|
||||
{
|
||||
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
|
||||
Headers = headers,
|
||||
Params = param
|
||||
QueryKeys = queryKeys
|
||||
};
|
||||
|
||||
AssertCachedVaryByRuleEqual(cachedVaryByRule, (CachedVaryByRules)CacheEntrySerializer.Deserialize(CacheEntrySerializer.Serialize(cachedVaryByRule)));
|
||||
|
|
@ -176,7 +176,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
Assert.NotNull(expected);
|
||||
Assert.Equal(expected.VaryByKeyPrefix, actual.VaryByKeyPrefix);
|
||||
Assert.Equal(expected.Headers, actual.Headers);
|
||||
Assert.Equal(expected.Params, actual.Params);
|
||||
Assert.Equal(expected.QueryKeys, actual.QueryKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,71 +95,71 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesListedParamsOnly()
|
||||
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesListedQueryKeysOnly()
|
||||
{
|
||||
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
|
||||
var context = TestUtils.CreateTestContext();
|
||||
context.HttpContext.Request.QueryString = new QueryString("?ParamA=ValueA&ParamB=ValueB");
|
||||
context.HttpContext.Request.QueryString = new QueryString("?QueryA=ValueA&QueryB=ValueB");
|
||||
context.CachedVaryByRules = new CachedVaryByRules()
|
||||
{
|
||||
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
|
||||
Params = new string[] { "ParamA", "ParamC" }
|
||||
QueryKeys = new string[] { "QueryA", "QueryC" }
|
||||
};
|
||||
|
||||
Assert.Equal($"{context.CachedVaryByRules.VaryByKeyPrefix}{KeyDelimiter}Q{KeyDelimiter}ParamA=ValueA{KeyDelimiter}ParamC=",
|
||||
Assert.Equal($"{context.CachedVaryByRules.VaryByKeyPrefix}{KeyDelimiter}Q{KeyDelimiter}QueryA=ValueA{KeyDelimiter}QueryC=",
|
||||
cacheKeyProvider.CreateStorageVaryByKey(context));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesParams_ParamNameCaseInsensitive_UseParamCasing()
|
||||
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesQueryKeys_QueryKeyCaseInsensitive_UseQueryKeyCasing()
|
||||
{
|
||||
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
|
||||
var context = TestUtils.CreateTestContext();
|
||||
context.HttpContext.Request.QueryString = new QueryString("?parama=ValueA¶mB=ValueB");
|
||||
context.HttpContext.Request.QueryString = new QueryString("?queryA=ValueA&queryB=ValueB");
|
||||
context.CachedVaryByRules = new CachedVaryByRules()
|
||||
{
|
||||
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
|
||||
Params = new string[] { "ParamA", "ParamC" }
|
||||
QueryKeys = new string[] { "QueryA", "QueryC" }
|
||||
};
|
||||
|
||||
Assert.Equal($"{context.CachedVaryByRules.VaryByKeyPrefix}{KeyDelimiter}Q{KeyDelimiter}ParamA=ValueA{KeyDelimiter}ParamC=",
|
||||
Assert.Equal($"{context.CachedVaryByRules.VaryByKeyPrefix}{KeyDelimiter}Q{KeyDelimiter}QueryA=ValueA{KeyDelimiter}QueryC=",
|
||||
cacheKeyProvider.CreateStorageVaryByKey(context));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesAllQueryParamsGivenAsterisk()
|
||||
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesAllQueryKeysGivenAsterisk()
|
||||
{
|
||||
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
|
||||
var context = TestUtils.CreateTestContext();
|
||||
context.HttpContext.Request.QueryString = new QueryString("?ParamA=ValueA&ParamB=ValueB");
|
||||
context.HttpContext.Request.QueryString = new QueryString("?QueryA=ValueA&QueryB=ValueB");
|
||||
context.CachedVaryByRules = new CachedVaryByRules()
|
||||
{
|
||||
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
|
||||
Params = new string[] { "*" }
|
||||
QueryKeys = new string[] { "*" }
|
||||
};
|
||||
|
||||
// To support case insensitivity, all param keys are converted to upper case.
|
||||
// Explicit params uses the casing specified in the setting.
|
||||
Assert.Equal($"{context.CachedVaryByRules.VaryByKeyPrefix}{KeyDelimiter}Q{KeyDelimiter}PARAMA=ValueA{KeyDelimiter}PARAMB=ValueB",
|
||||
// To support case insensitivity, all query keys are converted to upper case.
|
||||
// Explicit query keys uses the casing specified in the setting.
|
||||
Assert.Equal($"{context.CachedVaryByRules.VaryByKeyPrefix}{KeyDelimiter}Q{KeyDelimiter}QUERYA=ValueA{KeyDelimiter}QUERYB=ValueB",
|
||||
cacheKeyProvider.CreateStorageVaryByKey(context));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesListedHeadersAndParams()
|
||||
public void ResponseCacheKeyProvider_CreateStorageVaryKey_IncludesListedHeadersAndQueryKeys()
|
||||
{
|
||||
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
|
||||
var context = TestUtils.CreateTestContext();
|
||||
context.HttpContext.Request.Headers["HeaderA"] = "ValueA";
|
||||
context.HttpContext.Request.Headers["HeaderB"] = "ValueB";
|
||||
context.HttpContext.Request.QueryString = new QueryString("?ParamA=ValueA&ParamB=ValueB");
|
||||
context.HttpContext.Request.QueryString = new QueryString("?QueryA=ValueA&QueryB=ValueB");
|
||||
context.CachedVaryByRules = new CachedVaryByRules()
|
||||
{
|
||||
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
|
||||
Headers = new string[] { "HeaderA", "HeaderC" },
|
||||
Params = new string[] { "ParamA", "ParamC" }
|
||||
QueryKeys = new string[] { "QueryA", "QueryC" }
|
||||
};
|
||||
|
||||
Assert.Equal($"{context.CachedVaryByRules.VaryByKeyPrefix}{KeyDelimiter}H{KeyDelimiter}HeaderA=ValueA{KeyDelimiter}HeaderC={KeyDelimiter}Q{KeyDelimiter}ParamA=ValueA{KeyDelimiter}ParamC=",
|
||||
Assert.Equal($"{context.CachedVaryByRules.VaryByKeyPrefix}{KeyDelimiter}H{KeyDelimiter}HeaderA=ValueA{KeyDelimiter}HeaderC={KeyDelimiter}Q{KeyDelimiter}QueryA=ValueA{KeyDelimiter}QueryC=",
|
||||
cacheKeyProvider.CreateStorageVaryByKey(context));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -292,7 +292,6 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
MaxAge = TimeSpan.FromSeconds(12)
|
||||
};
|
||||
|
||||
context.ResponseTime = DateTimeOffset.UtcNow;
|
||||
context.TypedResponseHeaders.Expires = context.ResponseTime + TimeSpan.FromSeconds(11);
|
||||
|
||||
await middleware.FinalizeCacheHeadersAsync(context);
|
||||
|
|
@ -311,7 +310,6 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
SharedMaxAge = TimeSpan.FromSeconds(13)
|
||||
};
|
||||
|
||||
context.ResponseTime = DateTimeOffset.UtcNow;
|
||||
context.TypedResponseHeaders.Expires = context.ResponseTime + TimeSpan.FromSeconds(11);
|
||||
|
||||
await middleware.FinalizeCacheHeadersAsync(context);
|
||||
|
|
@ -328,11 +326,11 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
|
||||
context.HttpContext.Response.Headers[HeaderNames.Vary] = new StringValues(new[] { "headerA", "HEADERB", "HEADERc" });
|
||||
context.HttpContext.AddResponseCacheFeature();
|
||||
context.HttpContext.GetResponseCacheFeature().VaryByParams = new StringValues(new[] { "paramB", "PARAMAA" });
|
||||
context.HttpContext.GetResponseCacheFeature().VaryByQueryKeys = new StringValues(new[] { "queryB", "QUERYA" });
|
||||
var cachedVaryByRules = new CachedVaryByRules()
|
||||
{
|
||||
Headers = new StringValues(new[] { "HeaderA", "HeaderB" }),
|
||||
Params = new StringValues(new[] { "ParamA", "ParamB" })
|
||||
QueryKeys = new StringValues(new[] { "QueryA", "QueryB" })
|
||||
};
|
||||
context.CachedVaryByRules = cachedVaryByRules;
|
||||
|
||||
|
|
@ -352,12 +350,12 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
|
||||
context.HttpContext.Response.Headers[HeaderNames.Vary] = new StringValues(new[] { "headerA", "HEADERB" });
|
||||
context.HttpContext.AddResponseCacheFeature();
|
||||
context.HttpContext.GetResponseCacheFeature().VaryByParams = new StringValues(new[] { "paramB", "PARAMA" });
|
||||
context.HttpContext.GetResponseCacheFeature().VaryByQueryKeys = new StringValues(new[] { "queryB", "QUERYA" });
|
||||
var cachedVaryByRules = new CachedVaryByRules()
|
||||
{
|
||||
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
|
||||
Headers = new StringValues(new[] { "HEADERA", "HEADERB" }),
|
||||
Params = new StringValues(new[] { "PARAMA", "PARAMB" })
|
||||
QueryKeys = new StringValues(new[] { "QUERYA", "QUERYB" })
|
||||
};
|
||||
context.CachedVaryByRules = cachedVaryByRules;
|
||||
|
||||
|
|
|
|||
|
|
@ -385,6 +385,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
var utcNow = DateTimeOffset.UtcNow;
|
||||
var context = TestUtils.CreateTestContext();
|
||||
context.ResponseTime = DateTimeOffset.MaxValue;
|
||||
context.CachedEntryAge = TimeSpan.MaxValue;
|
||||
context.CachedResponseHeaders = new ResponseHeaders(new HeaderDictionary());
|
||||
|
||||
Assert.True(new ResponseCachePolicyProvider().IsCachedEntryFresh(context));
|
||||
|
|
@ -396,6 +397,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
var utcNow = DateTimeOffset.UtcNow;
|
||||
var context = TestUtils.CreateTestContext();
|
||||
context.ResponseTime = DateTimeOffset.MaxValue;
|
||||
context.CachedEntryAge = TimeSpan.MaxValue;
|
||||
context.CachedResponseHeaders = new ResponseHeaders(new HeaderDictionary())
|
||||
{
|
||||
CacheControl = new CacheControlHeaderValue()
|
||||
|
|
@ -413,6 +415,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
var utcNow = DateTimeOffset.UtcNow;
|
||||
var context = TestUtils.CreateTestContext();
|
||||
context.ResponseTime = utcNow;
|
||||
context.CachedEntryAge = TimeSpan.Zero;
|
||||
context.CachedResponseHeaders = new ResponseHeaders(new HeaderDictionary())
|
||||
{
|
||||
CacheControl = new CacheControlHeaderValue()
|
||||
|
|
|
|||
|
|
@ -88,152 +88,152 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async void ServesCachedContent_IfVaryParams_Matches()
|
||||
public async void ServesCachedContent_IfVaryQueryKeys_Matches()
|
||||
{
|
||||
var builder = TestUtils.CreateBuilderWithResponseCache(requestDelegate: async (context) =>
|
||||
{
|
||||
context.GetResponseCacheFeature().VaryByParams = "param";
|
||||
context.GetResponseCacheFeature().VaryByQueryKeys = "query";
|
||||
await TestUtils.TestRequestDelegate(context);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var initialResponse = await client.GetAsync("?param=value");
|
||||
var subsequentResponse = await client.GetAsync("?param=value");
|
||||
var initialResponse = await client.GetAsync("?query=value");
|
||||
var subsequentResponse = await client.GetAsync("?query=value");
|
||||
|
||||
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ServesCachedContent_IfVaryParamsExplicit_Matches_ParamNameCaseInsensitive()
|
||||
public async void ServesCachedContent_IfVaryQueryKeysExplicit_Matches_QueryKeyCaseInsensitive()
|
||||
{
|
||||
var builder = TestUtils.CreateBuilderWithResponseCache(requestDelegate: async (context) =>
|
||||
{
|
||||
context.GetResponseCacheFeature().VaryByParams = new[] { "ParamA", "paramb" };
|
||||
context.GetResponseCacheFeature().VaryByQueryKeys = new[] { "QueryA", "queryb" };
|
||||
await TestUtils.TestRequestDelegate(context);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var initialResponse = await client.GetAsync("?parama=valuea¶mb=valueb");
|
||||
var subsequentResponse = await client.GetAsync("?ParamA=valuea&ParamB=valueb");
|
||||
var initialResponse = await client.GetAsync("?querya=valuea&queryb=valueb");
|
||||
var subsequentResponse = await client.GetAsync("?QueryA=valuea&QueryB=valueb");
|
||||
|
||||
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ServesCachedContent_IfVaryParamsStar_Matches_ParamNameCaseInsensitive()
|
||||
public async void ServesCachedContent_IfVaryQueryKeyStar_Matches_QueryKeyCaseInsensitive()
|
||||
{
|
||||
var builder = TestUtils.CreateBuilderWithResponseCache(requestDelegate: async (context) =>
|
||||
{
|
||||
context.GetResponseCacheFeature().VaryByParams = new[] { "*" };
|
||||
context.GetResponseCacheFeature().VaryByQueryKeys = new[] { "*" };
|
||||
await TestUtils.TestRequestDelegate(context);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var initialResponse = await client.GetAsync("?parama=valuea¶mb=valueb");
|
||||
var subsequentResponse = await client.GetAsync("?ParamA=valuea&ParamB=valueb");
|
||||
var initialResponse = await client.GetAsync("?querya=valuea&queryb=valueb");
|
||||
var subsequentResponse = await client.GetAsync("?QueryA=valuea&QueryB=valueb");
|
||||
|
||||
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ServesCachedContent_IfVaryParamsExplicit_Matches_OrderInsensitive()
|
||||
public async void ServesCachedContent_IfVaryQueryKeyExplicit_Matches_OrderInsensitive()
|
||||
{
|
||||
var builder = TestUtils.CreateBuilderWithResponseCache(requestDelegate: async (context) =>
|
||||
{
|
||||
context.GetResponseCacheFeature().VaryByParams = new[] { "ParamB", "ParamA" };
|
||||
context.GetResponseCacheFeature().VaryByQueryKeys = new[] { "QueryB", "QueryA" };
|
||||
await TestUtils.TestRequestDelegate(context);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var initialResponse = await client.GetAsync("?ParamA=ValueA&ParamB=ValueB");
|
||||
var subsequentResponse = await client.GetAsync("?ParamB=ValueB&ParamA=ValueA");
|
||||
var initialResponse = await client.GetAsync("?QueryA=ValueA&QueryB=ValueB");
|
||||
var subsequentResponse = await client.GetAsync("?QueryB=ValueB&QueryA=ValueA");
|
||||
|
||||
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ServesCachedContent_IfVaryParamsStar_Matches_OrderInsensitive()
|
||||
public async void ServesCachedContent_IfVaryQueryKeyStar_Matches_OrderInsensitive()
|
||||
{
|
||||
var builder = TestUtils.CreateBuilderWithResponseCache(requestDelegate: async (context) =>
|
||||
{
|
||||
context.GetResponseCacheFeature().VaryByParams = new[] { "*" };
|
||||
context.GetResponseCacheFeature().VaryByQueryKeys = new[] { "*" };
|
||||
await TestUtils.TestRequestDelegate(context);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var initialResponse = await client.GetAsync("?ParamA=ValueA&ParamB=ValueB");
|
||||
var subsequentResponse = await client.GetAsync("?ParamB=ValueB&ParamA=ValueA");
|
||||
var initialResponse = await client.GetAsync("?QueryA=ValueA&QueryB=ValueB");
|
||||
var subsequentResponse = await client.GetAsync("?QueryB=ValueB&QueryA=ValueA");
|
||||
|
||||
await AssertResponseCachedAsync(initialResponse, subsequentResponse);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ServesFreshContent_IfVaryParams_Mismatches()
|
||||
public async void ServesFreshContent_IfVaryQueryKey_Mismatches()
|
||||
{
|
||||
var builder = TestUtils.CreateBuilderWithResponseCache(requestDelegate: async (context) =>
|
||||
{
|
||||
context.GetResponseCacheFeature().VaryByParams = "param";
|
||||
context.GetResponseCacheFeature().VaryByQueryKeys = "query";
|
||||
await TestUtils.TestRequestDelegate(context);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var initialResponse = await client.GetAsync("?param=value");
|
||||
var subsequentResponse = await client.GetAsync("?param=value2");
|
||||
var initialResponse = await client.GetAsync("?query=value");
|
||||
var subsequentResponse = await client.GetAsync("?query=value2");
|
||||
|
||||
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ServesFreshContent_IfVaryParamsExplicit_Mismatch_ParamValueCaseSensitive()
|
||||
public async void ServesFreshContent_IfVaryQueryKeyExplicit_Mismatch_QueryKeyCaseSensitive()
|
||||
{
|
||||
var builder = TestUtils.CreateBuilderWithResponseCache(requestDelegate: async (context) =>
|
||||
{
|
||||
context.GetResponseCacheFeature().VaryByParams = new[] { "ParamA", "ParamB" };
|
||||
context.GetResponseCacheFeature().VaryByQueryKeys = new[] { "QueryA", "QueryB" };
|
||||
await TestUtils.TestRequestDelegate(context);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var initialResponse = await client.GetAsync("?parama=valuea¶mb=valueb");
|
||||
var subsequentResponse = await client.GetAsync("?parama=ValueA¶mb=ValueB");
|
||||
var initialResponse = await client.GetAsync("?querya=valuea&queryb=valueb");
|
||||
var subsequentResponse = await client.GetAsync("?querya=ValueA&queryb=ValueB");
|
||||
|
||||
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ServesFreshContent_IfVaryParamsStar_Mismatch_ParamValueCaseSensitive()
|
||||
public async void ServesFreshContent_IfVaryQueryKeyStar_Mismatch_QueryKeyValueCaseSensitive()
|
||||
{
|
||||
var builder = TestUtils.CreateBuilderWithResponseCache(requestDelegate: async (context) =>
|
||||
{
|
||||
context.GetResponseCacheFeature().VaryByParams = new[] { "*" };
|
||||
context.GetResponseCacheFeature().VaryByQueryKeys = new[] { "*" };
|
||||
await TestUtils.TestRequestDelegate(context);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var initialResponse = await client.GetAsync("?parama=valuea¶mb=valueb");
|
||||
var subsequentResponse = await client.GetAsync("?parama=ValueA¶mb=ValueB");
|
||||
var initialResponse = await client.GetAsync("?querya=valuea&queryb=valueb");
|
||||
var subsequentResponse = await client.GetAsync("?querya=ValueA&queryb=ValueB");
|
||||
|
||||
await AssertResponseNotCachedAsync(initialResponse, subsequentResponse);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,10 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
|
|||
|
||||
internal static ResponseCacheContext CreateTestContext()
|
||||
{
|
||||
return new ResponseCacheContext(new DefaultHttpContext());
|
||||
return new ResponseCacheContext(new DefaultHttpContext())
|
||||
{
|
||||
ResponseTime = DateTimeOffset.UtcNow
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue