AssetMiddlewareTest.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice.
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 3.3.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\Routing\Middleware;
  17. use Cake\Http\ServerRequestFactory;
  18. use Cake\Routing\Middleware\AssetMiddleware;
  19. use Cake\TestSuite\TestCase;
  20. use PHPUnit\Framework\Attributes\DataProvider;
  21. use TestApp\Http\TestRequestHandler;
  22. /**
  23. * Test for AssetMiddleware
  24. */
  25. class AssetMiddlewareTest extends TestCase
  26. {
  27. /**
  28. * setup
  29. */
  30. public function setUp(): void
  31. {
  32. parent::setUp();
  33. $this->loadPlugins(['TestPlugin', 'Company/TestPluginThree']);
  34. }
  35. /**
  36. * tearDown
  37. */
  38. public function tearDown(): void
  39. {
  40. $this->clearPlugins();
  41. parent::tearDown();
  42. }
  43. /**
  44. * test that the if modified since header generates 304 responses
  45. */
  46. public function testCheckIfModifiedHeader(): void
  47. {
  48. $modified = filemtime(TEST_APP . 'Plugin/TestPlugin/webroot/root.js');
  49. $request = ServerRequestFactory::fromGlobals([
  50. 'REQUEST_URI' => '/test_plugin/root.js',
  51. 'HTTP_IF_MODIFIED_SINCE' => date(DATE_RFC7231, $modified),
  52. ]);
  53. $handler = new TestRequestHandler();
  54. $middleware = new AssetMiddleware();
  55. $res = $middleware->process($request, $handler);
  56. $body = $res->getBody()->getContents();
  57. $this->assertSame('', $body);
  58. $this->assertSame(304, $res->getStatusCode());
  59. $this->assertNotEmpty($res->getHeaderLine('Last-Modified'));
  60. }
  61. /**
  62. * test missing plugin assets.
  63. */
  64. public function testMissingPluginAsset(): void
  65. {
  66. $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/test_plugin/not_found.js']);
  67. $handler = new TestRequestHandler();
  68. $middleware = new AssetMiddleware();
  69. $res = $middleware->process($request, $handler);
  70. $body = $res->getBody()->getContents();
  71. $this->assertSame('', $body);
  72. }
  73. /**
  74. * Data provider for assets.
  75. *
  76. * @return array
  77. */
  78. public static function assetProvider(): array
  79. {
  80. return [
  81. // In plugin root.
  82. [
  83. '/test_plugin/root.js',
  84. TEST_APP . 'Plugin/TestPlugin/webroot/root.js',
  85. ],
  86. // Subdirectory
  87. [
  88. '/test_plugin/js/alert.js',
  89. TEST_APP . 'Plugin/TestPlugin/webroot/js/alert.js',
  90. ],
  91. // In path that matches the plugin name
  92. [
  93. '/test_plugin/js/test_plugin/test.js',
  94. TEST_APP . 'Plugin/TestPlugin/webroot/js/test_plugin/test.js',
  95. ],
  96. // In vendored plugin
  97. [
  98. '/company/test_plugin_three/css/company.css',
  99. TEST_APP . 'Plugin/Company/TestPluginThree/webroot/css/company.css',
  100. ],
  101. ];
  102. }
  103. /**
  104. * Test assets in a plugin.
  105. */
  106. #[DataProvider('assetProvider')]
  107. public function testPluginAsset(string $url, string $expectedFile): void
  108. {
  109. $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => $url]);
  110. $handler = new TestRequestHandler();
  111. $middleware = new AssetMiddleware();
  112. $res = $middleware->process($request, $handler);
  113. $body = $res->getBody()->getContents();
  114. $this->assertStringEqualsFile($expectedFile, $body);
  115. }
  116. /**
  117. * Test headers with plugin assets
  118. */
  119. public function testPluginAssetHeaders(): void
  120. {
  121. $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/test_plugin/root.js']);
  122. $handler = new TestRequestHandler();
  123. $modified = filemtime(TEST_APP . 'Plugin/TestPlugin/webroot/root.js');
  124. $expires = strtotime('+4 hours');
  125. $time = time();
  126. $middleware = new AssetMiddleware(['cacheTime' => '+4 hours']);
  127. $res = $middleware->process($request, $handler);
  128. $this->assertSame(
  129. 'application/javascript',
  130. $res->getHeaderLine('Content-Type')
  131. );
  132. $this->assertSame(
  133. gmdate(DATE_RFC7231, $time),
  134. $res->getHeaderLine('Date')
  135. );
  136. $this->assertSame(
  137. 'public,max-age=' . ($expires - $time),
  138. $res->getHeaderLine('Cache-Control')
  139. );
  140. $this->assertSame(
  141. gmdate(DATE_RFC7231, $modified),
  142. $res->getHeaderLine('Last-Modified')
  143. );
  144. $this->assertSame(
  145. gmdate(DATE_RFC7231, $expires),
  146. $res->getHeaderLine('Expires')
  147. );
  148. }
  149. /**
  150. * Test that // results in a 404
  151. */
  152. public function test404OnDoubleSlash(): void
  153. {
  154. $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '//index.php']);
  155. $handler = new TestRequestHandler();
  156. $middleware = new AssetMiddleware();
  157. $res = $middleware->process($request, $handler);
  158. $this->assertEmpty($res->getBody()->getContents());
  159. }
  160. /**
  161. * Test that .. results in a 404
  162. */
  163. public function test404OnDoubleDot(): void
  164. {
  165. $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/test_plugin/../webroot/root.js']);
  166. $handler = new TestRequestHandler();
  167. $middleware = new AssetMiddleware();
  168. $res = $middleware->process($request, $handler);
  169. $this->assertEmpty($res->getBody()->getContents());
  170. }
  171. /**
  172. * Test that hidden filenames result in a 404
  173. */
  174. public function test404OnHiddenFile(): void
  175. {
  176. $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/test_plugin/.hiddenfile']);
  177. $handler = new TestRequestHandler();
  178. $middleware = new AssetMiddleware();
  179. $res = $middleware->process($request, $handler);
  180. $this->assertEmpty($res->getBody()->getContents());
  181. }
  182. /**
  183. * Test that hidden filenames result in a 404
  184. */
  185. public function test404OnHiddenFolder(): void
  186. {
  187. $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/test_plugin/.hiddenfolder/some.js']);
  188. $handler = new TestRequestHandler();
  189. $middleware = new AssetMiddleware();
  190. $res = $middleware->process($request, $handler);
  191. $this->assertEmpty($res->getBody()->getContents());
  192. }
  193. }