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

Commit 36a247c

Browse files
committed
Update cache key delimiter
1 parent 0256853 commit 36a247c

File tree

2 files changed

+28
-13
lines changed

2 files changed

+28
-13
lines changed

src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingContext.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace Microsoft.AspNetCore.ResponseCaching
2020
internal class ResponseCachingContext
2121
{
2222
private static readonly CacheControlHeaderValue EmptyCacheControl = new CacheControlHeaderValue();
23+
private static readonly char KeyDelimiter = '\x1e'; // Use the record separator for delimiting components of the cache key
2324

2425
private readonly HttpContext _httpContext;
2526
private readonly IResponseCache _cache;
@@ -154,12 +155,16 @@ internal string CreateCacheKey(CachedVaryBy varyBy)
154155
// Default key
155156
builder
156157
.Append(request.Method.ToUpperInvariant())
157-
.Append(";")
158+
.Append(KeyDelimiter)
158159
.Append(request.Path.Value.ToUpperInvariant());
159160

160161
// Vary by headers
161162
if (varyBy?.Headers.Count > 0)
162163
{
164+
// Append a value denoting the start of the header segment of the cache key
165+
builder.Append(KeyDelimiter)
166+
.Append('H');
167+
163168
// TODO: resolve key format and delimiters
164169
foreach (var header in varyBy.Headers)
165170
{
@@ -172,7 +177,7 @@ internal string CreateCacheKey(CachedVaryBy varyBy)
172177
value = "null";
173178
}
174179

175-
builder.Append(";")
180+
builder.Append(KeyDelimiter)
176181
.Append(header)
177182
.Append("=")
178183
.Append(value);
@@ -182,12 +187,16 @@ internal string CreateCacheKey(CachedVaryBy varyBy)
182187
// Vary by query params
183188
if (varyBy?.Params.Count > 0)
184189
{
185-
if (varyBy.Params.Count == 1 && string.Equals(varyBy.Params[0], "*", StringComparison.OrdinalIgnoreCase))
190+
// Append a value denoting the start of the query parameter segment of the cache key
191+
builder.Append(KeyDelimiter)
192+
.Append('Q');
193+
194+
if (varyBy.Params.Count == 1 && string.Equals(varyBy.Params[0], "*"))
186195
{
187196
// Vary by all available query params
188197
foreach (var query in _httpContext.Request.Query.OrderBy(q => q.Key))
189198
{
190-
builder.Append(";")
199+
builder.Append(KeyDelimiter)
191200
.Append(query.Key.ToLower())
192201
.Append("=")
193202
.Append(query.Value);
@@ -207,7 +216,7 @@ internal string CreateCacheKey(CachedVaryBy varyBy)
207216
value = "null";
208217
}
209218

210-
builder.Append(";")
219+
builder.Append(KeyDelimiter)
211220
.Append(param)
212221
.Append("=")
213222
.Append(value);
@@ -219,7 +228,11 @@ internal string CreateCacheKey(CachedVaryBy varyBy)
219228
var customKey = _cacheKeySuffixProvider.CreateCustomKeySuffix(_httpContext);
220229
if (!string.IsNullOrEmpty(customKey))
221230
{
222-
builder.Append(";")
231+
// Append a value denoting the start of the query parameter segment of the cache key
232+
builder.Append(KeyDelimiter)
233+
.Append('C');
234+
235+
builder.Append(KeyDelimiter)
223236
.Append(customKey);
224237
}
225238

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ namespace Microsoft.AspNetCore.ResponseCaching.Tests
1717
{
1818
public class ResponseCachingContextTests
1919
{
20+
private static readonly char KeyDelimiter = '\x1e';
21+
2022
[Theory]
2123
[InlineData("GET")]
2224
[InlineData("HEAD")]
@@ -171,7 +173,7 @@ public void CreateCacheKey_Includes_UppercaseMethodAndPath()
171173
httpContext.Request.QueryString = new QueryString("?query.Key=a&query.Value=b");
172174
var context = CreateTestContext(httpContext);
173175

174-
Assert.Equal("HEAD;/PATH/SUBPATH", context.CreateCacheKey());
176+
Assert.Equal($"HEAD{KeyDelimiter}/PATH/SUBPATH", context.CreateCacheKey());
175177
}
176178

177179
[Fact]
@@ -184,7 +186,7 @@ public void CreateCacheKey_Includes_ListedVaryByHeadersOnly()
184186
httpContext.Request.Headers["HeaderB"] = "ValueB";
185187
var context = CreateTestContext(httpContext);
186188

187-
Assert.Equal("GET;/;HeaderA=ValueA;HeaderC=null", context.CreateCacheKey(new CachedVaryBy()
189+
Assert.Equal($"GET{KeyDelimiter}/{KeyDelimiter}H{KeyDelimiter}HeaderA=ValueA{KeyDelimiter}HeaderC=null", context.CreateCacheKey(new CachedVaryBy()
188190
{
189191
Headers = new string[] { "HeaderA", "HeaderC" }
190192
}));
@@ -199,7 +201,7 @@ public void CreateCacheKey_Includes_ListedVaryByParamsOnly()
199201
httpContext.Request.QueryString = new QueryString("?ParamA=ValueA&ParamB=ValueB");
200202
var context = CreateTestContext(httpContext);
201203

202-
Assert.Equal("GET;/;ParamA=ValueA;ParamC=null", context.CreateCacheKey(new CachedVaryBy()
204+
Assert.Equal($"GET{KeyDelimiter}/{KeyDelimiter}Q{KeyDelimiter}ParamA=ValueA{KeyDelimiter}ParamC=null", context.CreateCacheKey(new CachedVaryBy()
203205
{
204206
Params = new string[] { "ParamA", "ParamC" }
205207
}));
@@ -214,7 +216,7 @@ public void CreateCacheKey_Includes_VaryByParams_ParamNameCaseInsensitive_UseVar
214216
httpContext.Request.QueryString = new QueryString("?parama=ValueA&paramB=ValueB");
215217
var context = CreateTestContext(httpContext);
216218

217-
Assert.Equal("GET;/;ParamA=ValueA;ParamC=null", context.CreateCacheKey(new CachedVaryBy()
219+
Assert.Equal($"GET{KeyDelimiter}/{KeyDelimiter}Q{KeyDelimiter}ParamA=ValueA{KeyDelimiter}ParamC=null", context.CreateCacheKey(new CachedVaryBy()
218220
{
219221
Params = new string[] { "ParamA", "ParamC" }
220222
}));
@@ -231,7 +233,7 @@ public void CreateCacheKey_Includes_AllQueryParamsGivenAsterisk()
231233

232234
// To support case insensitivity, all param keys are converted to lower case.
233235
// Explicit VaryBy uses the casing specified in the setting.
234-
Assert.Equal("GET;/;parama=ValueA;paramb=ValueB", context.CreateCacheKey(new CachedVaryBy()
236+
Assert.Equal($"GET{KeyDelimiter}/{KeyDelimiter}Q{KeyDelimiter}parama=ValueA{KeyDelimiter}paramb=ValueB", context.CreateCacheKey(new CachedVaryBy()
235237
{
236238
Params = new string[] { "*" }
237239
}));
@@ -248,7 +250,7 @@ public void CreateCacheKey_Includes_ListedVaryByHeadersAndParams()
248250
httpContext.Request.QueryString = new QueryString("?ParamA=ValueA&ParamB=ValueB");
249251
var context = CreateTestContext(httpContext);
250252

251-
Assert.Equal("GET;/;HeaderA=ValueA;HeaderC=null;ParamA=ValueA;ParamC=null", context.CreateCacheKey(new CachedVaryBy()
253+
Assert.Equal($"GET{KeyDelimiter}/{KeyDelimiter}H{KeyDelimiter}HeaderA=ValueA{KeyDelimiter}HeaderC=null{KeyDelimiter}Q{KeyDelimiter}ParamA=ValueA{KeyDelimiter}ParamC=null", context.CreateCacheKey(new CachedVaryBy()
252254
{
253255
Headers = new string[] { "HeaderA", "HeaderC" },
254256
Params = new string[] { "ParamA", "ParamC" }
@@ -270,7 +272,7 @@ public void CreateCacheKey_OptionalCacheKey_AppendedToDefaultKey()
270272
httpContext.Request.Headers["HeaderB"] = "ValueB";
271273
var responseCachingContext = CreateTestContext(httpContext, new CustomizeKeySuffixProvider());
272274

273-
Assert.Equal("GET;/;HeaderA=ValueA;HeaderC=null;CustomizedKey", responseCachingContext.CreateCacheKey(new CachedVaryBy()
275+
Assert.Equal($"GET{KeyDelimiter}/{KeyDelimiter}H{KeyDelimiter}HeaderA=ValueA{KeyDelimiter}HeaderC=null{KeyDelimiter}C{KeyDelimiter}CustomizedKey", responseCachingContext.CreateCacheKey(new CachedVaryBy()
274276
{
275277
Headers = new string[] { "HeaderA", "HeaderC" }
276278
}));

0 commit comments

Comments
 (0)