Adding IgnoreNoCache setting to OutputCache

This setting lets a website ignore "no-cache" requests from clients.
This is usually done to force a refresh of a cached value, but this could
also lead to unnecessary load as Orchard already invalidates its cache
automatically (based on tags) or it could also be used by DDOS attacks.

Also remove the "browser" ASP.NET setting as it could create too many
entries in kernel cache.

Work Item: 20614
This commit is contained in:
Sebastien Ros
2014-04-10 14:35:08 -07:00
parent 5bc6b74395
commit 302b1f3540
5 changed files with 28 additions and 14 deletions

View File

@@ -89,7 +89,8 @@ namespace Orchard.OutputCache.Controllers {
IgnoredUrls = settings.IgnoredUrls,
DebugMode = settings.DebugMode,
ApplyCulture = settings.ApplyCulture,
RouteConfigurations = routeConfigurations
RouteConfigurations = routeConfigurations,
IgnoreNoCache = settings.IgnoreNoCache
};
return View(model);
@@ -113,6 +114,7 @@ namespace Orchard.OutputCache.Controllers {
settings.IgnoredUrls = model.IgnoredUrls;
settings.DebugMode = model.DebugMode;
settings.ApplyCulture = model.ApplyCulture;
settings.IgnoreNoCache = model.IgnoreNoCache;
// invalidates the settings cache
_signals.Trigger(CacheSettingsPart.CacheKey);

View File

@@ -70,6 +70,7 @@ namespace Orchard.OutputCache.Filters {
private int _maxAge;
private string _ignoredUrls;
private bool _applyCulture;
private bool _ignoreNoCache;
private string _cacheKey;
private string _invariantCacheKey;
private DateTime _now;
@@ -141,6 +142,14 @@ namespace Orchard.OutputCache.Filters {
}
);
// caches the default cache duration to prevent a query to the settings
_ignoreNoCache = _cacheManager.Get("CacheSettingsPart.IgnoreNoCache",
context => {
context.Monitor(_signals.When(CacheSettingsPart.CacheKey));
return _workContext.CurrentSite.As<CacheSettingsPart>().IgnoreNoCache;
}
);
// caches the default max age duration to prevent a query to the settings
_maxAge = _cacheManager.Get("CacheSettingsPart.MaxAge",
context => {
@@ -233,7 +242,7 @@ namespace Orchard.OutputCache.Filters {
// don't retrieve cache content if refused
// in this case the result of the action will update the current cached version
if (filterContext.RequestContext.HttpContext.Request.Headers["Cache-Control"] != "no-cache") {
if (filterContext.RequestContext.HttpContext.Request.Headers["Cache-Control"] != "no-cache" || _ignoreNoCache) {
// fetch cached data
_cacheItem = _cacheStorageProvider.GetCacheItem(_cacheKey);
@@ -499,15 +508,6 @@ namespace Orchard.OutputCache.Filters {
foreach (var varyRequestHeader in _varyRequestHeaders) {
response.Cache.VaryByHeaders[varyRequestHeader] = true;
}
// create a unique cache per browser, in case a Theme is rendered differently (e.g., mobile)
// c.f. http://msdn.microsoft.com/en-us/library/aa478965.aspx
// c.f. http://stackoverflow.com/questions/6007287/outputcache-varybyheader-user-agent-or-varybycustom-browser
response.Cache.SetVaryByCustom("browser");
// enabling this would create an entry for each different browser sub-version
// response.Cache.VaryByHeaders.UserAgent = true;
}
private string ComputeCacheKey(ControllerContext controllerContext, IEnumerable<KeyValuePair<string, object>> parameters) {

View File

@@ -38,5 +38,10 @@ namespace Orchard.OutputCache.Models {
get { return this.Retrieve(x => x.DebugMode); }
set { this.Store(x => x.DebugMode, value); }
}
public bool IgnoreNoCache {
get { return this.Retrieve(x => x.IgnoreNoCache); }
set { this.Store(x => x.IgnoreNoCache, value); }
}
}
}

View File

@@ -13,5 +13,6 @@ namespace Orchard.OutputCache.ViewModels {
public bool DebugMode { get; set; }
public string VaryQueryStringParameters { get; set; }
public string VaryRequestHeaders { get; set; }
public bool IgnoreNoCache { get; set; }
}
}

View File

@@ -25,6 +25,12 @@
<span class="hint">@T("When defined, a cache-control header with a max-age property will be added. Use this in order to enable kernel cache on IIS.")</span>
</fieldset>
<fieldset>
<label>@T("Ignore no-cache headers")</label>
@Html.TextAreaFor(m => m.IgnoredUrls, new { @class = "text medium" })
<span class="hint">@T("When checked, any request containing a 'Content-Cache: no-cache' header will still return cached values if available.")</span>
</fieldset>
<fieldset>
<label>@T("Vary Query String Parameters")</label>
@Html.TextBoxFor(m => m.VaryQueryStringParameters, new { @class = "text medium" })