Skip to content

Commit 4d32718

Browse files
committed
Added support for skipping the cache - also following Response header Cache-Control
1 parent 41095f7 commit 4d32718

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

HttpClient.Caching/InMemory/InMemoryCacheHandler.cs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,26 @@ namespace Microsoft.Extensions.Caching.InMemory
1414
/// </summary>
1515
public class InMemoryCacheHandler : DelegatingHandler
1616
{
17+
#if NET5_0_OR_GREATER
18+
/// <summary>
19+
/// The key to use to store the UseCache value in the HttpRequestMessage.Options dictionary.
20+
/// This key is used to determine if the cache should be checked for the request.
21+
/// If the key is not present, the cache will be checked.
22+
/// If the key is present and the value is false, the cache will not be checked.
23+
/// If the key is present and the value is true, the cache will be checked.
24+
/// </summary>
25+
public readonly static HttpRequestOptionsKey<bool> UseCache = new("UseCache");
26+
#else
27+
/// <summary>
28+
/// The key to use to store the UseCache value in the HttpRequestMessage.Properties dictionary.
29+
/// This key is used to determine if the cache should be checked for the request.
30+
/// If the key is not present, the cache will be checked.
31+
/// If the key is present and the value is false, the cache will not be checked.
32+
/// If the key is present and the value is true, the cache will be checked.
33+
/// </summary>
34+
public const string UseCache = "UseCache";
35+
#endif
36+
1737
private static HashSet<HttpMethod> CachedHttpMethods = new HashSet<HttpMethod>
1838
{
1939
HttpMethod.Get,
@@ -104,6 +124,37 @@ public void InvalidateCache(Uri uri, HttpMethod httpMethod = null)
104124
}
105125
}
106126

127+
/// <summary>
128+
/// Determines if the cache should be checked for the request.
129+
/// </summary>
130+
/// <param name="request"></param>
131+
/// <returns>A bool representing if the cache should be cached or not</returns>
132+
private bool ShouldTheCacheBeChecked(HttpRequestMessage request)
133+
{
134+
#if NET5_0_OR_GREATER
135+
return request.Options.TryGetValue(UseCache, out bool useCache) == false || useCache == true;
136+
#else
137+
return request.Properties.TryGetValue(UseCache, out var useCache) == false || (bool)useCache == true;
138+
#endif
139+
}
140+
141+
/// <summary>
142+
/// Determines if the response should be cached.
143+
/// </summary>
144+
/// <param name="response"></param>
145+
/// <returns>A bool representing if the response should be cached or not</returns>
146+
private bool ShouldCacheResponse(HttpResponseMessage response)
147+
{
148+
if (response.Headers.CacheControl is not null)
149+
{
150+
return response.Headers.CacheControl.NoStore == false
151+
&& response.Headers.CacheControl.NoCache == false
152+
&& response.StatusCode != HttpStatusCode.NotModified;
153+
}
154+
155+
return response.StatusCode != HttpStatusCode.NotModified;
156+
}
157+
107158
/// <summary>
108159
/// Tries to get the value from the cache, and only calls the delegating handler on cache misses.
109160
/// </summary>
@@ -114,7 +165,9 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
114165

115166
// Gets the data from cache, and returns the data if it's a cache hit
116167
var isCachedHttpMethod = CachedHttpMethods.Contains(request.Method);
117-
if (isCachedHttpMethod)
168+
// Check if the cache should be checked
169+
var shouldCheckCache = this.ShouldTheCacheBeChecked(request);
170+
if (shouldCheckCache && isCachedHttpMethod)
118171
{
119172
key = this.CacheKeysProvider.GetKey(request);
120173

@@ -134,7 +187,7 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
134187

135188
this.StatsProvider.ReportCacheMiss(response.StatusCode);
136189

137-
if (TimeSpan.Zero != absoluteExpirationRelativeToNow)
190+
if (this.ShouldCacheResponse(response) && TimeSpan.Zero != absoluteExpirationRelativeToNow)
138191
{
139192
var entry = await response.ToCacheEntryAsync();
140193
await this.responseCache.TrySetAsync(key, entry, absoluteExpirationRelativeToNow);
@@ -153,7 +206,9 @@ protected override HttpResponseMessage Send(HttpRequestMessage request, Cancella
153206

154207
// Gets the data from cache, and returns the data if it's a cache hit
155208
var isCachedHttpMethod = CachedHttpMethods.Contains(request.Method);
156-
if (isCachedHttpMethod)
209+
// Check if the cache should be checked
210+
var shouldCheckCache = this.ShouldTheCacheBeChecked(request);
211+
if (shouldCheckCache && isCachedHttpMethod)
157212
{
158213
key = this.CacheKeysProvider.GetKey(request);
159214

@@ -172,7 +227,7 @@ protected override HttpResponseMessage Send(HttpRequestMessage request, Cancella
172227

173228
this.StatsProvider.ReportCacheMiss(response.StatusCode);
174229

175-
if (TimeSpan.Zero != absoluteExpirationRelativeToNow)
230+
if (this.ShouldCacheResponse(response) && TimeSpan.Zero != absoluteExpirationRelativeToNow)
176231
{
177232
var cacheData = response.ToCacheEntry();
178233
this.responseCache.TrySetCacheData(key, cacheData, absoluteExpirationRelativeToNow);

0 commit comments

Comments
 (0)