mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Manual merge up of 3.x changes to HTTP class
This commit is contained in:
parent
76bf2ab21a
commit
442db3050c
@ -3,10 +3,17 @@ Name: coreconfig
|
|||||||
---
|
---
|
||||||
SilverStripe\Control\HTTP:
|
SilverStripe\Control\HTTP:
|
||||||
cache_control:
|
cache_control:
|
||||||
max-age: 0
|
no-cache: true
|
||||||
must-revalidate: "true"
|
no-store: true
|
||||||
no-transform: "true"
|
must-revalidate: true
|
||||||
vary: "Cookie, X-Forwarded-Protocol, X-Forwarded-Proto, User-Agent, Accept"
|
vary: "X-Requested-With, X-Forwarded-Protocol"
|
||||||
SilverStripe\Core\Manifest\VersionProvider:
|
SilverStripe\Core\Manifest\VersionProvider:
|
||||||
modules:
|
modules:
|
||||||
silverstripe/framework: Framework
|
silverstripe/framework: Framework
|
||||||
|
---
|
||||||
|
Name: httpconfig-dev
|
||||||
|
Only:
|
||||||
|
environment: dev
|
||||||
|
---
|
||||||
|
SilverStripe\Control\HTTP:
|
||||||
|
disable_http_cache: true
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
namespace SilverStripe\Control;
|
namespace SilverStripe\Control;
|
||||||
|
|
||||||
use SilverStripe\Assets\File;
|
use SilverStripe\Assets\File;
|
||||||
|
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
|
||||||
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Core\Config\Configurable;
|
use SilverStripe\Core\Config\Configurable;
|
||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
@ -37,6 +39,37 @@ class HTTP
|
|||||||
*/
|
*/
|
||||||
private static $cache_ajax_requests = true;
|
private static $cache_ajax_requests = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @config
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $disable_http_cache = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping of extension to mime types
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @config
|
||||||
|
*/
|
||||||
|
private static $MimeTypes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of names to add to the Cache-Control header.
|
||||||
|
*
|
||||||
|
* @see HTTPCacheControlMiddleware::__construct()
|
||||||
|
* @config
|
||||||
|
* @var array Keys are cache control names, values are boolean flags
|
||||||
|
*/
|
||||||
|
private static $cache_control = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vary string; A comma separated list of var header names
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
private static $vary = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turns a local system filename into a URL by comparing it to the script filename.
|
* Turns a local system filename into a URL by comparing it to the script filename.
|
||||||
*
|
*
|
||||||
@ -328,6 +361,7 @@ class HTTP
|
|||||||
public static function set_cache_age($age)
|
public static function set_cache_age($age)
|
||||||
{
|
{
|
||||||
self::$cache_age = $age;
|
self::$cache_age = $age;
|
||||||
|
HTTPCacheControlMiddleware::singleton()->setMaxAge(self::$cache_age);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -376,169 +410,175 @@ class HTTP
|
|||||||
*/
|
*/
|
||||||
public static function add_cache_headers($body = null)
|
public static function add_cache_headers($body = null)
|
||||||
{
|
{
|
||||||
$cacheAge = self::$cache_age;
|
|
||||||
|
|
||||||
// Validate argument
|
// Validate argument
|
||||||
if ($body && !($body instanceof HTTPResponse)) {
|
if ($body && !($body instanceof HTTPResponse)) {
|
||||||
user_error("HTTP::add_cache_headers() must be passed an HTTPResponse object", E_USER_WARNING);
|
user_error("HTTP::add_cache_headers() must be passed an HTTPResponse object", E_USER_WARNING);
|
||||||
$body = null;
|
$body = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Development sites have frequently changing templates; this can get stuffed up by the code
|
|
||||||
// below.
|
|
||||||
if (Director::isDev()) {
|
|
||||||
$cacheAge = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The headers have been sent and we don't have an HTTPResponse object to attach things to; no point in
|
// The headers have been sent and we don't have an HTTPResponse object to attach things to; no point in
|
||||||
// us trying.
|
// us trying.
|
||||||
if (headers_sent() && !$body) {
|
if (headers_sent() && !$body) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate $responseHeaders with all the headers that we want to build
|
// Warn if already assigned cache-control headers
|
||||||
$responseHeaders = array();
|
if ($body && $body->getHeader('Cache-Control')) {
|
||||||
|
trigger_error(
|
||||||
|
'Cache-Control header has already been set. '
|
||||||
|
. 'Please use HTTPCacheControlMiddleware API to set caching options instead.',
|
||||||
|
E_USER_WARNING
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$cacheControlHeaders = HTTP::config()->uninherited('cache_control');
|
$config = Config::forClass(__CLASS__);
|
||||||
|
|
||||||
|
// Get current cache control state
|
||||||
|
$cacheControl = HTTPCacheControlMiddleware::singleton();
|
||||||
|
|
||||||
// currently using a config setting to cancel this, seems to be so that the CMS caches ajax requests
|
// if http caching is disabled by config, disable it - used on dev environments due to frequently changing
|
||||||
if (function_exists('apache_request_headers') && static::config()->uninherited('cache_ajax_requests')) {
|
// templates and other data. will be overridden by forced publicCache() or privateCache() calls
|
||||||
$requestHeaders = array_change_key_case(apache_request_headers(), CASE_LOWER);
|
if ($config->get('disable_http_cache')) {
|
||||||
if (isset($requestHeaders['x-requested-with'])
|
$cacheControl->disableCache();
|
||||||
&& $requestHeaders['x-requested-with']=='XMLHttpRequest'
|
}
|
||||||
) {
|
|
||||||
$cacheAge = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cacheAge > 0) {
|
// Populate $responseHeaders with all the headers that we want to build
|
||||||
$cacheControlHeaders['max-age'] = self::$cache_age;
|
$responseHeaders = array();
|
||||||
|
|
||||||
// Set empty pragma to avoid PHP's session_cache_limiter adding conflicting caching information,
|
// if no caching ajax requests, disable ajax if is ajax request
|
||||||
// defaulting to "nocache" on most PHP configurations (see http://php.net/session_cache_limiter).
|
if (!$config->get('cache_ajax_requests') && Director::is_ajax()) {
|
||||||
// Since it's a deprecated HTTP 1.0 option, all modern HTTP clients and proxies should
|
$cacheControl->disableCache();
|
||||||
// prefer the caching information indicated through the "Cache-Control" header.
|
}
|
||||||
$responseHeaders["Pragma"] = "";
|
|
||||||
|
|
||||||
// To do: User-Agent should only be added in situations where you *are* actually
|
// Errors disable cache (unless some errors are cached intentionally by usercode)
|
||||||
// varying according to user-agent.
|
if ($body && $body->isError()) {
|
||||||
$vary = HTTP::config()->uninherited('vary');
|
// Even if publicCache(true) is specfied, errors will be uncachable
|
||||||
if ($vary && strlen($vary)) {
|
$cacheControl->disableCache(true);
|
||||||
$responseHeaders['Vary'] = $vary;
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$contentDisposition = null;
|
|
||||||
if ($body) {
|
|
||||||
// Grab header for checking. Unfortunately HTTPRequest uses a mistyped variant.
|
|
||||||
$contentDisposition = $body->getHeader('Content-disposition');
|
|
||||||
if (!$contentDisposition) {
|
|
||||||
$contentDisposition = $body->getHeader('Content-Disposition');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($body &&
|
// split the current vary header into it's parts and merge it with the config settings
|
||||||
Director::is_https() &&
|
// to create a list of unique vary values
|
||||||
isset($_SERVER['HTTP_USER_AGENT']) &&
|
$configVary = $config->get('vary');
|
||||||
strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')==true &&
|
$bodyVary = $body ? $body->getHeader('Vary') : '';
|
||||||
strstr($contentDisposition, 'attachment;')==true
|
$vary = self::combineVary($configVary, $bodyVary);
|
||||||
) {
|
if ($vary) {
|
||||||
// IE6-IE8 have problems saving files when https and no-cache are used
|
$responseHeaders['Vary'] = $vary;
|
||||||
// (http://support.microsoft.com/kb/323308)
|
}
|
||||||
// Note: this is also fixable by ticking "Do not save encrypted pages to disk" in advanced options.
|
|
||||||
$cacheControlHeaders['max-age'] = 3;
|
|
||||||
|
|
||||||
// Set empty pragma to avoid PHP's session_cache_limiter adding conflicting caching information,
|
// deal with IE6-IE8 problems with https and no-cache
|
||||||
// defaulting to "nocache" on most PHP configurations (see http://php.net/session_cache_limiter).
|
$contentDisposition = null;
|
||||||
// Since it's a deprecated HTTP 1.0 option, all modern HTTP clients and proxies should
|
if($body) {
|
||||||
// prefer the caching information indicated through the "Cache-Control" header.
|
// Grab header for checking. Unfortunately HTTPRequest uses a mistyped variant.
|
||||||
$responseHeaders["Pragma"] = "";
|
$contentDisposition = $body->getHeader('Content-Disposition');
|
||||||
} else {
|
}
|
||||||
$cacheControlHeaders['no-cache'] = "true";
|
|
||||||
$cacheControlHeaders['no-store'] = "true";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($cacheControlHeaders as $header => $value) {
|
if(
|
||||||
if (is_null($value)) {
|
$body &&
|
||||||
unset($cacheControlHeaders[$header]);
|
Director::is_https() &&
|
||||||
} elseif ((is_bool($value) && $value) || $value === "true") {
|
isset($_SERVER['HTTP_USER_AGENT']) &&
|
||||||
$cacheControlHeaders[$header] = $header;
|
strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') == true &&
|
||||||
} else {
|
strstr($contentDisposition, 'attachment;') == true &&
|
||||||
$cacheControlHeaders[$header] = $header . "=" . $value;
|
($cacheControl->hasDirective('no-cache') || $cacheControl->hasDirective('no-store'))
|
||||||
}
|
) {
|
||||||
}
|
// IE6-IE8 have problems saving files when https and no-cache/no-store are used
|
||||||
|
// (http://support.microsoft.com/kb/323308)
|
||||||
|
// Note: this is also fixable by ticking "Do not save encrypted pages to disk" in advanced options.
|
||||||
|
$cacheControl->privateCache(true);
|
||||||
|
}
|
||||||
|
|
||||||
$responseHeaders['Cache-Control'] = implode(', ', $cacheControlHeaders);
|
if (self::$modification_date) {
|
||||||
unset($cacheControlHeaders, $header, $value);
|
$responseHeaders["Last-Modified"] = self::gmt_date(self::$modification_date);
|
||||||
|
}
|
||||||
|
|
||||||
if (self::$modification_date && $cacheAge > 0) {
|
// if we can store the cache responses we should generate and send etags
|
||||||
$responseHeaders["Last-Modified"] = self::gmt_date(self::$modification_date);
|
if (!$cacheControl->hasDirective('no-store')) {
|
||||||
|
// Chrome ignores Varies when redirecting back (http://code.google.com/p/chromium/issues/detail?id=79758)
|
||||||
|
// which means that if you log out, you get redirected back to a page which Chrome then checks against
|
||||||
|
// last-modified (which passes, getting a 304)
|
||||||
|
// when it shouldn't be trying to use that page at all because it's the "logged in" version.
|
||||||
|
// By also using and etag that includes both the modification date and all the varies
|
||||||
|
// values which we also check against we can catch this and not return a 304
|
||||||
|
$etag = self::generateETag($body);
|
||||||
|
if ($etag) {
|
||||||
|
$responseHeaders['ETag'] = $etag;
|
||||||
|
|
||||||
// Chrome ignores Varies when redirecting back (http://code.google.com/p/chromium/issues/detail?id=79758)
|
// 304 response detection
|
||||||
// which means that if you log out, you get redirected back to a page which Chrome then checks against
|
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
|
||||||
// last-modified (which passes, getting a 304)
|
// As above, only 304 if the last request had all the same varies values
|
||||||
// when it shouldn't be trying to use that page at all because it's the "logged in" version.
|
// (or the etag isn't passed as part of the request - but with chrome it always is)
|
||||||
// By also using and etag that includes both the modification date and all the varies
|
$matchesEtag = $_SERVER['HTTP_IF_NONE_MATCH'] == $etag;
|
||||||
// values which we also check against we can catch this and not return a 304
|
|
||||||
$etagParts = array(self::$modification_date, serialize($_COOKIE));
|
|
||||||
$etagParts[] = Director::is_https() ? 'https' : 'http';
|
|
||||||
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
|
||||||
$etagParts[] = $_SERVER['HTTP_USER_AGENT'];
|
|
||||||
}
|
|
||||||
if (isset($_SERVER['HTTP_ACCEPT'])) {
|
|
||||||
$etagParts[] = $_SERVER['HTTP_ACCEPT'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$etag = sha1(implode(':', $etagParts));
|
if ($matchesEtag) {
|
||||||
$responseHeaders["ETag"] = $etag;
|
if ($body) {
|
||||||
|
$body->setStatusCode(304);
|
||||||
|
$body->setBody('');
|
||||||
|
} else {
|
||||||
|
// this is wrong, we need to send the same vary headers and so on
|
||||||
|
header('HTTP/1.0 304 Not Modified');
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 304 response detection
|
if ($cacheControl->hasDirective('max-age')) {
|
||||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
$expires = time() + $cacheControl->getDirective('max-age');
|
||||||
$ifModifiedSince = strtotime(stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']));
|
$responseHeaders["Expires"] = self::gmt_date($expires);
|
||||||
|
}
|
||||||
|
|
||||||
// As above, only 304 if the last request had all the same varies values
|
// etag needs to be a quoted string according to HTTP spec
|
||||||
// (or the etag isn't passed as part of the request - but with chrome it always is)
|
if (!empty($responseHeaders['ETag']) && 0 !== strpos($responseHeaders['ETag'], '"')) {
|
||||||
$matchesEtag = !isset($_SERVER['HTTP_IF_NONE_MATCH']) || $_SERVER['HTTP_IF_NONE_MATCH'] == $etag;
|
$responseHeaders['ETag'] = sprintf('"%s"', $responseHeaders['ETag']);
|
||||||
|
}
|
||||||
|
|
||||||
if ($ifModifiedSince >= self::$modification_date && $matchesEtag) {
|
// Merge with cache control headers
|
||||||
if ($body) {
|
$responseHeaders = array_merge($responseHeaders, $cacheControl->generateHeaders());
|
||||||
$body->setStatusCode(304);
|
|
||||||
$body->setBody('');
|
|
||||||
} else {
|
|
||||||
header('HTTP/1.0 304 Not Modified');
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$expires = time() + $cacheAge;
|
// Now that we've generated them, either output them or attach them to the SS_HTTPResponse as appropriate
|
||||||
$responseHeaders["Expires"] = self::gmt_date($expires);
|
foreach($responseHeaders as $k => $v) {
|
||||||
}
|
if($body) {
|
||||||
|
// Set the header now if it's not already set.
|
||||||
if (self::$etag) {
|
if ($body->getHeader($k) === null) {
|
||||||
$responseHeaders['ETag'] = self::$etag;
|
$body->addHeader($k, $v);
|
||||||
}
|
}
|
||||||
|
} elseif(!headers_sent()) {
|
||||||
// etag needs to be a quoted string according to HTTP spec
|
header("$k: $v");
|
||||||
if (!empty($responseHeaders['ETag']) && 0 !== strpos($responseHeaders['ETag'], '"')) {
|
}
|
||||||
$responseHeaders['ETag'] = sprintf('"%s"', $responseHeaders['ETag']);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Now that we've generated them, either output them or attach them to the HTTPResponse as appropriate
|
|
||||||
foreach ($responseHeaders as $k => $v) {
|
|
||||||
if ($body) {
|
|
||||||
// Set the header now if it's not already set.
|
|
||||||
if ($body->getHeader($k) === null) {
|
|
||||||
$body->addHeader($k, $v);
|
|
||||||
}
|
|
||||||
} elseif (!headers_sent()) {
|
|
||||||
header("$k: $v");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTTPResponse|string $response
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
protected static function generateETag($response)
|
||||||
|
{
|
||||||
|
// Explicit etag
|
||||||
|
if (self::$etag) {
|
||||||
|
return self::$etag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Existing e-tag
|
||||||
|
if ($response instanceof HTTPResponse && $response->getHeader('ETag')) {
|
||||||
|
return $response->getHeader('ETag');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate etag from body
|
||||||
|
$body = $response instanceof HTTPResponse
|
||||||
|
? $response->getBody()
|
||||||
|
: $response;
|
||||||
|
if ($body) {
|
||||||
|
return sprintf('"%s"', md5($response));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an {@link http://www.faqs.org/rfcs/rfc2822 RFC 2822} date in the GMT timezone (a timestamp
|
* Return an {@link http://www.faqs.org/rfcs/rfc2822 RFC 2822} date in the GMT timezone (a timestamp
|
||||||
* is always in GMT: the number of seconds since January 1 1970 00:00:00 GMT)
|
* is always in GMT: the number of seconds since January 1 1970 00:00:00 GMT)
|
||||||
@ -561,4 +601,22 @@ class HTTP
|
|||||||
{
|
{
|
||||||
return self::$cache_age;
|
return self::$cache_age;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combine vary strings
|
||||||
|
*
|
||||||
|
* @param string $vary,... Each vary as a separate arg
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function combineVary($vary)
|
||||||
|
{
|
||||||
|
$varies = array();
|
||||||
|
foreach (func_get_args() as $arg) {
|
||||||
|
$argVaries = array_filter(preg_split("/\s*,\s*/", trim($arg)));
|
||||||
|
if ($argVaries) {
|
||||||
|
$varies = array_merge($varies, $argVaries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return implode(', ', array_unique($varies));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,9 @@ class FlushMiddleware implements HTTPMiddleware
|
|||||||
public function process(HTTPRequest $request, callable $delegate)
|
public function process(HTTPRequest $request, callable $delegate)
|
||||||
{
|
{
|
||||||
if (array_key_exists('flush', $request->getVars())) {
|
if (array_key_exists('flush', $request->getVars())) {
|
||||||
|
// Disable cache when flushing
|
||||||
|
HTTPCacheControlMiddleware::singleton()->disableCache(true);
|
||||||
|
|
||||||
foreach (ClassInfo::implementorsOf(Flushable::class) as $class) {
|
foreach (ClassInfo::implementorsOf(Flushable::class) as $class) {
|
||||||
/** @var Flushable|string $class */
|
/** @var Flushable|string $class */
|
||||||
$class::flush();
|
$class::flush();
|
||||||
|
@ -41,6 +41,14 @@ class HTTPCacheControlMiddleware implements HTTPMiddleware, Resettable
|
|||||||
} catch (HTTPResponse_Exception $ex) {
|
} catch (HTTPResponse_Exception $ex) {
|
||||||
$response = $ex->getResponse();
|
$response = $ex->getResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If sessions exist we assume that the responses should not be cached by CDNs / proxies as we are
|
||||||
|
// likely to be supplying information relevant to the current user only
|
||||||
|
if ($request->getSession()->getAll()) {
|
||||||
|
// Don't force in case user code chooses to opt in to public caching
|
||||||
|
$this->privateCache();
|
||||||
|
}
|
||||||
|
|
||||||
HTTP::add_cache_headers($response);
|
HTTP::add_cache_headers($response);
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
@ -262,6 +270,17 @@ class HTTPCacheControlMiddleware implements HTTPMiddleware, Resettable
|
|||||||
return isset($this->stateDirectives[$state][$directive]);
|
return isset($this->stateDirectives[$state][$directive]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current state has the given directive.
|
||||||
|
*
|
||||||
|
* @param string $directive
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasDirective($directive)
|
||||||
|
{
|
||||||
|
return $this->hasStateDirective($this->getState(), $directive);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Low level method to get the value of a directive for a state.
|
* Low level method to get the value of a directive for a state.
|
||||||
* Returns false if there is no directive.
|
* Returns false if there is no directive.
|
||||||
@ -280,6 +299,38 @@ class HTTPCacheControlMiddleware implements HTTPMiddleware, Resettable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the given directive for the current state
|
||||||
|
*
|
||||||
|
* @param string $directive
|
||||||
|
* @return bool|int|string
|
||||||
|
*/
|
||||||
|
public function getDirective($directive)
|
||||||
|
{
|
||||||
|
return $this->getStateDirective($this->getState(), $directive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get directives for the given state
|
||||||
|
*
|
||||||
|
* @param string $state
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getStateDirectives($state)
|
||||||
|
{
|
||||||
|
return $this->stateDirectives[$state];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all directives for the currently active state
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDirectives()
|
||||||
|
{
|
||||||
|
return $this->getStateDirectives($this->getState());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cache should not store anything about the client request or server response.
|
* The cache should not store anything about the client request or server response.
|
||||||
* Affects all non-disabled states. Use setStateDirective() instead to set for a single state.
|
* Affects all non-disabled states. Use setStateDirective() instead to set for a single state.
|
||||||
@ -473,9 +524,9 @@ class HTTPCacheControlMiddleware implements HTTPMiddleware, Resettable
|
|||||||
*/
|
*/
|
||||||
protected function generateCacheHeader()
|
protected function generateCacheHeader()
|
||||||
{
|
{
|
||||||
$cacheControl = array();
|
$cacheControl = [];
|
||||||
foreach ($this->state as $directive => $value) {
|
foreach ($this->getDirectives() as $directive => $value) {
|
||||||
if (is_null($value)) {
|
if ($value === true) {
|
||||||
$cacheControl[] = $directive;
|
$cacheControl[] = $directive;
|
||||||
} else {
|
} else {
|
||||||
$cacheControl[] = $directive . '=' . $value;
|
$cacheControl[] = $directive . '=' . $value;
|
||||||
|
@ -6,6 +6,7 @@ use BadMethodCallException;
|
|||||||
use Exception;
|
use Exception;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
|
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
|
||||||
use SilverStripe\Core\ClassInfo;
|
use SilverStripe\Core\ClassInfo;
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Dev\Debug;
|
use SilverStripe\Dev\Debug;
|
||||||
@ -657,7 +658,7 @@ class RequestHandler extends ViewableData
|
|||||||
public function redirectBack()
|
public function redirectBack()
|
||||||
{
|
{
|
||||||
// Don't cache the redirect back ever
|
// Don't cache the redirect back ever
|
||||||
HTTP::set_cache_age(0);
|
HTTPCacheControlMiddleware::singleton()->disableCache(true);
|
||||||
|
|
||||||
// Prefer to redirect to ?BackURL, but fall back to Referer header
|
// Prefer to redirect to ?BackURL, but fall back to Referer header
|
||||||
// As a last resort redirect to base url
|
// As a last resort redirect to base url
|
||||||
|
Loading…
Reference in New Issue
Block a user