2021-06-07 00:15:28 +08:00
|
|
|
<?php
|
|
|
|
|
2022-08-29 18:02:14 +09:00
|
|
|
declare(strict_types=1);
|
|
|
|
|
2021-07-19 21:32:33 +08:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2021-06-07 00:15:28 +08:00
|
|
|
namespace CodeIgniter;
|
2016-03-29 22:30:05 +09:00
|
|
|
|
2024-02-11 06:20:35 +09:00
|
|
|
use App\Controllers\Home;
|
2021-07-03 00:56:44 +08:00
|
|
|
use CodeIgniter\Config\Services;
|
2024-02-11 06:20:35 +09:00
|
|
|
use CodeIgniter\Debug\Timer;
|
2023-09-11 18:40:51 +08:00
|
|
|
use CodeIgniter\Exceptions\PageNotFoundException;
|
2023-11-19 17:56:33 +09:00
|
|
|
use CodeIgniter\HTTP\Method;
|
2022-03-19 22:52:14 +07:00
|
|
|
use CodeIgniter\HTTP\Response;
|
2020-04-23 01:27:54 +07:00
|
|
|
use CodeIgniter\Router\RouteCollection;
|
2021-02-28 06:57:05 +07:00
|
|
|
use CodeIgniter\Test\CIUnitTestCase;
|
2022-07-20 11:54:12 +09:00
|
|
|
use CodeIgniter\Test\Filters\CITestStreamFilter;
|
2020-04-23 01:27:54 +07:00
|
|
|
use CodeIgniter\Test\Mock\MockCodeIgniter;
|
|
|
|
use Config\App;
|
2022-09-02 15:24:54 +03:00
|
|
|
use Config\Cache;
|
2023-01-31 17:28:47 +09:00
|
|
|
use Config\Filters as FiltersConfig;
|
2021-02-28 06:57:05 +07:00
|
|
|
use Config\Modules;
|
2023-04-05 09:07:05 -05:00
|
|
|
use Config\Routing;
|
2024-05-06 09:19:46 +09:00
|
|
|
use PHPUnit\Framework\Attributes\BackupGlobals;
|
|
|
|
use PHPUnit\Framework\Attributes\DataProvider;
|
|
|
|
use PHPUnit\Framework\Attributes\Group;
|
|
|
|
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
|
2024-07-26 20:51:10 +08:00
|
|
|
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
2021-09-24 17:31:19 +09:00
|
|
|
use Tests\Support\Filters\Customfilter;
|
2023-09-12 01:46:44 +08:00
|
|
|
use Tests\Support\Filters\RedirectFilter;
|
2016-03-30 07:30:02 +09:00
|
|
|
|
2017-02-09 19:33:03 +09:00
|
|
|
/**
|
2021-06-25 22:27:37 +08:00
|
|
|
* @internal
|
2017-02-09 19:33:03 +09:00
|
|
|
*/
|
2024-04-23 01:29:05 +08:00
|
|
|
#[BackupGlobals(true)]
|
|
|
|
#[Group('Others')]
|
2024-05-08 00:05:51 +08:00
|
|
|
#[RunTestsInSeparateProcesses]
|
2021-06-25 22:27:37 +08:00
|
|
|
final class CodeIgniterTest extends CIUnitTestCase
|
2016-03-29 22:30:05 +09:00
|
|
|
{
|
2022-04-29 01:32:05 +07:00
|
|
|
private CodeIgniter $codeigniter;
|
2021-06-04 22:51:52 +08:00
|
|
|
|
2024-07-26 20:51:10 +08:00
|
|
|
#[WithoutErrorHandler]
|
2021-06-04 22:51:52 +08:00
|
|
|
protected function setUp(): void
|
|
|
|
{
|
|
|
|
parent::setUp();
|
2021-10-29 19:35:37 +08:00
|
|
|
$this->resetServices();
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
|
|
|
|
2021-06-25 23:35:25 +08:00
|
|
|
$this->codeigniter = new MockCodeIgniter(new App());
|
2022-09-20 17:12:18 +09:00
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$response = service('response');
|
2022-09-20 17:12:18 +09:00
|
|
|
$response->pretend();
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2021-06-24 23:37:45 +08:00
|
|
|
protected function tearDown(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
|
|
|
parent::tearDown();
|
|
|
|
|
2022-03-01 11:09:11 +09:00
|
|
|
$this->resetServices();
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunEmptyDefaultRoute(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php'];
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['argc'] = 1;
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('Welcome to CodeIgniter', $output);
|
|
|
|
}
|
|
|
|
|
2024-04-10 11:28:07 +09:00
|
|
|
public function testOutputBufferingControl(): void
|
2023-05-15 14:58:30 +08:00
|
|
|
{
|
|
|
|
ob_start();
|
|
|
|
$this->codeigniter->run();
|
|
|
|
ob_get_clean();
|
|
|
|
|
|
|
|
// 1 phpunit output buffering level
|
|
|
|
$this->assertSame(1, ob_get_level());
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunEmptyDefaultRouteReturnResponse(): void
|
2022-10-22 19:28:24 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php'];
|
|
|
|
$_SERVER['argc'] = 1;
|
|
|
|
|
2023-10-17 09:22:10 +09:00
|
|
|
$response = $this->codeigniter->run(null, true);
|
2022-10-22 19:28:24 +09:00
|
|
|
|
|
|
|
$this->assertStringContainsString('Welcome to CodeIgniter', $response->getBody());
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunClosureRoute(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', 'pages/about'];
|
2021-06-08 11:17:07 +08:00
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['REQUEST_URI'] = '/pages/about';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-07-29 22:59:04 +08:00
|
|
|
$routes->add('pages/(:segment)', static function ($segment): void {
|
2021-06-04 22:51:52 +08:00
|
|
|
echo 'You want to see "' . esc($segment) . '" page.';
|
|
|
|
});
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('You want to see "about" page.', $output);
|
|
|
|
}
|
|
|
|
|
2024-07-26 16:10:44 +09:00
|
|
|
/**
|
|
|
|
* @psalm-suppress UndefinedClass
|
|
|
|
*/
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRun404Override(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2024-02-01 09:54:02 +09:00
|
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
|
|
$_SERVER['REQUEST_URI'] = '/pages/about';
|
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2021-06-04 22:51:52 +08:00
|
|
|
$routes->setAutoRoute(false);
|
2024-02-01 09:54:02 +09:00
|
|
|
$routes->set404Override('Tests\Support\Errors::show404');
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run($routes);
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
2024-02-01 09:54:02 +09:00
|
|
|
$this->assertStringContainsString("Can't find a route for 'GET: pages/about'.", $output);
|
2024-02-11 10:15:04 +09:00
|
|
|
$this->assertSame(404, response()->getStatusCode());
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRun404OverrideControllerReturnsResponse(): void
|
2022-02-17 09:11:04 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-02-17 09:11:04 +09:00
|
|
|
$routes->setAutoRoute(false);
|
|
|
|
$routes->set404Override('Tests\Support\Controllers\Popcorn::pop');
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2022-02-17 09:11:04 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
2023-05-24 18:00:04 +08:00
|
|
|
$response = $this->codeigniter->run($routes, true);
|
2022-02-17 09:11:04 +09:00
|
|
|
|
2023-05-24 18:00:04 +08:00
|
|
|
$this->assertStringContainsString('Oops', $response->getBody());
|
|
|
|
$this->assertSame(567, $response->getStatusCode());
|
2022-02-17 09:11:04 +09:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRun404OverrideReturnResponse(): void
|
2022-10-22 19:28:24 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-10-22 19:28:24 +09:00
|
|
|
$routes->setAutoRoute(false);
|
|
|
|
$routes->set404Override('Tests\Support\Controllers\Popcorn::pop');
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2022-10-22 19:28:24 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
2023-10-17 09:22:10 +09:00
|
|
|
$response = $this->codeigniter->run($routes, true);
|
2022-10-22 19:28:24 +09:00
|
|
|
|
|
|
|
$this->assertStringContainsString('Oops', $response->getBody());
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRun404OverrideByClosure(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = new RouteCollection(service('locator'), new Modules(), new Routing());
|
2021-06-04 22:51:52 +08:00
|
|
|
$routes->setAutoRoute(false);
|
2023-07-29 22:59:04 +08:00
|
|
|
$routes->set404Override(static function (): void {
|
2021-06-04 22:51:52 +08:00
|
|
|
echo '404 Override by Closure.';
|
|
|
|
});
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run($routes);
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('404 Override by Closure.', $output);
|
2024-02-11 10:15:04 +09:00
|
|
|
$this->assertSame(404, response()->getStatusCode());
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testControllersCanReturnString(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', 'pages/about'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['REQUEST_URI'] = '/pages/about';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-01-31 17:43:32 +09:00
|
|
|
$routes->add(
|
|
|
|
'pages/(:segment)',
|
2025-01-13 11:03:02 +08:00
|
|
|
static fn ($segment): string => 'You want to see "' . esc($segment) . '" page.',
|
2023-01-31 17:43:32 +09:00
|
|
|
);
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('You want to see "about" page.', $output);
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testControllersCanReturnResponseObject(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', 'pages/about'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['REQUEST_URI'] = '/pages/about';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2021-06-07 03:44:42 +02:00
|
|
|
$routes->add('pages/(:segment)', static function ($segment) {
|
2024-11-01 17:00:17 +03:00
|
|
|
$response = service('response');
|
2022-09-02 09:32:01 +08:00
|
|
|
$string = "You want to see 'about' page.";
|
2021-06-08 01:26:32 +08:00
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
return $response->setBody($string);
|
|
|
|
});
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString("You want to see 'about' page.", $output);
|
|
|
|
}
|
|
|
|
|
2022-08-13 10:04:35 +09:00
|
|
|
/**
|
|
|
|
* @see https://github.com/codeigniter4/CodeIgniter4/issues/6358
|
|
|
|
*/
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testControllersCanReturnDownloadResponseObject(): void
|
2022-08-13 10:04:35 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', 'pages/about'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/pages/about';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2022-08-13 10:04:35 +09:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-08-13 10:04:35 +09:00
|
|
|
$routes->add('pages/(:segment)', static function ($segment) {
|
2024-11-01 17:00:17 +03:00
|
|
|
$response = service('response');
|
2022-08-13 10:04:35 +09:00
|
|
|
|
|
|
|
return $response->download('some.txt', 'some text', true);
|
|
|
|
});
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2022-08-13 10:04:35 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2022-08-13 10:04:35 +09:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertSame('some text', $output);
|
|
|
|
}
|
|
|
|
|
2023-07-30 09:19:54 +09:00
|
|
|
public function testRunExecuteFilterByClassName(): void
|
2021-09-24 17:31:19 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', 'pages/about'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/pages/about';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-09-24 17:31:19 +09:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-01-31 17:43:32 +09:00
|
|
|
$routes->add(
|
|
|
|
'pages/about',
|
2024-11-01 17:00:17 +03:00
|
|
|
static fn () => service('incomingrequest')->getBody(),
|
2025-01-13 11:03:02 +08:00
|
|
|
['filter' => Customfilter::class],
|
2023-01-31 17:43:32 +09:00
|
|
|
);
|
2021-09-24 17:31:19 +09:00
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-09-24 17:31:19 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-09-24 17:31:19 +09:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('http://hellowworld.com', $output);
|
2022-08-13 09:12:32 +09:00
|
|
|
|
|
|
|
$this->resetServices();
|
2021-09-24 17:31:19 +09:00
|
|
|
}
|
|
|
|
|
2024-04-10 11:28:07 +09:00
|
|
|
public function testRegisterSameFilterTwiceWithDifferentArgument(): void
|
2023-01-31 17:28:47 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', 'pages/about'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/pages/about';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2023-01-31 17:28:47 +09:00
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-01-31 17:28:47 +09:00
|
|
|
$routes->add(
|
|
|
|
'pages/about',
|
2024-11-01 17:00:17 +03:00
|
|
|
static fn () => service('incomingrequest')->getBody(),
|
2023-01-31 17:28:47 +09:00
|
|
|
// Set filter with no argument.
|
2025-01-13 11:03:02 +08:00
|
|
|
['filter' => 'test-customfilter'],
|
2023-01-31 17:28:47 +09:00
|
|
|
);
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2023-01-31 17:28:47 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
/** @var FiltersConfig $filterConfig */
|
|
|
|
$filterConfig = config('Filters');
|
|
|
|
$filterConfig->filters = [
|
|
|
|
// Set filter with argument.
|
|
|
|
'test-customfilter:arg1' => [
|
|
|
|
'before' => ['pages/*'],
|
|
|
|
],
|
|
|
|
];
|
2024-11-01 17:00:17 +03:00
|
|
|
service('filters', $filterConfig);
|
2023-01-31 17:28:47 +09:00
|
|
|
|
2024-06-20 14:19:27 +09:00
|
|
|
ob_start();
|
2023-01-31 17:28:47 +09:00
|
|
|
$this->codeigniter->run();
|
2024-06-20 14:19:27 +09:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('http://hellowworld.comhttp://hellowworld.com', $output);
|
2023-01-31 17:28:47 +09:00
|
|
|
|
|
|
|
$this->resetServices();
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testDisableControllerFilters(): void
|
2022-10-10 07:02:32 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', 'pages/about'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/pages/about';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2022-10-10 07:02:32 +09:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-10-10 07:02:32 +09:00
|
|
|
$routes->add(
|
|
|
|
'pages/about',
|
2024-11-01 17:00:17 +03:00
|
|
|
static fn () => service('incomingrequest')->getBody(),
|
2025-01-13 11:03:02 +08:00
|
|
|
['filter' => Customfilter::class],
|
2022-10-10 07:02:32 +09:00
|
|
|
);
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2022-10-10 07:02:32 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
$this->codeigniter->disableFilters();
|
|
|
|
$this->codeigniter->run();
|
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('', $output);
|
|
|
|
|
|
|
|
$this->resetServices();
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testResponseConfigEmpty(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$response = service('response', null, false);
|
2021-06-04 22:51:52 +08:00
|
|
|
|
2022-03-19 22:52:14 +07:00
|
|
|
$this->assertInstanceOf(Response::class, $response);
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRoutesIsEmpty(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', null, service('incomingrequest'), false);
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('Welcome to CodeIgniter', $output);
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testTransfersCorrectHTTPVersion(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/2.0';
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-24 15:43:23 +07:00
|
|
|
ob_get_clean();
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
$response = $this->getPrivateProperty($this->codeigniter, 'response');
|
|
|
|
|
2021-06-25 23:35:25 +08:00
|
|
|
$this->assertSame('2.0', $response->getProtocolVersion());
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testSupportsHttp3(): void
|
2022-09-26 22:16:41 -05:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/3.0';
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
$this->codeigniter->run();
|
|
|
|
ob_get_clean();
|
|
|
|
|
|
|
|
$response = $this->getPrivateProperty($this->codeigniter, 'response');
|
|
|
|
|
|
|
|
$this->assertSame('3.0', $response->getProtocolVersion());
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testIgnoringErrorSuppressedByAt(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
@unlink('inexistent-file');
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('Welcome to CodeIgniter', $output);
|
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunForceSecure(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2023-11-03 11:45:27 +09:00
|
|
|
$filterConfig = config(FiltersConfig::class);
|
|
|
|
$filterConfig->required['before'][] = 'forcehttps';
|
2021-06-25 23:35:25 +08:00
|
|
|
|
2023-11-03 11:45:27 +09:00
|
|
|
$config = config(App::class);
|
2021-06-04 22:51:52 +08:00
|
|
|
$config->forceGlobalSecureRequests = true;
|
2021-06-25 23:35:25 +08:00
|
|
|
|
|
|
|
$codeigniter = new MockCodeIgniter($config);
|
2022-02-03 17:02:19 +09:00
|
|
|
$codeigniter->setContext('web');
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
$this->getPrivateMethodInvoker($codeigniter, 'getRequestObject')();
|
|
|
|
$this->getPrivateMethodInvoker($codeigniter, 'getResponseObject')();
|
|
|
|
|
|
|
|
$response = $this->getPrivateProperty($codeigniter, 'response');
|
|
|
|
$this->assertNull($response->header('Location'));
|
|
|
|
|
2023-06-24 06:54:14 +08:00
|
|
|
$response = $codeigniter->run(null, true);
|
2021-06-04 22:51:52 +08:00
|
|
|
|
2023-02-23 16:16:40 +09:00
|
|
|
$this->assertSame('https://example.com/index.php/', $response->header('Location')->getValue());
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunRedirectionWithNamed(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', 'example'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['REQUEST_URI'] = '/example';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-07-29 22:59:04 +08:00
|
|
|
$routes->add('pages/named', static function (): void {
|
2021-06-04 22:51:52 +08:00
|
|
|
}, ['as' => 'name']);
|
|
|
|
$routes->addRedirect('example', 'name');
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
ob_get_clean();
|
|
|
|
$response = $this->getPrivateProperty($this->codeigniter, 'response');
|
2021-06-25 23:35:25 +08:00
|
|
|
$this->assertSame('http://example.com/pages/named', $response->header('Location')->getValue());
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunRedirectionWithURI(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', 'example'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['REQUEST_URI'] = '/example';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-07-29 22:59:04 +08:00
|
|
|
$routes->add('pages/uri', static function (): void {
|
2021-06-04 22:51:52 +08:00
|
|
|
});
|
|
|
|
$routes->addRedirect('example', 'pages/uri');
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
ob_get_clean();
|
|
|
|
$response = $this->getPrivateProperty($this->codeigniter, 'response');
|
2021-06-25 23:35:25 +08:00
|
|
|
$this->assertSame('http://example.com/pages/uri', $response->header('Location')->getValue());
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @see https://github.com/codeigniter4/CodeIgniter4/issues/3041
|
|
|
|
*/
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunRedirectionWithGET(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', 'example'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2023-04-20 21:26:20 +09:00
|
|
|
$_SERVER['REQUEST_URI'] = '/example';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2023-04-20 21:26:20 +09:00
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
2021-06-04 22:51:52 +08:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-04-20 21:59:55 +09:00
|
|
|
// addRedirect() sets status code 302 by default.
|
2021-06-04 22:51:52 +08:00
|
|
|
$routes->addRedirect('example', 'pages/notset');
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
ob_get_clean();
|
2023-04-20 21:26:20 +09:00
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$response = $this->getPrivateProperty($this->codeigniter, 'response');
|
2021-06-25 23:35:25 +08:00
|
|
|
$this->assertSame('http://example.com/pages/notset', $response->header('Location')->getValue());
|
2023-04-20 21:59:55 +09:00
|
|
|
$this->assertSame(302, $response->getStatusCode());
|
2023-04-20 21:26:20 +09:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunRedirectionWithGETAndHTTPCode301(): void
|
2023-04-20 21:26:20 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', 'example'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/example';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2023-04-20 21:26:20 +09:00
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-04-20 21:26:20 +09:00
|
|
|
$routes->addRedirect('example', 'pages/notset', 301);
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2023-04-20 21:26:20 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
$this->codeigniter->run();
|
|
|
|
ob_get_clean();
|
|
|
|
|
|
|
|
$response = $this->getPrivateProperty($this->codeigniter, 'response');
|
|
|
|
$this->assertSame(301, $response->getStatusCode());
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunRedirectionWithPOSTAndHTTPCode301(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', 'example'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['REQUEST_URI'] = '/example';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2021-06-04 22:51:52 +08:00
|
|
|
$routes->addRedirect('example', 'pages/notset', 301);
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
ob_get_clean();
|
2021-06-25 23:35:25 +08:00
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$response = $this->getPrivateProperty($this->codeigniter, 'response');
|
2023-04-20 21:59:55 +09:00
|
|
|
$this->assertSame(301, $response->getStatusCode());
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testStoresPreviousURL(): void
|
2021-09-15 01:47:19 +00:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', null, service('incomingrequest'), false);
|
2021-09-15 01:47:19 +00:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-09-15 01:47:19 +00:00
|
|
|
ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertArrayHasKey('_ci_previous_url', $_SESSION);
|
2023-02-23 16:16:40 +09:00
|
|
|
$this->assertSame('http://example.com/index.php/', $_SESSION['_ci_previous_url']);
|
2021-09-15 01:47:19 +00:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testNotStoresPreviousURL(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', 'example'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['REQUEST_URI'] = '/example';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2021-06-04 22:51:52 +08:00
|
|
|
$routes->addRedirect('example', 'pages/notset', 301);
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2021-06-04 22:51:52 +08:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
ob_get_clean();
|
2021-09-15 01:47:19 +00:00
|
|
|
|
|
|
|
$this->assertArrayNotHasKey('_ci_previous_url', $_SESSION);
|
2021-06-04 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testNotStoresPreviousURLByCheckingContentType(): void
|
2022-05-30 11:08:37 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', 'image'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/image';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2022-05-30 11:08:37 +09:00
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-05-30 11:08:37 +09:00
|
|
|
$routes->add('image', static function () {
|
2024-11-01 17:00:17 +03:00
|
|
|
$response = service('response');
|
2022-05-30 11:08:37 +09:00
|
|
|
|
|
|
|
return $response->setContentType('image/jpeg', '');
|
|
|
|
});
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2022-05-30 11:08:37 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2022-05-30 11:08:37 +09:00
|
|
|
ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertArrayNotHasKey('_ci_previous_url', $_SESSION);
|
|
|
|
}
|
|
|
|
|
2021-06-04 22:51:52 +08:00
|
|
|
/**
|
|
|
|
* The method after all test, reset Servces:: config
|
|
|
|
* Can't use static::tearDownAfterClass. This will cause a buffer exception
|
|
|
|
* need improve
|
|
|
|
*/
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunDefaultRoute(): void
|
2021-06-04 22:51:52 +08:00
|
|
|
{
|
2021-06-25 23:35:25 +08:00
|
|
|
$_SERVER['argv'] = ['index.php', '/'];
|
2021-06-04 22:51:52 +08:00
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2021-06-04 22:51:52 +08:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('Welcome to CodeIgniter', $output);
|
|
|
|
}
|
2022-02-02 16:18:14 +09:00
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testRunCLIRoute(): void
|
2022-02-02 16:18:14 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php', 'cli'];
|
|
|
|
$_SERVER['argc'] = 2;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/cli';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = 'public/index.php';
|
2022-02-02 16:18:14 +09:00
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'CLI';
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-02-02 16:18:14 +09:00
|
|
|
$routes->cli('cli', '\Tests\Support\Controllers\Popcorn::index');
|
|
|
|
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2022-02-02 16:18:14 +09:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('Method Not Allowed', $output);
|
|
|
|
}
|
2022-02-09 11:40:48 +09:00
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testSpoofRequestMethodCanUsePUT(): void
|
2022-02-09 11:40:48 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php'];
|
|
|
|
$_SERVER['argc'] = 1;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2022-02-09 11:40:48 +09:00
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
|
|
|
2023-11-19 17:56:33 +09:00
|
|
|
$_POST['_method'] = Method::PUT;
|
2022-02-09 11:40:48 +09:00
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-03-01 11:09:11 +09:00
|
|
|
$routes->setDefaultNamespace('App\Controllers');
|
|
|
|
$routes->resetRoutes();
|
|
|
|
$routes->post('/', 'Home::index');
|
|
|
|
$routes->put('/', 'Home::index');
|
|
|
|
|
2022-02-09 11:40:48 +09:00
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2022-02-09 11:40:48 +09:00
|
|
|
ob_get_clean();
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$this->assertSame(Method::PUT, service('incomingrequest')->getMethod());
|
2022-02-09 11:40:48 +09:00
|
|
|
}
|
|
|
|
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testSpoofRequestMethodCannotUseGET(): void
|
2022-02-09 11:40:48 +09:00
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php'];
|
|
|
|
$_SERVER['argc'] = 1;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2022-02-09 11:40:48 +09:00
|
|
|
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
|
|
|
|
|
|
$_POST['_method'] = 'GET';
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-03-01 11:09:11 +09:00
|
|
|
$routes->setDefaultNamespace('App\Controllers');
|
|
|
|
$routes->resetRoutes();
|
|
|
|
$routes->post('/', 'Home::index');
|
|
|
|
$routes->get('/', 'Home::index');
|
|
|
|
|
2022-02-09 11:40:48 +09:00
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2022-02-09 11:40:48 +09:00
|
|
|
ob_get_clean();
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$this->assertSame('POST', service('incomingrequest')->getMethod());
|
2022-02-09 11:40:48 +09:00
|
|
|
}
|
2022-07-20 11:54:12 +09:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @see https://github.com/codeigniter4/CodeIgniter4/issues/6281
|
|
|
|
*/
|
2023-07-29 22:59:04 +08:00
|
|
|
public function testPageCacheSendSecureHeaders(): void
|
2022-07-20 11:54:12 +09:00
|
|
|
{
|
|
|
|
// Suppress command() output
|
2022-08-29 16:33:35 +08:00
|
|
|
CITestStreamFilter::registration();
|
|
|
|
CITestStreamFilter::addErrorFilter();
|
|
|
|
CITestStreamFilter::addOutputFilter();
|
2022-07-20 11:54:12 +09:00
|
|
|
|
|
|
|
// Clear Page cache
|
|
|
|
command('cache:clear');
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/test';
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2022-07-20 11:54:12 +09:00
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2022-07-20 11:54:12 +09:00
|
|
|
$routes->add('test', static function () {
|
|
|
|
CodeIgniter::cache(3600);
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$response = service('response');
|
2022-09-02 09:32:01 +08:00
|
|
|
$string = 'This is a test page. Elapsed time: {elapsed_time}';
|
2022-07-20 11:54:12 +09:00
|
|
|
|
|
|
|
return $response->setBody($string);
|
|
|
|
});
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest'));
|
2022-07-20 11:54:12 +09:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
2023-01-31 17:28:47 +09:00
|
|
|
/** @var FiltersConfig $filterConfig */
|
2022-07-20 11:54:12 +09:00
|
|
|
$filterConfig = config('Filters');
|
|
|
|
$filterConfig->globals['after'] = ['secureheaders'];
|
2024-11-01 17:00:17 +03:00
|
|
|
service('filters', $filterConfig);
|
2022-07-20 11:54:12 +09:00
|
|
|
|
|
|
|
// The first response to be cached.
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2022-07-20 11:54:12 +09:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('This is a test page', $output);
|
2024-11-01 17:00:17 +03:00
|
|
|
$response = service('response');
|
2022-07-20 11:54:12 +09:00
|
|
|
$headers = $response->headers();
|
|
|
|
$this->assertArrayHasKey('X-Frame-Options', $headers);
|
|
|
|
|
|
|
|
// The second response from the Page cache.
|
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2022-07-20 11:54:12 +09:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('This is a test page', $output);
|
2024-11-01 17:00:17 +03:00
|
|
|
$response = service('response');
|
2022-07-20 11:54:12 +09:00
|
|
|
$headers = $response->headers();
|
|
|
|
$this->assertArrayHasKey('X-Frame-Options', $headers);
|
|
|
|
|
|
|
|
// Clear Page cache
|
|
|
|
command('cache:clear');
|
|
|
|
|
2022-08-29 16:33:35 +08:00
|
|
|
// Remove stream filters
|
|
|
|
CITestStreamFilter::removeErrorFilter();
|
|
|
|
CITestStreamFilter::removeOutputFilter();
|
2022-07-20 11:54:12 +09:00
|
|
|
}
|
2022-09-02 15:24:54 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array|bool $cacheQueryStringValue
|
2022-09-04 19:44:31 +08:00
|
|
|
*
|
2022-09-02 15:24:54 +03:00
|
|
|
* @see https://github.com/codeigniter4/CodeIgniter4/pull/6410
|
|
|
|
*/
|
2024-04-23 01:29:05 +08:00
|
|
|
#[DataProvider('providePageCacheWithCacheQueryString')]
|
2023-01-31 17:43:32 +09:00
|
|
|
public function testPageCacheWithCacheQueryString(
|
|
|
|
$cacheQueryStringValue,
|
|
|
|
int $expectedPagesInCache,
|
2025-01-13 11:03:02 +08:00
|
|
|
array $testingUrls,
|
2023-07-30 09:19:54 +09:00
|
|
|
): void {
|
2022-09-02 15:24:54 +03:00
|
|
|
// Suppress command() output
|
2023-02-21 16:40:08 +09:00
|
|
|
CITestStreamFilter::registration();
|
|
|
|
CITestStreamFilter::addOutputFilter();
|
|
|
|
CITestStreamFilter::addErrorFilter();
|
2022-09-02 15:24:54 +03:00
|
|
|
|
|
|
|
// Create cache config with cacheQueryString value from the dataProvider
|
2023-02-23 15:45:31 +09:00
|
|
|
$cacheConfig = config(Cache::class);
|
2022-09-02 15:24:54 +03:00
|
|
|
$cacheConfig->cacheQueryString = $cacheQueryStringValue;
|
|
|
|
|
|
|
|
// Clear cache before starting the test
|
|
|
|
command('cache:clear');
|
|
|
|
|
|
|
|
// Calculate amount of items in the cache before the test
|
|
|
|
$cache = \Config\Services::cache();
|
|
|
|
$cacheStartCounter = count($cache->getCacheInfo());
|
|
|
|
|
|
|
|
// Generate request to each URL from the testing array
|
|
|
|
foreach ($testingUrls as $testingUrl) {
|
2023-02-23 15:45:31 +09:00
|
|
|
$this->resetServices();
|
2022-09-02 15:24:54 +03:00
|
|
|
$_SERVER['REQUEST_URI'] = '/' . $testingUrl;
|
2023-07-03 12:42:27 +09:00
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
2023-02-23 15:45:31 +09:00
|
|
|
$this->codeigniter = new MockCodeIgniter(new App());
|
|
|
|
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes', true);
|
2023-02-23 15:45:31 +09:00
|
|
|
$routePath = explode('?', $testingUrl)[0];
|
|
|
|
$string = 'This is a test page, to check cache configuration';
|
|
|
|
$routes->add($routePath, static function () use ($string) {
|
2024-11-01 17:00:17 +03:00
|
|
|
service('responsecache')->setTtl(60);
|
|
|
|
$response = service('response');
|
2022-09-02 15:24:54 +03:00
|
|
|
|
|
|
|
return $response->setBody($string);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Inject router
|
2024-11-01 17:00:17 +03:00
|
|
|
$router = service('router', $routes, service('incomingrequest', null, false));
|
2022-09-02 15:24:54 +03:00
|
|
|
Services::injectMock('router', $router);
|
|
|
|
|
2023-01-31 17:43:32 +09:00
|
|
|
// Cache the page output using default caching function and $cacheConfig
|
|
|
|
// with value from the data provider
|
2023-02-23 15:45:31 +09:00
|
|
|
ob_start();
|
2022-09-20 17:12:18 +09:00
|
|
|
$this->codeigniter->run();
|
2023-02-23 15:45:31 +09:00
|
|
|
$output = ob_get_clean();
|
|
|
|
|
|
|
|
$this->assertSame($string, $output);
|
2022-09-02 15:24:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate how much cached items exist in the cache after the test requests
|
|
|
|
$cacheEndCounter = count($cache->getCacheInfo());
|
|
|
|
$newPagesCached = $cacheEndCounter - $cacheStartCounter;
|
|
|
|
|
|
|
|
// Clear cache after the test
|
|
|
|
command('cache:clear');
|
|
|
|
|
|
|
|
// Check that amount of new items created in the cache matching expected value from the data provider
|
|
|
|
$this->assertSame($expectedPagesInCache, $newPagesCached);
|
|
|
|
|
|
|
|
// Remove stream filters
|
2023-02-21 16:40:08 +09:00
|
|
|
CITestStreamFilter::removeOutputFilter();
|
|
|
|
CITestStreamFilter::removeErrorFilter();
|
2022-09-02 15:24:54 +03:00
|
|
|
}
|
|
|
|
|
2023-08-03 18:13:11 +08:00
|
|
|
public static function providePageCacheWithCacheQueryString(): iterable
|
2022-09-02 15:24:54 +03:00
|
|
|
{
|
|
|
|
$testingUrls = [
|
2023-01-31 17:43:32 +09:00
|
|
|
// URL #1
|
|
|
|
'test',
|
|
|
|
// URL #2
|
|
|
|
'test?important_parameter=1',
|
|
|
|
// URL #3
|
|
|
|
'test?important_parameter=2',
|
|
|
|
// URL #4
|
|
|
|
'test?important_parameter=1¬_important_parameter=2',
|
|
|
|
// URL #5
|
|
|
|
'test?important_parameter=1¬_important_parameter=2&another_not_important_parameter=3',
|
2022-09-02 15:24:54 +03:00
|
|
|
];
|
|
|
|
|
|
|
|
return [
|
2023-01-31 17:43:32 +09:00
|
|
|
// We expect only 1 page in the cache, because when cacheQueryString
|
|
|
|
// is set to false, all GET parameter should be ignored, and page URI
|
|
|
|
// will be absolutely same "/test" string for all 5 requests
|
|
|
|
'$cacheQueryString=false' => [false, 1, $testingUrls],
|
|
|
|
// We expect all 5 pages in the cache, because when cacheQueryString
|
|
|
|
// is set to true, all GET parameter should be processed as unique requests
|
|
|
|
'$cacheQueryString=true' => [true, 5, $testingUrls],
|
|
|
|
// We expect only 3 pages in the cache, because when cacheQueryString
|
|
|
|
// is set to array with important parameters, we should ignore all
|
|
|
|
// parameters thats not in the array. Only URL #1, URL #2 and URL #3
|
|
|
|
// should be cached. URL #4 and URL #5 is duplication of URL #2
|
|
|
|
// (with value ?important_parameter=1), so they should not be processed
|
|
|
|
// as new unique requests and application should return already cached
|
|
|
|
// page for URL #2
|
|
|
|
'$cacheQueryString=array' => [['important_parameter'], 3, $testingUrls],
|
2022-09-02 15:24:54 +03:00
|
|
|
];
|
|
|
|
}
|
2023-09-11 18:40:51 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* See https://github.com/codeigniter4/CodeIgniter4/issues/7205
|
|
|
|
*/
|
|
|
|
public function testRunControllerNotFoundBeforeFilter(): void
|
|
|
|
{
|
|
|
|
$_SERVER['argv'] = ['index.php'];
|
|
|
|
$_SERVER['argc'] = 1;
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/cannotFound';
|
|
|
|
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
|
|
|
|
|
|
|
// Inject mock router.
|
2024-11-01 17:00:17 +03:00
|
|
|
$routes = service('routes');
|
2023-09-11 18:40:51 +08:00
|
|
|
$routes->setAutoRoute(true);
|
|
|
|
|
2023-09-12 01:46:44 +08:00
|
|
|
// Inject the before filter.
|
|
|
|
$filterConfig = config('Filters');
|
|
|
|
$filterConfig->aliases['redirectFilter'] = RedirectFilter::class;
|
|
|
|
$filterConfig->globals['before'] = ['redirectFilter'];
|
2024-11-01 17:00:17 +03:00
|
|
|
service('filters', $filterConfig);
|
2023-09-12 01:46:44 +08:00
|
|
|
|
2023-09-11 18:40:51 +08:00
|
|
|
$this->expectException(PageNotFoundException::class);
|
|
|
|
|
|
|
|
$this->codeigniter->run($routes);
|
|
|
|
}
|
2024-02-11 06:20:35 +09:00
|
|
|
|
|
|
|
public function testStartControllerPermitsInvoke(): void
|
|
|
|
{
|
|
|
|
$this->setPrivateProperty($this->codeigniter, 'benchmark', new Timer());
|
|
|
|
$this->setPrivateProperty($this->codeigniter, 'controller', '\\' . Home::class);
|
|
|
|
$startController = $this->getPrivateMethodInvoker($this->codeigniter, 'startController');
|
|
|
|
|
|
|
|
$this->setPrivateProperty($this->codeigniter, 'method', '__invoke');
|
|
|
|
$startController();
|
|
|
|
|
|
|
|
// No PageNotFoundException
|
|
|
|
$this->assertTrue(true);
|
|
|
|
}
|
2016-03-29 22:30:05 +09:00
|
|
|
}
|