Skip to content

Commit 9479fe2

Browse files
committed
update with code review feedback
1 parent 731ac90 commit 9479fe2

4 files changed

Lines changed: 134 additions & 34 deletions

File tree

src/OutputCacheModuleAsync/OutputCacheHelper.cs

Lines changed: 104 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private static CachedRawResponse Convert(OutputCacheEntry oce) {
155155
};
156156
}
157157

158-
public async Task<object> Get(string key) {
158+
internal async Task<object> GetAsync(string key) {
159159
OutputCacheProviderAsync provider = GetProvider(HttpContext.Current);
160160
object result = await provider.GetAsync(key);
161161
var oce = result as OutputCacheEntry;
@@ -170,7 +170,7 @@ public async Task<object> Get(string key) {
170170
return result;
171171
}
172172

173-
public async Task Remove(string key, HttpContext context) {
173+
internal async Task RemoveAsync(string key, HttpContext context) {
174174
// we don't know if it's in the internal cache or
175175
// one of the providers. If a context is given,
176176
// then we can narrow down to at most one provider.
@@ -189,7 +189,7 @@ public async Task Remove(string key, HttpContext context) {
189189
}
190190
}
191191

192-
public async Task InsertResponse(string cachedVaryKey,
192+
internal async Task InsertResponseAsync(string cachedVaryKey,
193193
CachedVary cachedVary,
194194
string rawResponseKey,
195195
CachedRawResponse rawResponse,
@@ -258,7 +258,7 @@ public async Task InsertResponse(string cachedVaryKey,
258258
}
259259
}
260260

261-
public static bool IsCacheableEncoding(string coding, string[] contentEncodings) {
261+
internal static bool IsCacheableEncoding(string coding, string[] contentEncodings) {
262262
// return true if we are not varying by content encoding.
263263
if (contentEncodings == null) {
264264
return true;
@@ -268,7 +268,7 @@ public static bool IsCacheableEncoding(string coding, string[] contentEncodings)
268268
// return true if the Content-Encoding header is listed
269269
}
270270

271-
public static bool ContainsNonShareableCookies(HttpResponse response) {
271+
internal static bool ContainsNonShareableCookies(HttpResponse response) {
272272
HttpCookieCollection cookies = response.Cookies;
273273
for (int i = 0; i < cookies.Count; i++) {
274274
HttpCookie httpCookie = cookies[i];
@@ -279,7 +279,7 @@ public static bool ContainsNonShareableCookies(HttpResponse response) {
279279
return false;
280280
}
281281

282-
public static void UseSnapshot(HttpRawResponse rawResponse, bool sendBody, HttpResponse response) {
282+
internal static void UseSnapshot(HttpRawResponse rawResponse, bool sendBody, HttpResponse response) {
283283
if (response.HeadersWritten)
284284
throw new HttpException(SR.Cannot_use_snapshot_after_headers_sent);
285285
response.Clear();
@@ -296,7 +296,7 @@ public static void UseSnapshot(HttpRawResponse rawResponse, bool sendBody, HttpR
296296
response.SuppressContent = !sendBody;
297297
}
298298

299-
public static HttpRawResponse GetSnapshot(HttpResponse response) {
299+
internal static HttpRawResponse GetSnapshot(HttpResponse response) {
300300
var headers = new NameValueCollection();
301301
const bool hasSubstBlocks = false;
302302
if (response.HeadersWritten)
@@ -328,7 +328,7 @@ public static HttpRawResponse GetSnapshot(HttpResponse response) {
328328
};
329329
}
330330

331-
public static HttpCachePolicySettings GetCurrentSettings(HttpResponse response) {
331+
internal static HttpCachePolicySettings GetCurrentSettings(HttpResponse response) {
332332
IEnumerable<KeyValuePair<HttpCacheValidateHandler, object>> validationCallbackInfo =
333333
OutputCacheUtility.GetValidationCallbacks(response);
334334

@@ -353,7 +353,7 @@ public static HttpCachePolicySettings GetCurrentSettings(HttpResponse response)
353353
};
354354
}
355355

356-
public static void ResetFromHttpCachePolicySettings(HttpCachePolicySettings settings,
356+
internal static void ResetFromHttpCachePolicySettings(HttpCachePolicySettings settings,
357357
DateTime utcTimestampRequest, HttpResponse response) {
358358
response.Cache.SetCacheability(settings.Cacheability);
359359
response.Cache.VaryByContentEncodings.SetContentEncodings(settings.VaryByContentEncodings);
@@ -385,13 +385,99 @@ public static void ResetFromHttpCachePolicySettings(HttpCachePolicySettings sett
385385
}
386386
}
387387

388-
public static void UpdateCachedHeaders(HttpResponse response) {
388+
internal static void UpdateCachedHeaders(HttpResponse response) {
389+
//To enable Out of Band OutputCache Module support, we will always refresh the UtcTimestampRequest.
389390
if (response.Cache.UtcTimestampCreated == DateTime.MinValue) {
390391
response.Cache.UtcTimestampCreated = HttpContext.Current.Timestamp.ToUniversalTime();
392+
}
393+
UpdateFromDependencies(response);
394+
}
395+
396+
private static void UpdateFromDependencies(HttpResponse response) {
397+
CacheDependency dep = null;
398+
// if response.Cache.GetETag() != null && response.Cache.GetETagFromFileDependencies() == true, then this HttpCachePolicy
399+
// was created from HttpCachePolicySettings and we don't need to update _etag.
400+
if (response.Cache.GetETag() == null && response.Cache.GetETagFromFileDependencies()) {
401+
dep = OutputCacheUtility.CreateCacheDependency(response);
402+
if (dep == null) {
403+
return;
404+
}
405+
string id = dep.GetUniqueID();
406+
if (id == null) {
407+
throw new HttpException(SR.No_UniqueId_Cache_Dependency);
408+
}
409+
DateTime utcFileLastModifiedMax = UpdateLastModifiedTimeFromDependency(dep, response);
410+
var sb = new StringBuilder(256);
411+
sb.Append(HttpRuntime.AppDomainId);
412+
sb.Append(id);
413+
sb.Append("+LM");
414+
sb.Append(utcFileLastModifiedMax.Ticks.ToString(CultureInfo.InvariantCulture));
415+
response.Cache.SetETag("\"" +
416+
System.Convert.ToBase64String(
417+
CryptoUtil.ComputeSha256Hash(Encoding.UTF8.GetBytes(sb.ToString()))) + "\"");
418+
419+
420+
if (!response.Cache.GetLastModifiedFromFileDependencies())
421+
return;
422+
}
423+
424+
{
425+
if (dep == null) {
426+
dep = OutputCacheUtility.CreateCacheDependency(response);
427+
if (dep == null) {
428+
return;
429+
}
430+
}
431+
DateTime utcFileLastModifiedMax = UpdateLastModifiedTimeFromDependency(dep,response);
432+
UtcSetLastModified(utcFileLastModifiedMax, response);
391433
}
392434
}
393435

394-
public static string CreateOutputCachedItemKey(
436+
private static void UtcSetLastModified(DateTime utcDate, HttpResponse response) {
437+
438+
/*
439+
* Time may differ if the system time changes in the middle of the request.
440+
* Adjust the timestamp to Now if necessary.
441+
*/
442+
443+
DateTime utcNow = DateTime.UtcNow;
444+
if (utcDate > utcNow) {
445+
utcDate = utcNow;
446+
}
447+
448+
/*
449+
* Because HTTP dates have a resolution of 1 second, we
450+
* need to store dates with 1 second resolution or comparisons
451+
* will be off.
452+
*/
453+
454+
utcDate = new DateTime(utcDate.Ticks - (utcDate.Ticks % TimeSpan.TicksPerSecond));
455+
if (response.Cache.GetUtcLastModified()!= DateTime.MinValue || utcDate > response.Cache.GetUtcLastModified()) {
456+
response.Cache.SetLastModified(utcDate);
457+
}
458+
459+
460+
}
461+
462+
463+
private static DateTime UpdateLastModifiedTimeFromDependency(CacheDependency dep, HttpResponse response) {
464+
DateTime utcFileLastModifiedMax = dep.UtcLastModified;
465+
if (utcFileLastModifiedMax < response.Cache.GetUtcLastModified()) {
466+
utcFileLastModifiedMax = response.Cache.GetUtcLastModified();
467+
}
468+
// account for difference between file system time
469+
// and DateTime.Now. On some machines it appears that
470+
// the last modified time is further in the future
471+
// that DateTime.Now
472+
DateTime utcNow = DateTime.UtcNow;
473+
if (utcFileLastModifiedMax > utcNow) {
474+
utcFileLastModifiedMax = utcNow;
475+
}
476+
return utcFileLastModifiedMax;
477+
478+
}
479+
480+
private static string CreateOutputCachedItemKey(
395481
string path,
396482
string verb,
397483
HttpContext context,
@@ -530,7 +616,7 @@ public static string CreateOutputCachedItemKey(
530616
* and form posted data.
531617
*/
532618

533-
public static string CreateOutputCachedItemKeyAsync(HttpContext context, CachedVary cachedVary) {
619+
internal static string CreateOutputCachedItemKey(HttpContext context, CachedVary cachedVary) {
534620
return CreateOutputCachedItemKey(context.Request.Path, context.Request.HttpMethod, context, cachedVary);
535621
}
536622

@@ -540,7 +626,7 @@ public static string CreateOutputCachedItemKeyAsync(HttpContext context, CachedV
540626
* returns either i) an acceptable index in contentEncodings, ii) -1 if the identity is acceptable, or iii) -2 if nothing is acceptable
541627
*/
542628

543-
public static int GetAcceptableEncoding(string[] contentEncodings, int startIndex, string acceptEncoding) {
629+
internal static int GetAcceptableEncoding(string[] contentEncodings, int startIndex, string acceptEncoding) {
544630
// The format of Accept-Encoding is ( 1#( codings [ ";" "q" "=" qvalue ] ) | "*" )
545631
if (string.IsNullOrEmpty(acceptEncoding)) {
546632
return -1; // use "identity"
@@ -604,9 +690,9 @@ public static int GetAcceptableEncoding(string[] contentEncodings, int startInde
604690
return bestCodingIndex; // coding index with highest weight, possibly -1 or -2
605691
}
606692

607-
public static double Tolerance { get; set; }
693+
private static double Tolerance { get; set; }
608694

609-
// Get the weight of the specified coding from the Accept-Encoding header.
695+
// GetAsync the weight of the specified coding from the Accept-Encoding header.
610696
// 1 means use this coding. 0 means don't use this coding. A number between
611697
// 1 and 0 must be compared with other codings. -1 means the coding was not found
612698
private static double GetAcceptableEncodingHelper(string coding, string acceptEncoding) {
@@ -689,7 +775,7 @@ private static bool IsIdentityAcceptable(string acceptEncoding) {
689775
return result;
690776
}
691777

692-
public static bool IsAcceptableEncoding(string contentEncoding, string acceptEncoding) {
778+
internal static bool IsAcceptableEncoding(string contentEncoding, string acceptEncoding) {
693779
if (string.IsNullOrEmpty(contentEncoding)) {
694780
// if Content-Encoding is not set treat it as the identity
695781
contentEncoding = Identity;
@@ -703,5 +789,7 @@ public static bool IsAcceptableEncoding(string contentEncoding, string acceptEnc
703789
return !(Math.Abs(weight) < tolerance) &&
704790
(!(weight <= 0) || Math.Abs(GetAcceptableEncodingHelper(Asterisk, acceptEncoding)) > 0);
705791
}
792+
793+
706794
}
707795
}

src/OutputCacheModuleAsync/OutputCacheModuleAsync.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ private async Task OnEnterAsync(object source, EventArgs eventArgs) {
6464
}
6565

6666
// Create a lookup key. Also store the key in global parameter _key to be used inside OnLeave() later
67-
string key = _key = OutputCacheHelper.CreateOutputCachedItemKeyAsync(context, null);
67+
string key = _key = OutputCacheHelper.CreateOutputCachedItemKey(context, null);
6868

6969
// Lookup the cache vary using the key
70-
object item = await _outputCacheHelper.Get(key);
71-
if (await _outputCacheHelper.Get(key) == null) {
70+
object item = await _outputCacheHelper.GetAsync(key);
71+
if (item == null) {
7272
return;
7373
}
7474
// 'item' may be one of the following:
@@ -87,7 +87,7 @@ private async Task OnEnterAsync(object source, EventArgs eventArgs) {
8787
return;
8888
}
8989

90-
if (await CheckHeadersToDetermineAcceptCachedCopy(key, settings, request, context)) {
90+
if (await CheckHeadersToDetermineAcceptCachedCopyAsync(key, settings, request, context)) {
9191
return;
9292
}
9393

@@ -114,7 +114,7 @@ private async Task OnLeaveAsync(object source, EventArgs eventArgs) {
114114
if (!IsResponseCacheable(response, request, context)) {
115115
return;
116116
}
117-
await CacheResponse(context, response);
117+
await CacheResponseAsync(context, response);
118118
_key = null;
119119
}
120120

@@ -167,7 +167,7 @@ private static bool IsResponseCacheable(HttpResponse response, HttpRequest reque
167167
cache.VaryByContentEncodings.GetContentEncodings());
168168
}
169169

170-
private async Task CacheResponse(HttpContext context, HttpResponse response) {
170+
private async Task CacheResponseAsync(HttpContext context, HttpResponse response) {
171171
CachedVary cachedVary;
172172
string keyRawResponse;
173173
/*
@@ -180,7 +180,7 @@ private async Task CacheResponse(HttpContext context, HttpResponse response) {
180180
string[] varyByParams = settings.IgnoreParams ? null : settings.VaryByParams;
181181
/* Create the key if it was not created in OnEnter */
182182
if (_key == null) {
183-
_key = OutputCacheHelper.CreateOutputCachedItemKeyAsync(context, null);
183+
_key = OutputCacheHelper.CreateOutputCachedItemKey(context, null);
184184
Debug.Assert(_key != null, "_key != null");
185185
}
186186
if (settings.VaryByContentEncodings == null && varyByHeaders == null && varyByParams == null &&
@@ -223,7 +223,7 @@ private async Task CacheResponse(HttpContext context, HttpResponse response) {
223223
VaryByAllParams = varyByAllParams,
224224
VaryByCustom = settings.VaryByCustom
225225
};
226-
keyRawResponse = OutputCacheHelper.CreateOutputCachedItemKeyAsync(context, cachedVary);
226+
keyRawResponse = OutputCacheHelper.CreateOutputCachedItemKey(context, cachedVary);
227227
if (keyRawResponse == null) {
228228
Debug.WriteLine(SR.OutputCacheModuleLeave, string.Format(SR.Couldnot_add_non_cacheable_post,_key));
229229
return;
@@ -265,7 +265,7 @@ private async Task CacheResponse(HttpContext context, HttpResponse response) {
265265
Debug.WriteLine(SR.OutputCacheModuleLeave, string.Format(SR.Adding_response_to_cache, keyRawResponse));
266266
CacheDependency dep = OutputCacheUtility.CreateCacheDependency(context.Response);
267267
try {
268-
await _outputCacheHelper.InsertResponse(_key, cachedVary,
268+
await _outputCacheHelper.InsertResponseAsync(_key, cachedVary,
269269
keyRawResponse, cachedRawResponse,
270270
dep,
271271
utcExpires, slidingDelta);
@@ -364,7 +364,7 @@ private static bool EnsureContentEncodingAcceptable(CachedVary cachedVary, HttpR
364364
return OutputCacheHelper.IsAcceptableEncoding(contentEncoding, acceptEncoding);
365365
}
366366

367-
private async Task<bool> CheckHeadersToDetermineAcceptCachedCopy(string key, HttpCachePolicySettings settings,
367+
private async Task<bool> CheckHeadersToDetermineAcceptCachedCopyAsync(string key, HttpCachePolicySettings settings,
368368
HttpRequest request, HttpContext context) {
369369
if (!settings.HasValidationPolicy()) {
370370
if (request.Headers["Cache-Control"] != null) {
@@ -449,7 +449,7 @@ private async Task<bool> CheckHeadersToDetermineAcceptCachedCopy(string key, Htt
449449
Debug.WriteLine(SR.OutputCacheModuleEnter,
450450
string.Format(SR.Output_cache_item_found_but_callback_invalidated_it,key) + " OutputCacheModule::Enter");
451451

452-
await _outputCacheHelper.Remove(key, context);
452+
await _outputCacheHelper.RemoveAsync(key, context);
453453
return true;
454454
case HttpValidationStatus.IgnoreThisRequest:
455455
validationStatusFinal = HttpValidationStatus.IgnoreThisRequest;
@@ -502,7 +502,7 @@ private async Task<CachedItem> CheckCacheVaryAsync(CachedVary cachedVary, HttpCo
502502
*
503503
* Skip this step if it's a VaryByNone vary policy.
504504
*/
505-
string key = OutputCacheHelper.CreateOutputCachedItemKeyAsync(context, cachedVary);
505+
string key = OutputCacheHelper.CreateOutputCachedItemKey(context, cachedVary);
506506
if (key == null) {
507507
Debug.WriteLine(SR.OutputCacheModuleEnter,
508508
string.Format(SR.Miss_key_could_not_be_created_for_varyby_item,"Vary-By") + " OutputCacheModule::Enter");
@@ -511,7 +511,7 @@ private async Task<CachedItem> CheckCacheVaryAsync(CachedVary cachedVary, HttpCo
511511
if (cachedVary.ContentEncodings == null) {
512512
// With the new key, look up the in-memory key.
513513
// At this point, we've exhausted the lookups in memory for this item.
514-
item = await _outputCacheHelper.Get(key);
514+
item = await _outputCacheHelper.GetAsync(key);
515515
}
516516
else {
517517
bool identityIsAcceptable = true;
@@ -526,7 +526,7 @@ private async Task<CachedItem> CheckCacheVaryAsync(CachedVary cachedVary, HttpCo
526526
if (index > -1) {
527527
identityIsAcceptable = false;
528528
// the client Accept-Encoding header contains an encoding that's in the VaryByContentEncoding list
529-
item = await _outputCacheHelper.Get(key + contentEncodings[index]);
529+
item = await _outputCacheHelper.GetAsync(key + contentEncodings[index]);
530530
if (item != null) {
531531
continue;
532532
}
@@ -543,15 +543,15 @@ private async Task<CachedItem> CheckCacheVaryAsync(CachedVary cachedVary, HttpCo
543543
}
544544
// the identity should not be used if the client Accept-Encoding contains an entry in the VaryByContentEncoding list or "identity" is not acceptable
545545
if (item == null && identityIsAcceptable) {
546-
item = await _outputCacheHelper.Get(key);
546+
item = await _outputCacheHelper.GetAsync(key);
547547
}
548548
}
549549
if (item != null && ((CachedRawResponse) item).CachedVaryId == cachedVary.CachedVaryId) {
550550
return new CachedItem {DoReturn = false, Item = item};
551551
}
552552
if (item != null) {
553553
// explicitly remove entry because _cachedVaryId does not match
554-
await _outputCacheHelper.Remove(key, context);
554+
await _outputCacheHelper.RemoveAsync(key, context);
555555
}
556556
return new CachedItem {DoReturn = true, Item = item};
557557
}

0 commit comments

Comments
 (0)