mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-11-24 08:46:48 +08:00
Adding correct ETag support
This commit is contained in:
@@ -207,6 +207,15 @@ namespace Orchard.OutputCache.Filters {
|
||||
var response = filterContext.HttpContext.Response;
|
||||
var captureStream = new CaptureStream(response.Filter);
|
||||
response.Filter = captureStream;
|
||||
|
||||
// Add ETag header for the newly created item
|
||||
var etag = Guid.NewGuid().ToString("n");
|
||||
if (HttpRuntime.UsingIntegratedPipeline) {
|
||||
if (response.Headers.Get("ETag") == null) {
|
||||
response.Headers["ETag"] = etag;
|
||||
}
|
||||
}
|
||||
|
||||
captureStream.Captured += (output) => {
|
||||
try {
|
||||
// Since this is a callback any call to injected dependencies can result in an Autofac exception: "Instances
|
||||
@@ -227,12 +236,12 @@ namespace Orchard.OutputCache.Filters {
|
||||
Url = filterContext.HttpContext.Request.Url.AbsolutePath,
|
||||
Tenant = scope.Resolve<ShellSettings>().Name,
|
||||
StatusCode = response.StatusCode,
|
||||
Tags = new[] { _invariantCacheKey }.Union(contentItemIds).ToArray()
|
||||
Tags = new[] { _invariantCacheKey }.Union(contentItemIds).ToArray(),
|
||||
ETag = etag
|
||||
};
|
||||
|
||||
// Write the rendered item to the cache.
|
||||
var cacheStorageProvider = scope.Resolve<IOutputCacheStorageProvider>();
|
||||
cacheStorageProvider.Remove(_cacheKey);
|
||||
cacheStorageProvider.Set(_cacheKey, cacheItem);
|
||||
|
||||
Logger.Debug("Item '{0}' was written to cache.", _cacheKey);
|
||||
@@ -465,6 +474,7 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
private void ServeCachedItem(ActionExecutingContext filterContext, CacheItem cacheItem) {
|
||||
var response = filterContext.HttpContext.Response;
|
||||
var request = filterContext.HttpContext.Request;
|
||||
|
||||
// Fix for missing charset in response headers
|
||||
response.Charset = response.Charset;
|
||||
@@ -474,12 +484,27 @@ namespace Orchard.OutputCache.Filters {
|
||||
response.AddHeader("X-Cached-On", cacheItem.CachedOnUtc.ToString("r"));
|
||||
response.AddHeader("X-Cached-Until", cacheItem.ValidUntilUtc.ToString("r"));
|
||||
}
|
||||
|
||||
|
||||
// Shorcut action execution.
|
||||
filterContext.Result = new FileContentResult(cacheItem.Output, cacheItem.ContentType);
|
||||
|
||||
response.StatusCode = cacheItem.StatusCode;
|
||||
|
||||
// Add ETag header
|
||||
if (HttpRuntime.UsingIntegratedPipeline && response.Headers.Get("ETag") == null) {
|
||||
response.Headers["ETag"] = cacheItem.ETag;
|
||||
}
|
||||
|
||||
// Check ETag in request
|
||||
// https://www.w3.org/2005/MWI/BPWG/techs/CachingWithETag.html
|
||||
var etag = request.Headers["If-None-Match"];
|
||||
if (!String.IsNullOrEmpty(etag)) {
|
||||
if (String.Equals(etag, cacheItem.ETag, StringComparison.Ordinal)) {
|
||||
// ETag matches the cached item, we return a 304
|
||||
filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.NotModified);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ApplyCacheControl(response);
|
||||
}
|
||||
|
||||
@@ -509,15 +534,6 @@ namespace Orchard.OutputCache.Filters {
|
||||
// response.DisableKernelCache();
|
||||
// response.Cache.SetOmitVaryStar(true);
|
||||
|
||||
// An ETag is a string that uniquely identifies a specific version of a component.
|
||||
// We use the cache item to detect if it's a new one.
|
||||
if (HttpRuntime.UsingIntegratedPipeline) {
|
||||
if (response.Headers.Get("ETag") == null) {
|
||||
// What is the point of GetHashCode() of a newly generated item? /DanielStolt
|
||||
response.Cache.SetETag(new CacheItem().GetHashCode().ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
|
||||
if (CacheSettings.VaryByQueryStringParameters == null) {
|
||||
response.Cache.VaryByParams["*"] = true;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Orchard.OutputCache.Models {
|
||||
[Serializable]
|
||||
public class CacheItem {
|
||||
// used for serialization compatibility
|
||||
public static readonly string Version = "1";
|
||||
public static readonly string Version = "2";
|
||||
|
||||
public DateTime CachedOnUtc { get; set; }
|
||||
public int Duration { get; set; }
|
||||
@@ -18,6 +18,7 @@ namespace Orchard.OutputCache.Models {
|
||||
public string Tenant { get; set; }
|
||||
public int StatusCode { get; set; }
|
||||
public string[] Tags { get; set; }
|
||||
public string ETag { get; set; }
|
||||
|
||||
public int ValidFor {
|
||||
get { return Duration; }
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Orchard.OutputCache.Services {
|
||||
}
|
||||
|
||||
public void Set(string key, CacheItem cacheItem) {
|
||||
_workContext.HttpContext.Cache.Remove(key);
|
||||
_workContext.HttpContext.Cache.Add(
|
||||
key,
|
||||
cacheItem,
|
||||
|
||||
Reference in New Issue
Block a user