mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -37,8 +36,6 @@ namespace Orchard.OutputCache.Filters {
|
||||
private readonly ICacheControlStrategy _cacheControlStrategy;
|
||||
private Stream _previousFilter;
|
||||
|
||||
private const string RefreshKey = "__r";
|
||||
|
||||
public OutputCacheFilter(
|
||||
ICacheManager cacheManager,
|
||||
IOutputCacheStorageProvider cacheStorageProvider,
|
||||
@@ -50,7 +47,8 @@ namespace Orchard.OutputCache.Filters {
|
||||
ICacheService cacheService,
|
||||
ISignals signals,
|
||||
ShellSettings shellSettings,
|
||||
ICacheControlStrategy cacheControlStrategy) {
|
||||
ICacheControlStrategy cacheControlStrategy
|
||||
) {
|
||||
_cacheManager = cacheManager;
|
||||
_cacheStorageProvider = cacheStorageProvider;
|
||||
_tagCache = tagCache;
|
||||
@@ -73,11 +71,10 @@ namespace Orchard.OutputCache.Filters {
|
||||
private bool _applyCulture;
|
||||
private string _cacheKey;
|
||||
private string _invariantCacheKey;
|
||||
private string _actionName;
|
||||
private DateTime _now;
|
||||
private string[] _varyQueryStringParameters;
|
||||
private ISet<string> _varyRequestHeaders;
|
||||
|
||||
private bool _transformRedirect;
|
||||
|
||||
private WorkContext _workContext;
|
||||
private CapturingResponseFilter _filter;
|
||||
@@ -87,8 +84,6 @@ namespace Orchard.OutputCache.Filters {
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void OnActionExecuting(ActionExecutingContext filterContext) {
|
||||
// use the action in the cacheKey so that the same route can't return cache for different actions
|
||||
_actionName = filterContext.ActionDescriptor.ActionName;
|
||||
|
||||
// apply OutputCacheAttribute logic if defined
|
||||
var actionAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(OutputCacheAttribute), true);
|
||||
@@ -284,12 +279,12 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
// no cache content available, intercept the execution results for caching
|
||||
_previousFilter = response.Filter;
|
||||
response.Filter = _filter = new CapturingResponseFilter(response.Filter);
|
||||
response.Filter = _filter = new CapturingResponseFilter();
|
||||
}
|
||||
|
||||
public void OnActionExecuted(ActionExecutedContext filterContext) {
|
||||
// handle redirections
|
||||
TransformRedirect(filterContext);
|
||||
_transformRedirect = TransformRedirect(filterContext);
|
||||
}
|
||||
|
||||
public void OnResultExecuted(ResultExecutedContext filterContext) {
|
||||
@@ -342,7 +337,7 @@ namespace Orchard.OutputCache.Filters {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// save the result only if the content can be intercepted
|
||||
if (_filter == null) return;
|
||||
|
||||
@@ -358,8 +353,7 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
response.Filter = null;
|
||||
response.Write(output);
|
||||
|
||||
|
||||
|
||||
// check if there is a specific rule not to cache the whole route
|
||||
var configurations = _cacheService.GetRouteConfigurations();
|
||||
var route = filterContext.Controller.ControllerContext.RouteData.Route;
|
||||
@@ -372,12 +366,28 @@ namespace Orchard.OutputCache.Filters {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't cache the result of a POST redirection as it could contain notifications
|
||||
if (_transformRedirect) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't cache the result if there were some notifications
|
||||
var messagesZone = _workContextAccessor.GetContext(filterContext).Layout.Zones["Messages"];
|
||||
var hasNotifications = messagesZone != null && ((IEnumerable<dynamic>)messagesZone).Any();
|
||||
if (hasNotifications) {
|
||||
return;
|
||||
}
|
||||
|
||||
// default duration of specific one ?
|
||||
var cacheDuration = configuration != null && configuration.Duration.HasValue ? configuration.Duration.Value : _cacheDuration;
|
||||
|
||||
// include each of the content item ids as tags for the cache entry
|
||||
var contentItemIds = _displayedContentItemHandler.GetDisplayed().Select(x => x.ToString(CultureInfo.InvariantCulture)).ToArray();
|
||||
|
||||
if (filterContext.HttpContext.Request.Url == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
_cacheItem.ContentType = response.ContentType;
|
||||
_cacheItem.StatusCode = response.StatusCode;
|
||||
_cacheItem.CachedOnUtc = _now;
|
||||
@@ -407,6 +417,8 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
private bool TransformRedirect(ActionExecutedContext filterContext) {
|
||||
|
||||
// removes the target of the redirection from cache after a POST
|
||||
|
||||
if (filterContext.Result == null) {
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
@@ -438,26 +450,6 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
_cacheService.RemoveByTag(invariantCacheKey);
|
||||
|
||||
// adding a refresh key so that the next request will not be cached
|
||||
var epIndex = redirectUrl.IndexOf('?');
|
||||
var qs = new NameValueCollection();
|
||||
if (epIndex > 0) {
|
||||
qs = HttpUtility.ParseQueryString(redirectUrl.Substring(epIndex));
|
||||
}
|
||||
|
||||
var refresh = _now.Ticks;
|
||||
qs.Remove(RefreshKey);
|
||||
|
||||
qs.Add(RefreshKey, refresh.ToString("x"));
|
||||
var querystring = "?" + string.Join("&", Array.ConvertAll(qs.AllKeys, k => string.Format("{0}={1}", HttpUtility.UrlEncode(k), HttpUtility.UrlEncode(qs[k]))));
|
||||
|
||||
if (epIndex > 0) {
|
||||
redirectUrl = redirectUrl.Substring(0, epIndex) + querystring;
|
||||
}
|
||||
else {
|
||||
redirectUrl = redirectUrl + querystring;
|
||||
}
|
||||
|
||||
filterContext.Result = new RedirectResult(redirectUrl, ((RedirectResult) filterContext.Result).Permanent);
|
||||
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
|
||||
|
||||
@@ -538,9 +530,6 @@ namespace Orchard.OutputCache.Filters {
|
||||
// include the theme in the cache key
|
||||
keyBuilder.Append("theme=").Append(theme.ToLowerInvariant()).Append(";");
|
||||
|
||||
// include the theme in the cache key
|
||||
keyBuilder.Append("action=").Append(_actionName.ToLowerInvariant()).Append(";");
|
||||
|
||||
if (parameters != null) {
|
||||
foreach (var pair in parameters) {
|
||||
keyBuilder.AppendFormat("{0}={1};", pair.Key.ToLowerInvariant(), Convert.ToString(pair.Value).ToLowerInvariant());
|
||||
@@ -597,11 +586,9 @@ namespace Orchard.OutputCache.Filters {
|
||||
/// Captures the response stream while writing to it
|
||||
/// </summary>
|
||||
public class CapturingResponseFilter : Stream {
|
||||
// private readonly Stream _sink;
|
||||
private readonly MemoryStream _mem;
|
||||
|
||||
public CapturingResponseFilter(Stream sink) {
|
||||
// _sink = sink;
|
||||
public CapturingResponseFilter() {
|
||||
_mem = new MemoryStream();
|
||||
}
|
||||
|
||||
@@ -629,27 +616,21 @@ namespace Orchard.OutputCache.Filters {
|
||||
}
|
||||
|
||||
public override void SetLength(long length) {
|
||||
// _sink.SetLength(length);
|
||||
}
|
||||
|
||||
public override void Close() {
|
||||
// _sink.Close();
|
||||
_mem.Close();
|
||||
}
|
||||
|
||||
public override void Flush() {
|
||||
// _sink.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) {
|
||||
// return _sink.Read(buffer, offset, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
// Override the Write method to filter Response to a file.
|
||||
public override void Write(byte[] buffer, int offset, int count) {
|
||||
//Here we will not write to the sink b/c we want to capture
|
||||
// _sink.Write(buffer, offset, count);
|
||||
|
||||
//Write out the response to the file.
|
||||
_mem.Write(buffer, 0, count);
|
||||
|
@@ -3,9 +3,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.OutputCache.Models;
|
||||
using Orchard;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Services;
|
||||
|
||||
namespace Orchard.OutputCache.Services {
|
||||
public class DefaultCacheStorageProvider : IOutputCacheStorageProvider {
|
||||
|
Reference in New Issue
Block a user