Delimit key values for query strings

This commit is contained in:
John Luo 2018-02-21 15:03:55 -08:00
parent 3e0e1ed24b
commit c29531f2eb
2 changed files with 29 additions and 0 deletions

View File

@ -15,6 +15,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
{
// Use the record separator for delimiting components of the cache key to avoid possible collisions
private static readonly char KeyDelimiter = '\x1e';
// Use the unit separator for delimiting subcomponents of the cache key to avoid possible collisions
private static readonly char KeySubDelimiter = '\x1f';
private readonly ObjectPool<StringBuilder> _builderPool;
private readonly ResponseCachingOptions _options;
@ -147,6 +149,10 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
for (var i = 0; i < query.Value.Count; i++)
{
if (i > 0)
{
builder.Append(KeySubDelimiter);
}
builder.Append(query.Value[i]);
}
}
@ -163,6 +169,10 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
for (var j = 0; j < queryKeyValues.Count; j++)
{
if (j > 0)
{
builder.Append(KeySubDelimiter);
}
builder.Append(queryKeyValues[j]);
}
}

View File

@ -11,6 +11,7 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
public class ResponseCachingKeyProviderTests
{
private static readonly char KeyDelimiter = '\x1e';
private static readonly char KeySubDelimiter = '\x1f';
[Fact]
public void ResponseCachingKeyProvider_CreateStorageBaseKey_IncludesOnlyNormalizedMethodSchemeHostPortAndPath()
@ -143,6 +144,24 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
cacheKeyProvider.CreateStorageVaryByKey(context));
}
[Fact]
public void ResponseCachingKeyProvider_CreateStorageVaryKey_QueryKeysValuesNotConsolidated()
{
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
var context = TestUtils.CreateTestContext();
context.HttpContext.Request.QueryString = new QueryString("?QueryA=ValueA&QueryA=ValueB");
context.CachedVaryByRules = new CachedVaryByRules()
{
VaryByKeyPrefix = FastGuid.NewGuid().IdString,
QueryKeys = new string[] { "*" }
};
// 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{KeySubDelimiter}ValueB",
cacheKeyProvider.CreateStorageVaryByKey(context));
}
[Fact]
public void ResponseCachingKeyProvider_CreateStorageVaryKey_IncludesListedHeadersAndQueryKeys()
{