public static CacheResponseDirective ReadCacheResponseDirective(this HttpResponseMessage responseMessage) { var directive = new CacheResponseDirective(); var cacheControl = responseMessage.Headers.CacheControl; if (cacheControl != null) { directive.MustRevalidate = cacheControl.MustRevalidate; directive.NoCache = cacheControl.NoCache; // TODO deal with no-cache field names? directive.NoStore = cacheControl.NoStore; // TODO deal with no-transform? directive.Public = cacheControl.Public; directive.Private = cacheControl.Private; // TODO deal with private field names? // TODO deal with proxy-revalidate? directive.MaxAge = cacheControl.MaxAge; directive.SharedMaxAge = cacheControl.SharedMaxAge; // TODO deal with cacheControl.Extensions } // TODO handle Expires, Age, Date directive.LastModified = responseMessage.Content?.Headers.LastModified; directive.ETag = responseMessage.Headers.ETag.ToETag(); // TODO handle responseMessage.Headers.Vary; // TODO handle responseMessage.Headers.Warning; return directive; }
public void AppliesDirectiveToResponse() { var dateTime1 = new DateTimeOffset(2015, 10, 20, 15, 42, 31, TimeSpan.Zero); var response = new TestableHttpResponse(); var cacheResponseDirective = new CacheResponseDirective(); cacheResponseDirective.LastModified = dateTime1; cacheResponseDirective.MaxAge = TimeSpan.FromMinutes(15); cacheResponseDirective.MustRevalidate = true; cacheResponseDirective.NoCache = true; cacheResponseDirective.NoStore = true; cacheResponseDirective.Private = true; cacheResponseDirective.Public = true; cacheResponseDirective.SharedMaxAge = TimeSpan.FromHours(1); DnxExtensions.ApplyCacheResponseDirective(response, cacheResponseDirective); var responseHeaders = response.GetTypedHeaders(); Assert.NotNull(responseHeaders.CacheControl); Assert.Equal(dateTime1, responseHeaders.LastModified); Assert.Equal(TimeSpan.FromMinutes(15), responseHeaders.CacheControl.MaxAge); Assert.True(responseHeaders.CacheControl.MustRevalidate); Assert.True(responseHeaders.CacheControl.NoCache); Assert.True(responseHeaders.CacheControl.NoStore); Assert.True(responseHeaders.CacheControl.Private); Assert.True(responseHeaders.CacheControl.Public); Assert.Equal(TimeSpan.FromHours(1), responseHeaders.CacheControl.SharedMaxAge); }
public static void ApplyCacheResponseDirective(this HttpResponse response, CacheResponseDirective directive) { var cacheControl = new CacheControlHeaderValue(); cacheControl.MaxAge = directive.MaxAge; cacheControl.MustRevalidate = directive.MustRevalidate; cacheControl.NoCache = directive.NoCache; cacheControl.NoStore = directive.NoStore; cacheControl.Private = directive.Private; cacheControl.Public = directive.Public; cacheControl.SharedMaxAge = directive.SharedMaxAge; var responseHeaders = response.GetTypedHeaders(); responseHeaders.CacheControl = cacheControl; responseHeaders.LastModified = directive.LastModified; responseHeaders.ETag = directive.ETag.ToETagHeaderValue(); }
/// <summary> /// Combines two <see cref="CacheResponseDirective"/> instances into a new one, using the most restrictive value from each pair of input properties. /// </summary> /// <remarks> /// <see cref="LastModified"/> is only set if both inputs specify a value. /// <see cref="Public"/> is only set if the result does not have <see cref="Private"/> set. /// </remarks> public static CacheResponseDirective Combine(CacheResponseDirective a, CacheResponseDirective b, Func<ETag, ETag, ETag> etagCombiner = null) { var result = new CacheResponseDirective(); if (a.LastModified.HasValue && b.LastModified.HasValue) { // Only set LastModified if both sides specify it. If either side does not specify then LastModified of the combined result is indeterminate. result.LastModified = Max(a.LastModified, b.LastModified); } result.MaxAge = Min(a.MaxAge, b.MaxAge); result.MustRevalidate = a.MustRevalidate || b.MustRevalidate; result.NoCache = a.NoCache || b.NoCache; result.NoStore = a.NoStore || b.NoStore; result.Private = a.Private || b.Private; result.Public = !result.Private && (a.Public || b.Public); // TODO: Is this correct? Does it make sense for a response to be marked both as Public and Private? result.SharedMaxAge = Min(a.SharedMaxAge, b.SharedMaxAge); if (etagCombiner != null && a.ETag != null && b.ETag != null) result.ETag = etagCombiner(a.ETag, b.ETag); return result; }