2018-06-12 15:26:19 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace SilverStripe\Control\Tests\Middleware;
|
|
|
|
|
2018-07-06 12:48:30 +02:00
|
|
|
use SilverStripe\Control\HTTPResponse;
|
2018-06-12 15:26:19 +02:00
|
|
|
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
|
|
|
|
use SilverStripe\Dev\SapphireTest;
|
|
|
|
|
|
|
|
class HTTPCacheControlMiddlewareTest extends SapphireTest
|
|
|
|
{
|
2021-10-27 04:39:47 +02:00
|
|
|
protected function setUp(): void
|
2018-06-13 07:56:47 +02:00
|
|
|
{
|
|
|
|
parent::setUp();
|
|
|
|
// Set to disabled at null forcing level
|
|
|
|
HTTPCacheControlMiddleware::config()
|
2018-07-06 12:48:30 +02:00
|
|
|
->set('defaultState', HTTPCacheControlMiddleware::STATE_ENABLED)
|
2018-06-13 07:56:47 +02:00
|
|
|
->set('defaultForcingLevel', 0);
|
|
|
|
HTTPCacheControlMiddleware::reset();
|
|
|
|
}
|
|
|
|
|
2018-07-06 12:48:30 +02:00
|
|
|
public function provideCacheStates()
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
['enableCache', false],
|
|
|
|
['publicCache', false],
|
|
|
|
['privateCache', false],
|
|
|
|
['disableCache', true],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider provideCacheStates
|
|
|
|
*/
|
|
|
|
public function testCheckDefaultStates($state, $immutable)
|
|
|
|
{
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
$cc->{$state}();
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('must-revalidate', $response->getHeader('cache-control'));
|
2018-07-06 12:48:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider provideCacheStates
|
|
|
|
*/
|
|
|
|
public function testSetMaxAge($state, $immutable)
|
|
|
|
{
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
$cc->{$state}();
|
|
|
|
|
|
|
|
$originalResponse = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($originalResponse);
|
|
|
|
|
|
|
|
$cc->setMaxAge('300');
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
|
|
|
if ($immutable) {
|
|
|
|
$this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control'));
|
|
|
|
} else {
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('max-age=300', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('no-cache', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('no-store', $response->getHeader('cache-control'));
|
2018-07-06 12:48:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-19 01:20:58 +02:00
|
|
|
public function testEnableCacheWithMaxAge()
|
|
|
|
{
|
|
|
|
$maxAge = 300;
|
|
|
|
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
$cc->enableCache(false, $maxAge);
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('max-age=300', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('no-cache', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('no-store', $response->getHeader('cache-control'));
|
2018-07-19 01:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testEnableCacheWithMaxAgeAppliesWhenLevelDoesNot()
|
|
|
|
{
|
|
|
|
$maxAge = 300;
|
|
|
|
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
$cc->privateCache(true);
|
|
|
|
$cc->enableCache(false, $maxAge);
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('max-age=300', $response->getHeader('cache-control'));
|
2018-07-19 01:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testPublicCacheWithMaxAge()
|
|
|
|
{
|
|
|
|
$maxAge = 300;
|
|
|
|
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
$cc->publicCache(false, $maxAge);
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('max-age=300', $response->getHeader('cache-control'));
|
2018-07-19 01:20:58 +02:00
|
|
|
// STATE_PUBLIC doesn't contain no-cache or no-store headers to begin with,
|
|
|
|
// so can't test their removal effectively
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringNotContainsString('no-cache', $response->getHeader('cache-control'));
|
2018-07-19 01:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testPublicCacheWithMaxAgeAppliesWhenLevelDoesNot()
|
|
|
|
{
|
|
|
|
$maxAge = 300;
|
|
|
|
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
$cc->privateCache(true);
|
|
|
|
$cc->publicCache(false, $maxAge);
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('max-age=300', $response->getHeader('cache-control'));
|
2018-07-19 01:20:58 +02:00
|
|
|
}
|
|
|
|
|
2018-07-06 12:48:30 +02:00
|
|
|
/**
|
|
|
|
* @dataProvider provideCacheStates
|
|
|
|
*/
|
|
|
|
public function testSetNoStore($state, $immutable)
|
|
|
|
{
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
$cc->setMaxAge('300');
|
|
|
|
$cc->setSharedMaxAge('300');
|
|
|
|
|
|
|
|
$cc->{$state}();
|
|
|
|
|
|
|
|
$originalResponse = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($originalResponse);
|
|
|
|
|
|
|
|
$cc->setNoStore();
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
|
|
|
if ($immutable) {
|
|
|
|
$this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control'));
|
|
|
|
} else {
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('no-store', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('max-age', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('s-maxage', $response->getHeader('cache-control'));
|
2018-07-06 12:48:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider provideCacheStates
|
|
|
|
*/
|
|
|
|
public function testSetNoCache($state, $immutable)
|
|
|
|
{
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
$cc->setMaxAge('300');
|
|
|
|
$cc->setSharedMaxAge('300');
|
|
|
|
|
|
|
|
$cc->{$state}();
|
|
|
|
|
|
|
|
$originalResponse = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($originalResponse);
|
|
|
|
|
|
|
|
$cc->setNoCache();
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
|
|
|
if ($immutable) {
|
|
|
|
$this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control'));
|
|
|
|
} else {
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('no-cache', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('max-age', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('s-maxage', $response->getHeader('cache-control'));
|
2018-07-06 12:48:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider provideCacheStates
|
|
|
|
*/
|
|
|
|
public function testSetSharedMaxAge($state, $immutable)
|
|
|
|
{
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
|
|
|
|
$cc->{$state}();
|
|
|
|
|
|
|
|
$originalResponse = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($originalResponse);
|
|
|
|
|
|
|
|
$cc->setSharedMaxAge('300');
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
|
|
|
if ($immutable) {
|
|
|
|
$this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control'));
|
|
|
|
} else {
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('s-maxage=300', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('no-cache', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('no-store', $response->getHeader('cache-control'));
|
2018-07-06 12:48:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider provideCacheStates
|
|
|
|
*/
|
|
|
|
public function testSetMustRevalidate($state, $immutable)
|
|
|
|
{
|
|
|
|
$cc = HTTPCacheControlMiddleware::singleton();
|
|
|
|
|
|
|
|
$cc->{$state}();
|
|
|
|
|
|
|
|
$originalResponse = new HTTPResponse();
|
|
|
|
$cc->applyToResponse($originalResponse);
|
|
|
|
|
|
|
|
$cc->setMustRevalidate();
|
|
|
|
|
|
|
|
$response = new HTTPResponse();
|
|
|
|
|
|
|
|
$cc->applyToResponse($response);
|
|
|
|
|
|
|
|
if ($immutable) {
|
|
|
|
$this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control'));
|
|
|
|
} else {
|
2021-10-27 04:39:47 +02:00
|
|
|
$this->assertStringContainsString('must-revalidate', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('max-age', $response->getHeader('cache-control'));
|
|
|
|
$this->assertStringNotContainsString('s-maxage', $response->getHeader('cache-control'));
|
2018-07-06 12:48:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-12 15:26:19 +02:00
|
|
|
public function testCachingPriorities()
|
|
|
|
{
|
|
|
|
$hcc = new HTTPCacheControlMiddleware();
|
2018-07-06 12:48:30 +02:00
|
|
|
$this->assertFalse($this->isDisabled($hcc), 'caching starts as disabled');
|
2018-06-12 15:26:19 +02:00
|
|
|
|
|
|
|
$hcc->enableCache();
|
|
|
|
$this->assertFalse($this->isDisabled($hcc));
|
|
|
|
|
|
|
|
$hcc->publicCache();
|
|
|
|
$this->assertTrue($this->isPublic($hcc), 'public can be set at start');
|
|
|
|
|
|
|
|
$hcc->privateCache();
|
|
|
|
$this->assertTrue($this->isPrivate($hcc), 'private overrides public');
|
|
|
|
|
|
|
|
$hcc->publicCache();
|
|
|
|
$this->assertFalse($this->isPublic($hcc), 'public does not overrides private');
|
|
|
|
|
|
|
|
$hcc->disableCache();
|
|
|
|
$this->assertTrue($this->isDisabled($hcc), 'disabled overrides private');
|
|
|
|
|
|
|
|
$hcc->privateCache();
|
|
|
|
$this->assertFalse($this->isPrivate($hcc), 'private does not override disabled');
|
|
|
|
|
|
|
|
$hcc->enableCache(true);
|
|
|
|
$this->assertFalse($this->isDisabled($hcc));
|
|
|
|
|
|
|
|
$hcc->publicCache(true);
|
|
|
|
$this->assertTrue($this->isPublic($hcc), 'force-public overrides disabled');
|
|
|
|
|
|
|
|
$hcc->privateCache();
|
|
|
|
$this->assertFalse($this->isPrivate($hcc), 'private does not overrdie force-public');
|
|
|
|
|
|
|
|
$hcc->privateCache(true);
|
|
|
|
$this->assertTrue($this->isPrivate($hcc), 'force-private overrides force-public');
|
|
|
|
|
|
|
|
$hcc->publicCache(true);
|
|
|
|
$this->assertFalse($this->isPublic($hcc), 'force-public does not override force-private');
|
|
|
|
|
|
|
|
$hcc->disableCache(true);
|
|
|
|
$this->assertTrue($this->isDisabled($hcc), 'force-disabled overrides force-private');
|
|
|
|
|
|
|
|
$hcc->publicCache(true);
|
|
|
|
$this->assertFalse($this->isPublic($hcc), 'force-public does not overrides force-disabled');
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function isPrivate(HTTPCacheControlMiddleware $hcc)
|
|
|
|
{
|
|
|
|
return $hcc->hasDirective('private') && !$hcc->hasDirective('public') && !$hcc->hasDirective('no-cache');
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function isPublic(HTTPCacheControlMiddleware $hcc)
|
|
|
|
{
|
|
|
|
return $hcc->hasDirective('public') && !$hcc->hasDirective('private') && !$hcc->hasDirective('no-cache');
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function isDisabled(HTTPCacheControlMiddleware $hcc)
|
|
|
|
{
|
2018-07-06 12:48:30 +02:00
|
|
|
return $hcc->hasDirective('no-store') && !$hcc->hasDirective('private') && !$hcc->hasDirective('public');
|
2018-06-12 15:26:19 +02:00
|
|
|
}
|
|
|
|
}
|