AssetMiddlewareTest.php 6.6 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 TestApp\Http\TestRequestHandler;
  21. /**
  22. * Test for AssetMiddleware
  23. */
  24. class AssetMiddlewareTest extends TestCase
  25. {
  26. /**
  27. * setup
  28. */
  29. public function setUp(): void
  30. {
  31. parent::setUp();
  32. $this->loadPlugins(['TestPlugin', 'Company/TestPluginThree']);
  33. }
  34. /**
  35. * tearDown
  36. */
  37. public function tearDown(): void
  38. {
  39. $this->clearPlugins();
  40. parent::tearDown();
  41. }
  42. /**
  43. * test that the if modified since header generates 304 responses
  44. */
  45. public function testCheckIfModifiedHeader(): void
  46. {
  47. $modified = filemtime(TEST_APP . 'Plugin/TestPlugin/webroot/root.js');
  48. $request = ServerRequestFactory::fromGlobals([
  49. 'REQUEST_URI' => '/test_plugin/root.js',
  50. 'HTTP_IF_MODIFIED_SINCE' => date(DATE_RFC7231, $modified),
  51. ]);
  52. $handler = new TestRequestHandler();
  53. $middleware = new AssetMiddleware();
  54. $res = $middleware->process($request, $handler);
  55. $body = $res->getBody()->getContents();
  56. $this->assertSame('', $body);
  57. $this->assertSame(304, $res->getStatusCode());
  58. $this->assertNotEmpty($res->getHeaderLine('Last-Modified'));
  59. }
  60. /**
  61. * test missing plugin assets.
  62. */
  63. public function testMissingPluginAsset(): void
  64. {
  65. $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/test_plugin/not_found.js']);
  66. $handler = new TestRequestHandler();
  67. $middleware = new AssetMiddleware();
  68. $res = $middleware->process($request, $handler);
  69. $body = $res->getBody()->getContents();
  70. $this->assertSame('', $body);
  71. }
  72. /**
  73. * Data provider for assets.
  74. *
  75. * @return array
  76. */
  77. public function assetProvider(): array
  78. {
  79. return [
  80. // In plugin root.
  81. [
  82. '/test_plugin/root.js',
  83. TEST_APP . 'Plugin/TestPlugin/webroot/root.js',
  84. ],
  85. // Subdirectory
  86. [
  87. '/test_plugin/js/alert.js',
  88. TEST_APP . 'Plugin/TestPlugin/webroot/js/alert.js',
  89. ],
  90. // In path that matches the plugin name
  91. [
  92. '/test_plugin/js/test_plugin/test.js',
  93. TEST_APP . 'Plugin/TestPlugin/webroot/js/test_plugin/test.js',
  94. ],
  95. // In vendored plugin
  96. [
  97. '/company/test_plugin_three/css/company.css',
  98. TEST_APP . 'Plugin/Company/TestPluginThree/webroot/css/company.css',
  99. ],
  100. ];
  101. }
  102. /**
  103. * Test assets in a plugin.
  104. *
  105. * @dataProvider assetProvider
  106. */
  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. }