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

Commit 4f61c65

Browse files
committed
Update no-store behaviour
1 parent 62aabc1 commit 4f61c65

File tree

3 files changed

+116
-9
lines changed

3 files changed

+116
-9
lines changed

src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingContext.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ internal bool RequestIsCacheable()
212212
// TODO: no-cache requests can be retrieved upon validation with origin
213213
if (!string.IsNullOrEmpty(request.Headers[HeaderNames.CacheControl]))
214214
{
215-
if (RequestCacheControl.NoCache || RequestCacheControl.NoStore)
215+
if (RequestCacheControl.NoCache)
216216
{
217217
return false;
218218
}
@@ -244,7 +244,7 @@ internal bool ResponseIsCacheable()
244244
}
245245

246246
// Check no-store
247-
if (ResponseCacheControl.NoStore)
247+
if (RequestCacheControl.NoStore || ResponseCacheControl.NoStore)
248248
{
249249
return false;
250250
}

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

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,34 @@ public void RequestIsCacheable_AuthorizationHeaders_NotAllowed()
5757
Assert.False(context.RequestIsCacheable());
5858
}
5959

60-
[Theory]
61-
[InlineData("no-cache")]
62-
[InlineData("no-store")]
63-
[InlineData("no-cache, no-store")]
64-
public void RequestIsCacheable_ExplicitDisablingDirectives_NotAllowed(string directive)
60+
[Fact]
61+
public void RequestIsCacheable_NoCache_NotAllowed()
6562
{
6663
var httpContext = new DefaultHttpContext();
6764
httpContext.Request.Method = "GET";
68-
httpContext.Request.Headers[HeaderNames.CacheControl] = directive;
65+
httpContext.Request.GetTypedHeaders().CacheControl = new CacheControlHeaderValue()
66+
{
67+
NoCache = true
68+
};
6969
var context = new ResponseCachingContext(httpContext, new TestResponseCache());
7070

7171
Assert.False(context.RequestIsCacheable());
7272
}
7373

74+
[Fact]
75+
public void RequestIsCacheable_NoStore_Allowed()
76+
{
77+
var httpContext = new DefaultHttpContext();
78+
httpContext.Request.Method = "GET";
79+
httpContext.Request.GetTypedHeaders().CacheControl = new CacheControlHeaderValue()
80+
{
81+
NoStore = true
82+
};
83+
var context = new ResponseCachingContext(httpContext, new TestResponseCache());
84+
85+
Assert.True(context.RequestIsCacheable());
86+
}
87+
7488
[Fact]
7589
public void RequestIsCacheable_LegacyDirectives_NotAllowed()
7690
{
@@ -162,7 +176,24 @@ public void ResponseIsCacheable_NoCache_NotAllowed()
162176
}
163177

164178
[Fact]
165-
public void ResponseIsCacheable_NoStore_NotAllowed()
179+
public void ResponseIsCacheable_RequestNoStore_NotAllowed()
180+
{
181+
var httpContext = new DefaultHttpContext();
182+
httpContext.Request.GetTypedHeaders().CacheControl = new CacheControlHeaderValue()
183+
{
184+
NoStore = true
185+
};
186+
httpContext.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue()
187+
{
188+
Public = true
189+
};
190+
var context = new ResponseCachingContext(httpContext, new TestResponseCache());
191+
192+
Assert.False(context.ResponseIsCacheable());
193+
}
194+
195+
[Fact]
196+
public void ResponseIsCacheable_ResponseNoStore_NotAllowed()
166197
{
167198
var httpContext = new DefaultHttpContext();
168199
httpContext.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue()

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

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,82 @@ public async void ServesFreshContentIfIHttpSendFileFeatureUsed()
347347
}
348348
}
349349

350+
[Fact]
351+
public async void ServesCachedContentIfSubsequentRequestContainsNoStore()
352+
{
353+
var builder = CreateBuilderWithResponseCaching(
354+
async (context) =>
355+
{
356+
var uniqueId = Guid.NewGuid().ToString();
357+
var headers = context.Response.GetTypedHeaders();
358+
headers.CacheControl = new CacheControlHeaderValue()
359+
{
360+
Public = true,
361+
MaxAge = TimeSpan.FromSeconds(10)
362+
};
363+
headers.Date = DateTimeOffset.UtcNow;
364+
headers.Headers["X-Value"] = uniqueId;
365+
await context.Response.WriteAsync(uniqueId);
366+
});
367+
368+
using (var server = new TestServer(builder))
369+
{
370+
var client = server.CreateClient();
371+
var initialResponse = await client.GetAsync("");
372+
client.DefaultRequestHeaders.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue()
373+
{
374+
NoStore = true
375+
};
376+
var subsequentResponse = await client.GetAsync("");
377+
378+
initialResponse.EnsureSuccessStatusCode();
379+
subsequentResponse.EnsureSuccessStatusCode();
380+
381+
foreach (var header in initialResponse.Headers)
382+
{
383+
Assert.Equal(initialResponse.Headers.GetValues(header.Key), subsequentResponse.Headers.GetValues(header.Key));
384+
}
385+
Assert.True(subsequentResponse.Headers.Contains(HeaderNames.Age));
386+
Assert.Equal(await initialResponse.Content.ReadAsStringAsync(), await subsequentResponse.Content.ReadAsStringAsync());
387+
}
388+
}
389+
390+
[Fact]
391+
public async void ServesFreshContentIfInitialRequestContainsNoStore()
392+
{
393+
var builder = CreateBuilderWithResponseCaching(
394+
async (context) =>
395+
{
396+
var uniqueId = Guid.NewGuid().ToString();
397+
var headers = context.Response.GetTypedHeaders();
398+
headers.CacheControl = new CacheControlHeaderValue()
399+
{
400+
Public = true,
401+
MaxAge = TimeSpan.FromSeconds(10)
402+
};
403+
headers.Date = DateTimeOffset.UtcNow;
404+
headers.Headers["X-Value"] = uniqueId;
405+
await context.Response.WriteAsync(uniqueId);
406+
});
407+
408+
using (var server = new TestServer(builder))
409+
{
410+
var client = server.CreateClient();
411+
client.DefaultRequestHeaders.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue()
412+
{
413+
NoStore = true
414+
};
415+
var initialResponse = await client.GetAsync("");
416+
var subsequentResponse = await client.GetAsync("");
417+
418+
initialResponse.EnsureSuccessStatusCode();
419+
subsequentResponse.EnsureSuccessStatusCode();
420+
421+
Assert.False(subsequentResponse.Headers.Contains(HeaderNames.Age));
422+
Assert.NotEqual(await initialResponse.Content.ReadAsStringAsync(), await subsequentResponse.Content.ReadAsStringAsync());
423+
}
424+
}
425+
350426
private static IWebHostBuilder CreateBuilderWithResponseCaching(RequestDelegate requestDelegate) =>
351427
CreateBuilderWithResponseCaching(app => { }, requestDelegate);
352428

0 commit comments

Comments
 (0)