Skip to content
This repository was archived by the owner on Nov 22, 2018. It is now read-only.

Commit 2adda71

Browse files
JunTaoLuoJohn Luo
authored andcommitted
Update base key
- Add Scheme, Host, Port and PathBase
1 parent d4606fe commit 2adda71

File tree

3 files changed

+66
-15
lines changed

3 files changed

+66
-15
lines changed

src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCachingKeyProvider.cs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,22 @@ namespace Microsoft.AspNetCore.ResponseCaching.Internal
1313
{
1414
public class ResponseCachingKeyProvider : IResponseCachingKeyProvider
1515
{
16+
private const string UseMethodPathCacheKeySwitch = "Switch.Microsoft.AspNetCore.ResponseCaching.UseMethodPathCacheKey";
17+
1618
// Use the record separator for delimiting components of the cache key to avoid possible collisions
1719
private static readonly char KeyDelimiter = '\x1e';
1820

1921
private readonly ObjectPool<StringBuilder> _builderPool;
2022
private readonly ResponseCachingOptions _options;
2123

24+
internal bool UseMethodPathCacheKey { get; set; }
25+
2226
public ResponseCachingKeyProvider(ObjectPoolProvider poolProvider, IOptions<ResponseCachingOptions> options)
2327
{
28+
var isEnabled = false;
29+
AppContext.TryGetSwitch(UseMethodPathCacheKeySwitch, out isEnabled);
30+
UseMethodPathCacheKey = isEnabled;
31+
2432
if (poolProvider == null)
2533
{
2634
throw new ArgumentNullException(nameof(poolProvider));
@@ -39,7 +47,7 @@ public IEnumerable<string> CreateLookupVaryByKeys(ResponseCachingContext context
3947
return new string[] { CreateStorageVaryByKey(context) };
4048
}
4149

42-
// GET<delimiter>/PATH
50+
// GET<delimiter>SCHEME<delimiter>HOST:PORT/PATHBASE/PATH
4351
public string CreateBaseKey(ResponseCachingContext context)
4452
{
4553
if (context == null)
@@ -52,17 +60,42 @@ public string CreateBaseKey(ResponseCachingContext context)
5260

5361
try
5462
{
55-
builder
56-
.AppendUpperInvariant(request.Method)
57-
.Append(KeyDelimiter);
58-
59-
if (_options.UseCaseSensitivePaths)
63+
if (UseMethodPathCacheKey)
6064
{
61-
builder.Append(request.Path.Value);
65+
builder
66+
.AppendUpperInvariant(request.Method)
67+
.Append(KeyDelimiter);
68+
69+
if (_options.UseCaseSensitivePaths)
70+
{
71+
builder.Append(request.Path.Value);
72+
}
73+
else
74+
{
75+
builder.AppendUpperInvariant(request.Path.Value);
76+
}
6277
}
6378
else
6479
{
65-
builder.AppendUpperInvariant(request.Path.Value);
80+
builder
81+
.AppendUpperInvariant(request.Method)
82+
.Append(KeyDelimiter)
83+
.AppendUpperInvariant(request.Scheme)
84+
.Append(KeyDelimiter)
85+
.AppendUpperInvariant(request.Host.Value);
86+
87+
if (_options.UseCaseSensitivePaths)
88+
{
89+
builder
90+
.Append(request.PathBase.Value)
91+
.Append(request.Path.Value);
92+
}
93+
else
94+
{
95+
builder
96+
.AppendUpperInvariant(request.PathBase.Value)
97+
.AppendUpperInvariant(request.Path.Value);
98+
}
6699
}
67100

68101
return builder.ToString();

src/Microsoft.AspNetCore.ResponseCaching/Internal/StringBuilderExtensions.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
54
using System.Text;
65

76
namespace Microsoft.AspNetCore.ResponseCaching.Internal
@@ -10,10 +9,13 @@ internal static class StringBuilderExtensions
109
{
1110
internal static StringBuilder AppendUpperInvariant(this StringBuilder builder, string value)
1211
{
13-
builder.EnsureCapacity(builder.Length + value.Length);
14-
for (var i = 0; i < value.Length; i++)
12+
if (!string.IsNullOrEmpty(value))
1513
{
16-
builder.Append(char.ToUpperInvariant(value[i]));
14+
builder.EnsureCapacity(builder.Length + value.Length);
15+
for (var i = 0; i < value.Length; i++)
16+
{
17+
builder.Append(char.ToUpperInvariant(value[i]));
18+
}
1719
}
1820

1921
return builder;

test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachingKeyProviderTests.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class ResponseCachingKeyProviderTests
1313
private static readonly char KeyDelimiter = '\x1e';
1414

1515
[Fact]
16-
public void ResponseCachingKeyProvider_CreateStorageBaseKey_IncludesOnlyNormalizedMethodAndPath()
16+
public void ResponseCachingKeyProvider_CreateStorageBaseKey_IncludesOnlyNormalizedMethodSchemeHostPortAndPath()
1717
{
1818
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
1919
var context = TestUtils.CreateTestContext();
@@ -24,6 +24,22 @@ public void ResponseCachingKeyProvider_CreateStorageBaseKey_IncludesOnlyNormaliz
2424
context.HttpContext.Request.PathBase = "/pathBase";
2525
context.HttpContext.Request.QueryString = new QueryString("?query.Key=a&query.Value=b");
2626

27+
Assert.Equal($"HEAD{KeyDelimiter}HTTPS{KeyDelimiter}EXAMPLE.COM:80/PATHBASE/PATH/SUBPATH", cacheKeyProvider.CreateBaseKey(context));
28+
}
29+
30+
[Fact]
31+
public void ResponseCachingKeyProvider_CreateStorageBaseKey_IncludesOnlyNormalizedMethodAndPath_InQuirkMode()
32+
{
33+
var cacheKeyProvider = TestUtils.CreateTestKeyProvider();
34+
((ResponseCachingKeyProvider)cacheKeyProvider).UseMethodPathCacheKey = true;
35+
var context = TestUtils.CreateTestContext();
36+
context.HttpContext.Request.Method = "head";
37+
context.HttpContext.Request.Path = "/path/subpath";
38+
context.HttpContext.Request.Scheme = "https";
39+
context.HttpContext.Request.Host = new HostString("example.com", 80);
40+
context.HttpContext.Request.PathBase = "/pathBase";
41+
context.HttpContext.Request.QueryString = new QueryString("?query.Key=a&query.Value=b");
42+
2743
Assert.Equal($"HEAD{KeyDelimiter}/PATH/SUBPATH", cacheKeyProvider.CreateBaseKey(context));
2844
}
2945

@@ -38,7 +54,7 @@ public void ResponseCachingKeyProvider_CreateStorageBaseKey_CaseInsensitivePath_
3854
context.HttpContext.Request.Method = HttpMethods.Get;
3955
context.HttpContext.Request.Path = "/Path";
4056

41-
Assert.Equal($"{HttpMethods.Get}{KeyDelimiter}/PATH", cacheKeyProvider.CreateBaseKey(context));
57+
Assert.Equal($"{HttpMethods.Get}{KeyDelimiter}{KeyDelimiter}/PATH", cacheKeyProvider.CreateBaseKey(context));
4258
}
4359

4460
[Fact]
@@ -52,7 +68,7 @@ public void ResponseCachingKeyProvider_CreateStorageBaseKey_CaseSensitivePath_Pr
5268
context.HttpContext.Request.Method = HttpMethods.Get;
5369
context.HttpContext.Request.Path = "/Path";
5470

55-
Assert.Equal($"{HttpMethods.Get}{KeyDelimiter}/Path", cacheKeyProvider.CreateBaseKey(context));
71+
Assert.Equal($"{HttpMethods.Get}{KeyDelimiter}{KeyDelimiter}/Path", cacheKeyProvider.CreateBaseKey(context));
5672
}
5773

5874
[Fact]

0 commit comments

Comments
 (0)