InlineFragmentRendererTest.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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\Fragment;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\HttpFoundation\RequestStack;
  13. use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
  14. use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
  15. use Symfony\Component\HttpKernel\Controller\ControllerReference;
  16. use Symfony\Component\HttpKernel\HttpKernel;
  17. use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer;
  18. use Symfony\Component\HttpKernel\KernelEvents;
  19. use Symfony\Component\HttpFoundation\Request;
  20. use Symfony\Component\HttpFoundation\Response;
  21. use Symfony\Component\EventDispatcher\EventDispatcher;
  22. class InlineFragmentRendererTest extends TestCase
  23. {
  24. public function testRender()
  25. {
  26. $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo'))));
  27. $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent());
  28. }
  29. public function testRenderWithControllerReference()
  30. {
  31. $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo'))));
  32. $this->assertEquals('foo', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent());
  33. }
  34. public function testRenderWithObjectsAsAttributes()
  35. {
  36. $object = new \stdClass();
  37. $subRequest = Request::create('/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dmain_controller');
  38. $subRequest->attributes->replace(array('object' => $object, '_format' => 'html', '_controller' => 'main_controller', '_locale' => 'en'));
  39. $subRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
  40. $subRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
  41. $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($subRequest));
  42. $this->assertSame('foo', $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/'))->getContent());
  43. }
  44. /**
  45. * @group legacy
  46. */
  47. public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheControllerLegacy()
  48. {
  49. $resolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver')->setMethods(array('getController'))->getMock();
  50. $resolver
  51. ->expects($this->once())
  52. ->method('getController')
  53. ->will($this->returnValue(function (\stdClass $object, Bar $object1) {
  54. return new Response($object1->getBar());
  55. }))
  56. ;
  57. $kernel = new HttpKernel(new EventDispatcher(), $resolver, new RequestStack());
  58. $renderer = new InlineFragmentRenderer($kernel);
  59. $response = $renderer->render(new ControllerReference('main_controller', array('object' => new \stdClass(), 'object1' => new Bar()), array()), Request::create('/'));
  60. $this->assertEquals('bar', $response->getContent());
  61. }
  62. /**
  63. * @group legacy
  64. */
  65. public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheController()
  66. {
  67. $resolver = $this->getMockBuilder(ControllerResolverInterface::class)->getMock();
  68. $resolver
  69. ->expects($this->once())
  70. ->method('getController')
  71. ->will($this->returnValue(function (\stdClass $object, Bar $object1) {
  72. return new Response($object1->getBar());
  73. }))
  74. ;
  75. $kernel = new HttpKernel(new EventDispatcher(), $resolver, new RequestStack(), new ArgumentResolver());
  76. $renderer = new InlineFragmentRenderer($kernel);
  77. $response = $renderer->render(new ControllerReference('main_controller', array('object' => new \stdClass(), 'object1' => new Bar()), array()), Request::create('/'));
  78. $this->assertEquals('bar', $response->getContent());
  79. }
  80. public function testRenderWithTrustedHeaderDisabled()
  81. {
  82. Request::setTrustedProxies(array(), 0);
  83. $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest(Request::create('/')));
  84. $this->assertSame('foo', $strategy->render('/', Request::create('/'))->getContent());
  85. Request::setTrustedProxies(array(), -1);
  86. }
  87. /**
  88. * @expectedException \RuntimeException
  89. */
  90. public function testRenderExceptionNoIgnoreErrors()
  91. {
  92. $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
  93. $dispatcher->expects($this->never())->method('dispatch');
  94. $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher);
  95. $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent());
  96. }
  97. public function testRenderExceptionIgnoreErrors()
  98. {
  99. $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
  100. $dispatcher->expects($this->once())->method('dispatch')->with(KernelEvents::EXCEPTION);
  101. $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher);
  102. $this->assertEmpty($strategy->render('/', Request::create('/'), array('ignore_errors' => true))->getContent());
  103. }
  104. public function testRenderExceptionIgnoreErrorsWithAlt()
  105. {
  106. $strategy = new InlineFragmentRenderer($this->getKernel($this->onConsecutiveCalls(
  107. $this->throwException(new \RuntimeException('foo')),
  108. $this->returnValue(new Response('bar'))
  109. )));
  110. $this->assertEquals('bar', $strategy->render('/', Request::create('/'), array('ignore_errors' => true, 'alt' => '/foo'))->getContent());
  111. }
  112. private function getKernel($returnValue)
  113. {
  114. $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
  115. $kernel
  116. ->expects($this->any())
  117. ->method('handle')
  118. ->will($returnValue)
  119. ;
  120. return $kernel;
  121. }
  122. public function testExceptionInSubRequestsDoesNotMangleOutputBuffers()
  123. {
  124. $controllerResolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface')->getMock();
  125. $controllerResolver
  126. ->expects($this->once())
  127. ->method('getController')
  128. ->will($this->returnValue(function () {
  129. ob_start();
  130. echo 'bar';
  131. throw new \RuntimeException();
  132. }))
  133. ;
  134. $argumentResolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface')->getMock();
  135. $argumentResolver
  136. ->expects($this->once())
  137. ->method('getArguments')
  138. ->will($this->returnValue(array()))
  139. ;
  140. $kernel = new HttpKernel(new EventDispatcher(), $controllerResolver, new RequestStack(), $argumentResolver);
  141. $renderer = new InlineFragmentRenderer($kernel);
  142. // simulate a main request with output buffering
  143. ob_start();
  144. echo 'Foo';
  145. // simulate a sub-request with output buffering and an exception
  146. $renderer->render('/', Request::create('/'), array('ignore_errors' => true));
  147. $this->assertEquals('Foo', ob_get_clean());
  148. }
  149. public function testESIHeaderIsKeptInSubrequest()
  150. {
  151. $expectedSubRequest = Request::create('/');
  152. $expectedSubRequest->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
  153. if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) {
  154. $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
  155. $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
  156. }
  157. $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest));
  158. $request = Request::create('/');
  159. $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
  160. $strategy->render('/', $request);
  161. }
  162. public function testESIHeaderIsKeptInSubrequestWithTrustedHeaderDisabled()
  163. {
  164. Request::setTrustedProxies(array(), 0);
  165. $this->testESIHeaderIsKeptInSubrequest();
  166. Request::setTrustedProxies(array(), -1);
  167. }
  168. public function testHeadersPossiblyResultingIn304AreNotAssignedToSubrequest()
  169. {
  170. $expectedSubRequest = Request::create('/');
  171. if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) {
  172. $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
  173. $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
  174. }
  175. $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest));
  176. $request = Request::create('/', 'GET', array(), array(), array(), array('HTTP_IF_MODIFIED_SINCE' => 'Fri, 01 Jan 2016 00:00:00 GMT', 'HTTP_IF_NONE_MATCH' => '*'));
  177. $strategy->render('/', $request);
  178. }
  179. /**
  180. * Creates a Kernel expecting a request equals to $request
  181. * Allows delta in comparison in case REQUEST_TIME changed by 1 second.
  182. */
  183. private function getKernelExpectingRequest(Request $request, $strict = false)
  184. {
  185. $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
  186. $kernel
  187. ->expects($this->once())
  188. ->method('handle')
  189. ->with($this->equalTo($request, 1))
  190. ->willReturn(new Response('foo'));
  191. return $kernel;
  192. }
  193. }
  194. class Bar
  195. {
  196. public $bar = 'bar';
  197. public function getBar()
  198. {
  199. return $this->bar;
  200. }
  201. }