mirror of
https://github.com/codeigniter4/CodeIgniter4.git
synced 2025-02-20 11:44:28 +08:00
Merge pull request #7644 from kenjis/refactor-PageCache
refactor: extract ResponseCache class for Web Page Caching
This commit is contained in:
commit
0d154876b5
@ -222,6 +222,10 @@ parameters:
|
||||
- Cache
|
||||
skip_violations:
|
||||
# Individual class exemptions
|
||||
CodeIgniter\Cache\ResponseCache:
|
||||
- CodeIgniter\HTTP\CLIRequest
|
||||
- CodeIgniter\HTTP\IncomingRequest
|
||||
- CodeIgniter\HTTP\ResponseInterface
|
||||
CodeIgniter\Entity\Cast\URICast:
|
||||
- CodeIgniter\HTTP\URI
|
||||
CodeIgniter\Log\Handlers\ChromeLoggerHandler:
|
||||
|
@ -25,16 +25,6 @@ parameters:
|
||||
count: 1
|
||||
path: system/Cache/Handlers/RedisHandler.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method CodeIgniter\\\\HTTP\\\\Request\\:\\:getPost\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: system/CodeIgniter.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method CodeIgniter\\\\HTTP\\\\Request\\:\\:setLocale\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: system/CodeIgniter.php
|
||||
|
||||
-
|
||||
message: "#^Property CodeIgniter\\\\Database\\\\BaseBuilder\\:\\:\\$db \\(CodeIgniter\\\\Database\\\\BaseConnection\\) in empty\\(\\) is not falsy\\.$#"
|
||||
count: 1
|
||||
|
149
system/Cache/ResponseCache.php
Normal file
149
system/Cache/ResponseCache.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Cache;
|
||||
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
use CodeIgniter\HTTP\IncomingRequest;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Config\Cache as CacheConfig;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Web Page Caching
|
||||
*/
|
||||
final class ResponseCache
|
||||
{
|
||||
/**
|
||||
* Whether to take the URL query string into consideration when generating
|
||||
* output cache files. Valid options are:
|
||||
*
|
||||
* false = Disabled
|
||||
* true = Enabled, take all query parameters into account.
|
||||
* Please be aware that this may result in numerous cache
|
||||
* files generated for the same page over and over again.
|
||||
* array('q') = Enabled, but only take into account the specified list
|
||||
* of query parameters.
|
||||
*
|
||||
* @var bool|string[]
|
||||
*/
|
||||
private $cacheQueryString = false;
|
||||
|
||||
/**
|
||||
* Cache time to live.
|
||||
*
|
||||
* @var int seconds
|
||||
*/
|
||||
private int $ttl = 0;
|
||||
|
||||
private CacheInterface $cache;
|
||||
|
||||
public function __construct(CacheConfig $config, CacheInterface $cache)
|
||||
{
|
||||
$this->cacheQueryString = $config->cacheQueryString;
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setTtl(int $ttl)
|
||||
{
|
||||
$this->ttl = $ttl;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the cache key to use from the current request.
|
||||
*
|
||||
* @param CLIRequest|IncomingRequest $request
|
||||
*
|
||||
* @internal for testing purposes only
|
||||
*/
|
||||
public function generateCacheKey($request): string
|
||||
{
|
||||
if ($request instanceof CLIRequest) {
|
||||
return md5($request->getPath());
|
||||
}
|
||||
|
||||
$uri = clone $request->getUri();
|
||||
|
||||
$query = $this->cacheQueryString
|
||||
? $uri->getQuery(is_array($this->cacheQueryString) ? ['only' => $this->cacheQueryString] : [])
|
||||
: '';
|
||||
|
||||
return md5($uri->setFragment('')->setQuery($query));
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the response.
|
||||
*
|
||||
* @param CLIRequest|IncomingRequest $request
|
||||
*/
|
||||
public function make($request, ResponseInterface $response): bool
|
||||
{
|
||||
if ($this->ttl === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$headers = [];
|
||||
|
||||
foreach ($response->headers() as $header) {
|
||||
$headers[$header->getName()] = $header->getValueLine();
|
||||
}
|
||||
|
||||
return $this->cache->save(
|
||||
$this->generateCacheKey($request),
|
||||
serialize(['headers' => $headers, 'output' => $response->getBody()]),
|
||||
$this->ttl
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cached response for the request.
|
||||
*
|
||||
* @param CLIRequest|IncomingRequest $request
|
||||
*/
|
||||
public function get($request, ResponseInterface $response): ?ResponseInterface
|
||||
{
|
||||
if ($cachedResponse = $this->cache->get($this->generateCacheKey($request))) {
|
||||
$cachedResponse = unserialize($cachedResponse);
|
||||
|
||||
if (
|
||||
! is_array($cachedResponse)
|
||||
|| ! isset($cachedResponse['output'])
|
||||
|| ! isset($cachedResponse['headers'])
|
||||
) {
|
||||
throw new Exception('Error unserializing page cache');
|
||||
}
|
||||
|
||||
$headers = $cachedResponse['headers'];
|
||||
$output = $cachedResponse['output'];
|
||||
|
||||
// Clear all default headers
|
||||
foreach (array_keys($response->headers()) as $key) {
|
||||
$response->removeHeader($key);
|
||||
}
|
||||
|
||||
// Set cached headers
|
||||
foreach ($headers as $name => $value) {
|
||||
$response->setHeader($name, $value);
|
||||
}
|
||||
|
||||
$response->setBody($output);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
namespace CodeIgniter;
|
||||
|
||||
use Closure;
|
||||
use CodeIgniter\Cache\ResponseCache;
|
||||
use CodeIgniter\Debug\Timer;
|
||||
use CodeIgniter\Events\Events;
|
||||
use CodeIgniter\Exceptions\FrameworkException;
|
||||
@ -84,7 +85,7 @@ class CodeIgniter
|
||||
/**
|
||||
* Current request.
|
||||
*
|
||||
* @var CLIRequest|IncomingRequest|Request|null
|
||||
* @var CLIRequest|IncomingRequest|null
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
@ -127,6 +128,8 @@ class CodeIgniter
|
||||
* Cache expiration time
|
||||
*
|
||||
* @var int seconds
|
||||
*
|
||||
* @deprecated 4.4.0 Moved to ResponseCache::$ttl. No longer used.
|
||||
*/
|
||||
protected static $cacheTTL = 0;
|
||||
|
||||
@ -175,6 +178,11 @@ class CodeIgniter
|
||||
*/
|
||||
protected int $bufferLevel;
|
||||
|
||||
/**
|
||||
* Web Page Caching
|
||||
*/
|
||||
protected ResponseCache $pageCache;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
@ -182,6 +190,8 @@ class CodeIgniter
|
||||
{
|
||||
$this->startTime = microtime(true);
|
||||
$this->config = $config;
|
||||
|
||||
$this->pageCache = Services::responsecache();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -330,7 +340,7 @@ class CodeIgniter
|
||||
);
|
||||
}
|
||||
|
||||
static::$cacheTTL = 0;
|
||||
$this->pageCache->setTtl(0);
|
||||
$this->bufferLevel = ob_get_level();
|
||||
|
||||
$this->startBenchmark();
|
||||
@ -463,7 +473,7 @@ class CodeIgniter
|
||||
return $possibleResponse;
|
||||
}
|
||||
|
||||
if ($possibleResponse instanceof Request) {
|
||||
if ($possibleResponse instanceof IncomingRequest || $possibleResponse instanceof CLIRequest) {
|
||||
$this->request = $possibleResponse;
|
||||
}
|
||||
}
|
||||
@ -517,9 +527,7 @@ class CodeIgniter
|
||||
// Cache it without the performance metrics replaced
|
||||
// so that we can have live speed updates along the way.
|
||||
// Must be run after filters to preserve the Response headers.
|
||||
if (static::$cacheTTL > 0) {
|
||||
$this->cachePage($cacheConfig);
|
||||
}
|
||||
$this->pageCache->make($this->request, $this->response);
|
||||
|
||||
// Update the performance metrics
|
||||
$body = $this->response->getBody();
|
||||
@ -603,9 +611,11 @@ class CodeIgniter
|
||||
* Sets a Request object to be used for this request.
|
||||
* Used when running certain tests.
|
||||
*
|
||||
* @param CLIRequest|IncomingRequest $request
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRequest(Request $request)
|
||||
public function setRequest($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
|
||||
@ -674,27 +684,11 @@ class CodeIgniter
|
||||
*/
|
||||
public function displayCache(Cache $config)
|
||||
{
|
||||
if ($cachedResponse = cache()->get($this->generateCacheName($config))) {
|
||||
$cachedResponse = unserialize($cachedResponse);
|
||||
if (! is_array($cachedResponse) || ! isset($cachedResponse['output']) || ! isset($cachedResponse['headers'])) {
|
||||
throw new Exception('Error unserializing page cache');
|
||||
}
|
||||
|
||||
$headers = $cachedResponse['headers'];
|
||||
$output = $cachedResponse['output'];
|
||||
|
||||
// Clear all default headers
|
||||
foreach (array_keys($this->response->headers()) as $key) {
|
||||
$this->response->removeHeader($key);
|
||||
}
|
||||
|
||||
// Set cached headers
|
||||
foreach ($headers as $name => $value) {
|
||||
$this->response->setHeader($name, $value);
|
||||
}
|
||||
if ($cachedResponse = $this->pageCache->get($this->request, $this->response)) {
|
||||
$this->response = $cachedResponse;
|
||||
|
||||
$this->totalTime = $this->benchmark->getElapsedTime('total_execution');
|
||||
$output = $this->displayPerformanceMetrics($output);
|
||||
$output = $this->displayPerformanceMetrics($cachedResponse->getBody());
|
||||
$this->response->setBody($output);
|
||||
|
||||
return $this->response;
|
||||
@ -705,6 +699,8 @@ class CodeIgniter
|
||||
|
||||
/**
|
||||
* Tells the app that the final output should be cached.
|
||||
*
|
||||
* @deprecated 4.4.0 Moved to ResponseCache::setTtl(). to No longer used.
|
||||
*/
|
||||
public static function cache(int $time)
|
||||
{
|
||||
@ -716,6 +712,8 @@ class CodeIgniter
|
||||
* full-page caching for very high performance.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @deprecated 4.4.0 No longer used.
|
||||
*/
|
||||
public function cachePage(Cache $config)
|
||||
{
|
||||
@ -741,6 +739,8 @@ class CodeIgniter
|
||||
|
||||
/**
|
||||
* Generates the cache name to use for our full-page caching.
|
||||
*
|
||||
* @deprecated 4.4.0 No longer used.
|
||||
*/
|
||||
protected function generateCacheName(Cache $config): string
|
||||
{
|
||||
|
@ -14,6 +14,7 @@ namespace CodeIgniter\Config;
|
||||
use CodeIgniter\Autoloader\Autoloader;
|
||||
use CodeIgniter\Autoloader\FileLocator;
|
||||
use CodeIgniter\Cache\CacheInterface;
|
||||
use CodeIgniter\Cache\ResponseCache;
|
||||
use CodeIgniter\CLI\Commands;
|
||||
use CodeIgniter\CodeIgniter;
|
||||
use CodeIgniter\Database\ConnectionInterface;
|
||||
@ -117,6 +118,7 @@ use Config\View as ConfigView;
|
||||
* @method static View renderer($viewPath = null, ConfigView $config = null, $getShared = true)
|
||||
* @method static IncomingRequest|CLIRequest request(App $config = null, $getShared = true)
|
||||
* @method static ResponseInterface response(App $config = null, $getShared = true)
|
||||
* @method static ResponseCache responsecache(?Cache $config = null, ?CacheInterface $cache = null, bool $getShared = true)
|
||||
* @method static Router router(RouteCollectionInterface $routes = null, Request $request = null, $getShared = true)
|
||||
* @method static RouteCollection routes($getShared = true)
|
||||
* @method static Security security(App $config = null, $getShared = true)
|
||||
|
@ -13,6 +13,7 @@ namespace CodeIgniter\Config;
|
||||
|
||||
use CodeIgniter\Cache\CacheFactory;
|
||||
use CodeIgniter\Cache\CacheInterface;
|
||||
use CodeIgniter\Cache\ResponseCache;
|
||||
use CodeIgniter\CLI\Commands;
|
||||
use CodeIgniter\CodeIgniter;
|
||||
use CodeIgniter\Database\ConnectionInterface;
|
||||
@ -438,6 +439,23 @@ class Services extends BaseService
|
||||
return new Negotiate($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ResponseCache.
|
||||
*
|
||||
* @return ResponseCache
|
||||
*/
|
||||
public static function responsecache(?Cache $config = null, ?CacheInterface $cache = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('responsecache', $config, $cache);
|
||||
}
|
||||
|
||||
$config ??= config(Cache::class);
|
||||
$cache ??= AppServices::cache();
|
||||
|
||||
return new ResponseCache($config, $cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the appropriate pagination handler.
|
||||
*
|
||||
|
@ -104,12 +104,13 @@ class Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a simple way to tie into the main CodeIgniter class and
|
||||
* tell it how long to cache the current page for.
|
||||
* How long to cache the current page for.
|
||||
*
|
||||
* @params int $time time to live in seconds.
|
||||
*/
|
||||
protected function cachePage(int $time)
|
||||
{
|
||||
CodeIgniter::cache($time);
|
||||
Services::responsecache()->setTtl($time);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace CodeIgniter\Test;
|
||||
|
||||
use CodeIgniter\Events\Events;
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
use CodeIgniter\HTTP\Exceptions\RedirectException;
|
||||
use CodeIgniter\HTTP\IncomingRequest;
|
||||
use CodeIgniter\HTTP\Request;
|
||||
@ -328,11 +329,13 @@ class FeatureTestCase extends CIUnitTestCase
|
||||
*
|
||||
* Always populate the GET vars based on the URI.
|
||||
*
|
||||
* @return Request
|
||||
* @param CLIRequest|IncomingRequest $request
|
||||
*
|
||||
* @return CLIRequest|IncomingRequest
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
protected function populateGlobals(string $method, Request $request, ?array $params = null)
|
||||
protected function populateGlobals(string $method, $request, ?array $params = null)
|
||||
{
|
||||
// $params should set the query vars if present,
|
||||
// otherwise set it from the URL.
|
||||
@ -357,10 +360,13 @@ class FeatureTestCase extends CIUnitTestCase
|
||||
* This allows the body to be formatted in a way that the controller is going to
|
||||
* expect as in the case of testing a JSON or XML API.
|
||||
*
|
||||
* @param array|null $params The parameters to be formatted and put in the body. If this is empty, it will get the
|
||||
* what has been loaded into the request global of the request class.
|
||||
* @param CLIRequest|IncomingRequest $request
|
||||
* @param array|null $params The parameters to be formatted and put in the body. If this is empty, it will get the
|
||||
* what has been loaded into the request global of the request class.
|
||||
*
|
||||
* @return CLIRequest|IncomingRequest
|
||||
*/
|
||||
protected function setRequestBody(Request $request, ?array $params = null): Request
|
||||
protected function setRequestBody($request, ?array $params = null)
|
||||
{
|
||||
if (isset($this->requestBody) && $this->requestBody !== '') {
|
||||
$request->setBody($this->requestBody);
|
||||
|
249
tests/system/Cache/ResponseCacheTest.php
Normal file
249
tests/system/Cache/ResponseCacheTest.php
Normal file
@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Cache;
|
||||
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
use CodeIgniter\HTTP\IncomingRequest;
|
||||
use CodeIgniter\HTTP\Response;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\HTTP\URI;
|
||||
use CodeIgniter\HTTP\UserAgent;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use Config\App as AppConfig;
|
||||
use Config\Cache as CacheConfig;
|
||||
use ErrorException;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @backupGlobals enabled
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @group Others
|
||||
*/
|
||||
final class ResponseCacheTest extends CIUnitTestCase
|
||||
{
|
||||
private AppConfig $appConfig;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->appConfig = new AppConfig();
|
||||
}
|
||||
|
||||
private function createIncomingRequest(
|
||||
string $uri = '',
|
||||
array $query = [],
|
||||
?AppConfig $appConfig = null
|
||||
): IncomingRequest {
|
||||
$_POST = $_GET = $_SERVER = $_REQUEST = $_ENV = $_COOKIE = $_SESSION = [];
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/' . $uri . ($query ? '?' . http_build_query($query) : '');
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
$appConfig ??= $this->appConfig;
|
||||
|
||||
$siteUri = new URI($appConfig->baseURL . $uri);
|
||||
if ($query !== []) {
|
||||
$_GET = $_REQUEST = $query;
|
||||
$siteUri->setQueryArray($query);
|
||||
}
|
||||
|
||||
return new IncomingRequest(
|
||||
$appConfig,
|
||||
$siteUri,
|
||||
null,
|
||||
new UserAgent()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param list<string> $params
|
||||
*/
|
||||
private function createCLIRequest(array $params = [], ?AppConfig $appConfig = null): CLIRequest
|
||||
{
|
||||
$_POST = $_GET = $_SERVER = $_REQUEST = $_ENV = $_COOKIE = $_SESSION = [];
|
||||
|
||||
$_SERVER['argv'] = ['public/index.php', ...$params];
|
||||
$_SERVER['SCRIPT_NAME'] = 'public/index.php';
|
||||
|
||||
$appConfig ??= $this->appConfig;
|
||||
|
||||
return new CLIRequest($appConfig);
|
||||
}
|
||||
|
||||
private function createResponseCache(?CacheConfig $cacheConfig = null): ResponseCache
|
||||
{
|
||||
$cache = mock(CacheFactory::class);
|
||||
|
||||
$cacheConfig ??= new CacheConfig();
|
||||
|
||||
return (new ResponseCache($cacheConfig, $cache))->setTtl(300);
|
||||
}
|
||||
|
||||
public function testCachePageIncomingRequest()
|
||||
{
|
||||
$pageCache = $this->createResponseCache();
|
||||
|
||||
$request = $this->createIncomingRequest('foo/bar');
|
||||
|
||||
$response = new Response($this->appConfig);
|
||||
$response->setHeader('ETag', 'abcd1234');
|
||||
$response->setBody('The response body.');
|
||||
|
||||
$return = $pageCache->make($request, $response);
|
||||
|
||||
$this->assertTrue($return);
|
||||
|
||||
// Check cache with a request with the same URI path.
|
||||
$request = $this->createIncomingRequest('foo/bar');
|
||||
$cachedResponse = $pageCache->get($request, new Response($this->appConfig));
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $cachedResponse);
|
||||
$this->assertSame('The response body.', $cachedResponse->getBody());
|
||||
$this->assertSame('abcd1234', $cachedResponse->getHeaderLine('ETag'));
|
||||
|
||||
// Check cache with a request with the same URI path and different query string.
|
||||
$request = $this->createIncomingRequest('foo/bar', ['foo' => 'bar', 'bar' => 'baz']);
|
||||
$cachedResponse = $pageCache->get($request, new Response($this->appConfig));
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $cachedResponse);
|
||||
$this->assertSame('The response body.', $cachedResponse->getBody());
|
||||
$this->assertSame('abcd1234', $cachedResponse->getHeaderLine('ETag'));
|
||||
|
||||
// Check cache with another request with the different URI path.
|
||||
$request = $this->createIncomingRequest('another');
|
||||
|
||||
$cachedResponse = $pageCache->get($request, new Response($this->appConfig));
|
||||
|
||||
$this->assertNull($cachedResponse);
|
||||
}
|
||||
|
||||
public function testCachePageIncomingRequestWithCacheQueryString()
|
||||
{
|
||||
$cacheConfig = new CacheConfig();
|
||||
$cacheConfig->cacheQueryString = true;
|
||||
$pageCache = $this->createResponseCache($cacheConfig);
|
||||
|
||||
$request = $this->createIncomingRequest('foo/bar', ['foo' => 'bar', 'bar' => 'baz']);
|
||||
|
||||
$response = new Response($this->appConfig);
|
||||
$response->setHeader('ETag', 'abcd1234');
|
||||
$response->setBody('The response body.');
|
||||
|
||||
$return = $pageCache->make($request, $response);
|
||||
|
||||
$this->assertTrue($return);
|
||||
|
||||
// Check cache with a request with the same URI path and same query string.
|
||||
$this->createIncomingRequest('foo/bar', ['foo' => 'bar', 'bar' => 'baz']);
|
||||
$cachedResponse = $pageCache->get($request, new Response($this->appConfig));
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $cachedResponse);
|
||||
$this->assertSame('The response body.', $cachedResponse->getBody());
|
||||
$this->assertSame('abcd1234', $cachedResponse->getHeaderLine('ETag'));
|
||||
|
||||
// Check cache with a request with the same URI path and different query string.
|
||||
$request = $this->createIncomingRequest('foo/bar', ['xfoo' => 'bar', 'bar' => 'baz']);
|
||||
$cachedResponse = $pageCache->get($request, new Response($this->appConfig));
|
||||
|
||||
$this->assertNull($cachedResponse);
|
||||
|
||||
// Check cache with another request with the different URI path.
|
||||
$request = $this->createIncomingRequest('another');
|
||||
|
||||
$cachedResponse = $pageCache->get($request, new Response($this->appConfig));
|
||||
|
||||
$this->assertNull($cachedResponse);
|
||||
}
|
||||
|
||||
public function testCachePageCLIRequest()
|
||||
{
|
||||
$pageCache = $this->createResponseCache();
|
||||
|
||||
$request = $this->createCLIRequest(['foo', 'bar']);
|
||||
|
||||
$response = new Response($this->appConfig);
|
||||
$response->setBody('The response body.');
|
||||
|
||||
$return = $pageCache->make($request, $response);
|
||||
|
||||
$this->assertTrue($return);
|
||||
|
||||
// Check cache with a request with the same params.
|
||||
$request = $this->createCLIRequest(['foo', 'bar']);
|
||||
$cachedResponse = $pageCache->get($request, new Response($this->appConfig));
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $cachedResponse);
|
||||
$this->assertSame('The response body.', $cachedResponse->getBody());
|
||||
|
||||
// Check cache with another request with the different params.
|
||||
$request = $this->createCLIRequest(['baz']);
|
||||
|
||||
$cachedResponse = $pageCache->get($request, new Response($this->appConfig));
|
||||
|
||||
$this->assertNull($cachedResponse);
|
||||
}
|
||||
|
||||
public function testUnserializeError()
|
||||
{
|
||||
$this->expectException(ErrorException::class);
|
||||
$this->expectExceptionMessage('unserialize(): Error at offset 0 of 12 bytes');
|
||||
|
||||
$cache = mock(CacheFactory::class);
|
||||
$cacheConfig = new CacheConfig();
|
||||
$pageCache = new ResponseCache($cacheConfig, $cache);
|
||||
|
||||
$request = $this->createIncomingRequest('foo/bar');
|
||||
|
||||
$response = new Response($this->appConfig);
|
||||
$response->setHeader('ETag', 'abcd1234');
|
||||
$response->setBody('The response body.');
|
||||
|
||||
$pageCache->make($request, $response);
|
||||
|
||||
$cacheKey = $pageCache->generateCacheKey($request);
|
||||
|
||||
// Save invalid data.
|
||||
$cache->save($cacheKey, 'Invalid data');
|
||||
|
||||
// Check cache with a request with the same URI path.
|
||||
$pageCache->get($request, new Response($this->appConfig));
|
||||
}
|
||||
|
||||
public function testInvalidCacheError()
|
||||
{
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('Error unserializing page cache');
|
||||
|
||||
$cache = mock(CacheFactory::class);
|
||||
$cacheConfig = new CacheConfig();
|
||||
$pageCache = new ResponseCache($cacheConfig, $cache);
|
||||
|
||||
$request = $this->createIncomingRequest('foo/bar');
|
||||
|
||||
$response = new Response($this->appConfig);
|
||||
$response->setHeader('ETag', 'abcd1234');
|
||||
$response->setBody('The response body.');
|
||||
|
||||
$pageCache->make($request, $response);
|
||||
|
||||
$cacheKey = $pageCache->generateCacheKey($request);
|
||||
|
||||
// Save invalid data.
|
||||
$cache->save($cacheKey, serialize(['a' => '1']));
|
||||
|
||||
// Check cache with a request with the same URI path.
|
||||
$pageCache->get($request, new Response($this->appConfig));
|
||||
}
|
||||
}
|
@ -96,6 +96,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/pages/about';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -193,6 +194,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/pages/about';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -216,6 +218,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/pages/about';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -244,6 +247,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/pages/about';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -268,6 +272,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/pages/about';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -298,6 +303,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/pages/about';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
$routes = Services::routes();
|
||||
$routes->add(
|
||||
@ -331,6 +337,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/pages/about';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -452,6 +459,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/example';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -475,6 +483,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/example';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -501,6 +510,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/example';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
|
||||
@ -527,6 +537,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/example';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
|
||||
@ -551,6 +562,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/example';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['REQUEST_METHOD'] = 'POST';
|
||||
|
||||
@ -615,6 +627,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/example';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
|
||||
@ -638,6 +651,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/image';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
// Inject mock router.
|
||||
$routes = Services::routes();
|
||||
@ -679,6 +693,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 2;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/cli';
|
||||
$_SERVER['SCRIPT_NAME'] = 'public/index.php';
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['REQUEST_METHOD'] = 'CLI';
|
||||
|
||||
@ -698,6 +713,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 1;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['REQUEST_METHOD'] = 'POST';
|
||||
|
||||
@ -722,6 +738,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
$_SERVER['argc'] = 1;
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['REQUEST_METHOD'] = 'POST';
|
||||
|
||||
@ -754,6 +771,7 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
command('cache:clear');
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/test';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
$routes = Services::routes();
|
||||
$routes->add('test', static function () {
|
||||
@ -832,13 +850,14 @@ final class CodeIgniterTest extends CIUnitTestCase
|
||||
foreach ($testingUrls as $testingUrl) {
|
||||
$this->resetServices();
|
||||
$_SERVER['REQUEST_URI'] = '/' . $testingUrl;
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$this->codeigniter = new MockCodeIgniter(new App());
|
||||
|
||||
$routes = Services::routes(true);
|
||||
$routePath = explode('?', $testingUrl)[0];
|
||||
$string = 'This is a test page, to check cache configuration';
|
||||
$routes->add($routePath, static function () use ($string) {
|
||||
CodeIgniter::cache(60);
|
||||
Services::responsecache()->setTtl(60);
|
||||
$response = Services::response();
|
||||
|
||||
return $response->setBody($string);
|
||||
|
@ -52,15 +52,24 @@ Parameter Type Changes
|
||||
|
||||
- **Services:** The first parameter of ``Services::security()`` has been
|
||||
changed from ``Config\App`` to ``Config\Security``.
|
||||
- **Session:** The second parameter of ``Session::__construct()`` has been
|
||||
changed from ``Config\App`` to ``Config\Session``.
|
||||
- **Session:** The first parameter of ``__construct()`` in ``BaseHandler``,
|
||||
``DatabaseHandler``, ``FileHandler``, ``MemcachedHandler``, and ``RedisHandler``
|
||||
has been changed from ``Config\App`` to ``Config\Session``.
|
||||
- **Session:**
|
||||
- The second parameter of ``Session::__construct()`` has been changed from
|
||||
``Config\App`` to ``Config\Session``.
|
||||
- The first parameter of ``__construct()`` in the database's ``BaseHandler``,
|
||||
``DatabaseHandler``, ``FileHandler``, ``MemcachedHandler``, and ``RedisHandler``
|
||||
has been changed from ``Config\App`` to ``Config\Session``.
|
||||
- **Security:** The first parameter of ``Security::__construct()`` has been
|
||||
changed from ``Config\App`` to ``Config\Security``.
|
||||
- **Validation:** The method signature of ``Validation::check()`` has been changed.
|
||||
The ``string`` typehint on the ``$rule`` parameter was removed.
|
||||
- **CodeIgniter:** The method signature of ``CodeIgniter::setRequest()`` has been
|
||||
changed. The ``Request`` typehint on the ``$request`` parameter was removed.
|
||||
- **FeatureTestCase:**
|
||||
- The method signature of ``FeatureTestCase::populateGlobals()`` has been
|
||||
changed. The ``Request`` typehint on the ``$request`` parameter was removed.
|
||||
- The method signature of ``FeatureTestCase::setRequestBody()`` has been
|
||||
changed. The ``Request`` typehint on the ``$request`` parameter and the
|
||||
return type ``Request`` were removed.
|
||||
|
||||
Added Parameters
|
||||
----------------
|
||||
@ -179,7 +188,12 @@ Deprecations
|
||||
are deprecated. Because these methods have been moved to ``BaseExceptionHandler`` or
|
||||
``ExceptionHandler``.
|
||||
- **Autoloader:** ``Autoloader::sanitizeFilename()`` is deprecated.
|
||||
- **CodeIgniter:** ``CodeIgniter::$returnResponse`` property is deprecated. No longer used.
|
||||
- **CodeIgniter:**
|
||||
- ``CodeIgniter::$returnResponse`` property is deprecated. No longer used.
|
||||
- ``CodeIgniter::$cacheTTL`` property is deprecated. No longer used. Use ``ResponseCache`` instead.
|
||||
- ``CodeIgniter::cache()`` method is deprecated. No longer used. Use ``ResponseCache`` instead.
|
||||
- ``CodeIgniter::cachePage()`` method is deprecated. No longer used. Use ``ResponseCache`` instead.
|
||||
- ``CodeIgniter::generateCacheName()`` method is deprecated. No longer used. Use ``ResponseCache`` instead.
|
||||
- **RedirectException:** ``\CodeIgniter\Router\Exceptions\RedirectException`` is deprecated. Use ``\CodeIgniter\HTTP\Exceptions\RedirectException`` instead.
|
||||
- **Session:** The property ``$sessionDriverName``, ``$sessionCookieName``,
|
||||
``$sessionExpiration``, ``$sessionSavePath``, ``$sessionMatchIP``,
|
||||
|
Loading…
x
Reference in New Issue
Block a user