EsiTest.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpKernel\Tests\HttpCache;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\HttpKernel\HttpCache\Esi;
  15. use Symfony\Component\HttpKernel\HttpCache\HttpCache;
  16. class EsiTest extends TestCase
  17. {
  18. public function testHasSurrogateEsiCapability()
  19. {
  20. $esi = new Esi();
  21. $request = Request::create('/');
  22. $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
  23. $this->assertTrue($esi->hasSurrogateCapability($request));
  24. $request = Request::create('/');
  25. $request->headers->set('Surrogate-Capability', 'foobar');
  26. $this->assertFalse($esi->hasSurrogateCapability($request));
  27. $request = Request::create('/');
  28. $this->assertFalse($esi->hasSurrogateCapability($request));
  29. }
  30. public function testAddSurrogateEsiCapability()
  31. {
  32. $esi = new Esi();
  33. $request = Request::create('/');
  34. $esi->addSurrogateCapability($request);
  35. $this->assertEquals('symfony="ESI/1.0"', $request->headers->get('Surrogate-Capability'));
  36. $esi->addSurrogateCapability($request);
  37. $this->assertEquals('symfony="ESI/1.0", symfony="ESI/1.0"', $request->headers->get('Surrogate-Capability'));
  38. }
  39. public function testAddSurrogateControl()
  40. {
  41. $esi = new Esi();
  42. $response = new Response('foo <esi:include src="" />');
  43. $esi->addSurrogateControl($response);
  44. $this->assertEquals('content="ESI/1.0"', $response->headers->get('Surrogate-Control'));
  45. $response = new Response('foo');
  46. $esi->addSurrogateControl($response);
  47. $this->assertEquals('', $response->headers->get('Surrogate-Control'));
  48. }
  49. public function testNeedsEsiParsing()
  50. {
  51. $esi = new Esi();
  52. $response = new Response();
  53. $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
  54. $this->assertTrue($esi->needsParsing($response));
  55. $response = new Response();
  56. $this->assertFalse($esi->needsParsing($response));
  57. }
  58. public function testRenderIncludeTag()
  59. {
  60. $esi = new Esi();
  61. $this->assertEquals('<esi:include src="/" onerror="continue" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', true));
  62. $this->assertEquals('<esi:include src="/" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', false));
  63. $this->assertEquals('<esi:include src="/" onerror="continue" />', $esi->renderIncludeTag('/'));
  64. $this->assertEquals('<esi:comment text="some comment" />'."\n".'<esi:include src="/" onerror="continue" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', true, 'some comment'));
  65. }
  66. public function testProcessDoesNothingIfContentTypeIsNotHtml()
  67. {
  68. $esi = new Esi();
  69. $request = Request::create('/');
  70. $response = new Response();
  71. $response->headers->set('Content-Type', 'text/plain');
  72. $this->assertSame($response, $esi->process($request, $response));
  73. $this->assertFalse($response->headers->has('x-body-eval'));
  74. }
  75. public function testMultilineEsiRemoveTagsAreRemoved()
  76. {
  77. $esi = new Esi();
  78. $request = Request::create('/');
  79. $response = new Response('<esi:remove> <a href="http://www.example.com">www.example.com</a> </esi:remove> Keep this'."<esi:remove>\n <a>www.example.com</a> </esi:remove> And this");
  80. $this->assertSame($response, $esi->process($request, $response));
  81. $this->assertEquals(' Keep this And this', substr($response->getContent(), 24, -24));
  82. }
  83. public function testCommentTagsAreRemoved()
  84. {
  85. $esi = new Esi();
  86. $request = Request::create('/');
  87. $response = new Response('<esi:comment text="some comment &gt;" /> Keep this');
  88. $this->assertSame($response, $esi->process($request, $response));
  89. $this->assertEquals(' Keep this', substr($response->getContent(), 24, -24));
  90. }
  91. public function testProcess()
  92. {
  93. $esi = new Esi();
  94. $request = Request::create('/');
  95. $response = new Response('foo <esi:comment text="some comment" /><esi:include src="..." alt="alt" onerror="continue" />');
  96. $this->assertSame($response, $esi->process($request, $response));
  97. $content = explode(substr($response->getContent(), 0, 24), $response->getContent());
  98. $this->assertSame(['', 'foo ', "...\nalt\n1\n", ''], $content);
  99. $this->assertEquals('ESI', $response->headers->get('x-body-eval'));
  100. $response = new Response('foo <esi:comment text="some comment" /><esi:include src="foo\'" alt="bar\'" onerror="continue" />');
  101. $this->assertSame($response, $esi->process($request, $response));
  102. $content = explode(substr($response->getContent(), 0, 24), $response->getContent());
  103. $this->assertSame(['', 'foo ', "foo'\nbar'\n1\n", ''], $content);
  104. $response = new Response('foo <esi:include src="..." />');
  105. $this->assertSame($response, $esi->process($request, $response));
  106. $content = explode(substr($response->getContent(), 0, 24), $response->getContent());
  107. $this->assertSame(['', 'foo ', "...\n\n\n", ''], $content);
  108. $response = new Response('foo <esi:include src="..."></esi:include>');
  109. $this->assertSame($response, $esi->process($request, $response));
  110. $content = explode(substr($response->getContent(), 0, 24), $response->getContent());
  111. $this->assertSame(['', 'foo ', "...\n\n\n", ''], $content);
  112. }
  113. public function testProcessEscapesPhpTags()
  114. {
  115. $esi = new Esi();
  116. $request = Request::create('/');
  117. $response = new Response('<?php <? <% <script language=php>');
  118. $this->assertSame($response, $esi->process($request, $response));
  119. $content = explode(substr($response->getContent(), 0, 24), $response->getContent());
  120. $this->assertSame(['', '<?php <? <% <script language=php>', ''], $content);
  121. }
  122. public function testProcessWhenNoSrcInAnEsi()
  123. {
  124. $this->expectException(\RuntimeException::class);
  125. $esi = new Esi();
  126. $request = Request::create('/');
  127. $response = new Response('foo <esi:include />');
  128. $this->assertSame($response, $esi->process($request, $response));
  129. }
  130. public function testProcessRemoveSurrogateControlHeader()
  131. {
  132. $esi = new Esi();
  133. $request = Request::create('/');
  134. $response = new Response('foo <esi:include src="..." />');
  135. $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
  136. $this->assertSame($response, $esi->process($request, $response));
  137. $this->assertEquals('ESI', $response->headers->get('x-body-eval'));
  138. $response->headers->set('Surrogate-Control', 'no-store, content="ESI/1.0"');
  139. $this->assertSame($response, $esi->process($request, $response));
  140. $this->assertEquals('ESI', $response->headers->get('x-body-eval'));
  141. $this->assertEquals('no-store', $response->headers->get('surrogate-control'));
  142. $response->headers->set('Surrogate-Control', 'content="ESI/1.0", no-store');
  143. $this->assertSame($response, $esi->process($request, $response));
  144. $this->assertEquals('ESI', $response->headers->get('x-body-eval'));
  145. $this->assertEquals('no-store', $response->headers->get('surrogate-control'));
  146. }
  147. public function testHandle()
  148. {
  149. $esi = new Esi();
  150. $cache = $this->getCache(Request::create('/'), new Response('foo'));
  151. $this->assertEquals('foo', $esi->handle($cache, '/', '/alt', true));
  152. }
  153. public function testHandleWhenResponseIsNot200()
  154. {
  155. $this->expectException(\RuntimeException::class);
  156. $esi = new Esi();
  157. $response = new Response('foo');
  158. $response->setStatusCode(404);
  159. $cache = $this->getCache(Request::create('/'), $response);
  160. $esi->handle($cache, '/', '/alt', false);
  161. }
  162. public function testHandleWhenResponseIsNot200AndErrorsAreIgnored()
  163. {
  164. $esi = new Esi();
  165. $response = new Response('foo');
  166. $response->setStatusCode(404);
  167. $cache = $this->getCache(Request::create('/'), $response);
  168. $this->assertEquals('', $esi->handle($cache, '/', '/alt', true));
  169. }
  170. public function testHandleWhenResponseIsNot200AndAltIsPresent()
  171. {
  172. $esi = new Esi();
  173. $response1 = new Response('foo');
  174. $response1->setStatusCode(404);
  175. $response2 = new Response('bar');
  176. $cache = $this->getCache(Request::create('/'), [$response1, $response2]);
  177. $this->assertEquals('bar', $esi->handle($cache, '/', '/alt', false));
  178. }
  179. public function testHandleWhenResponseIsNotModified()
  180. {
  181. $esi = new Esi();
  182. $response = new Response('');
  183. $response->setStatusCode(304);
  184. $cache = $this->getCache(Request::create('/'), $response);
  185. $this->assertEquals('', $esi->handle($cache, '/', '/alt', true));
  186. }
  187. protected function getCache($request, $response)
  188. {
  189. $cache = $this->getMockBuilder(HttpCache::class)->onlyMethods(['getRequest', 'handle'])->disableOriginalConstructor()->getMock();
  190. $cache->expects($this->any())
  191. ->method('getRequest')
  192. ->willReturn($request)
  193. ;
  194. if (\is_array($response)) {
  195. $cache->expects($this->any())
  196. ->method('handle')
  197. ->will($this->onConsecutiveCalls(...$response))
  198. ;
  199. } else {
  200. $cache->expects($this->any())
  201. ->method('handle')
  202. ->willReturn($response)
  203. ;
  204. }
  205. return $cache;
  206. }
  207. }