InlineFragmentRendererTest.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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. $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/'));
  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. $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP);
  83. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, '');
  84. $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest(Request::create('/')));
  85. $strategy->render('/', Request::create('/'));
  86. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, $trustedHeaderName);
  87. }
  88. /**
  89. * @expectedException \RuntimeException
  90. */
  91. public function testRenderExceptionNoIgnoreErrors()
  92. {
  93. $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
  94. $dispatcher->expects($this->never())->method('dispatch');
  95. $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher);
  96. $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent());
  97. }
  98. public function testRenderExceptionIgnoreErrors()
  99. {
  100. $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
  101. $dispatcher->expects($this->once())->method('dispatch')->with(KernelEvents::EXCEPTION);
  102. $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher);
  103. $this->assertEmpty($strategy->render('/', Request::create('/'), array('ignore_errors' => true))->getContent());
  104. }
  105. public function testRenderExceptionIgnoreErrorsWithAlt()
  106. {
  107. $strategy = new InlineFragmentRenderer($this->getKernel($this->onConsecutiveCalls(
  108. $this->throwException(new \RuntimeException('foo')),
  109. $this->returnValue(new Response('bar'))
  110. )));
  111. $this->assertEquals('bar', $strategy->render('/', Request::create('/'), array('ignore_errors' => true, 'alt' => '/foo'))->getContent());
  112. }
  113. private function getKernel($returnValue)
  114. {
  115. $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
  116. $kernel
  117. ->expects($this->any())
  118. ->method('handle')
  119. ->will($returnValue)
  120. ;
  121. return $kernel;
  122. }
  123. /**
  124. * Creates a Kernel expecting a request equals to $request
  125. * Allows delta in comparison in case REQUEST_TIME changed by 1 second.
  126. */
  127. private function getKernelExpectingRequest(Request $request)
  128. {
  129. $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
  130. $kernel
  131. ->expects($this->any())
  132. ->method('handle')
  133. ->with($this->equalTo($request, 1))
  134. ;
  135. return $kernel;
  136. }
  137. public function testExceptionInSubRequestsDoesNotMangleOutputBuffers()
  138. {
  139. $controllerResolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface')->getMock();
  140. $controllerResolver
  141. ->expects($this->once())
  142. ->method('getController')
  143. ->will($this->returnValue(function () {
  144. ob_start();
  145. echo 'bar';
  146. throw new \RuntimeException();
  147. }))
  148. ;
  149. $argumentResolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface')->getMock();
  150. $argumentResolver
  151. ->expects($this->once())
  152. ->method('getArguments')
  153. ->will($this->returnValue(array()))
  154. ;
  155. $kernel = new HttpKernel(new EventDispatcher(), $controllerResolver, new RequestStack(), $argumentResolver);
  156. $renderer = new InlineFragmentRenderer($kernel);
  157. // simulate a main request with output buffering
  158. ob_start();
  159. echo 'Foo';
  160. // simulate a sub-request with output buffering and an exception
  161. $renderer->render('/', Request::create('/'), array('ignore_errors' => true));
  162. $this->assertEquals('Foo', ob_get_clean());
  163. }
  164. public function testESIHeaderIsKeptInSubrequest()
  165. {
  166. $expectedSubRequest = Request::create('/');
  167. $expectedSubRequest->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
  168. if (Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) {
  169. $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
  170. $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
  171. }
  172. $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest));
  173. $request = Request::create('/');
  174. $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
  175. $strategy->render('/', $request);
  176. }
  177. public function testESIHeaderIsKeptInSubrequestWithTrustedHeaderDisabled()
  178. {
  179. $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP);
  180. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, '');
  181. $this->testESIHeaderIsKeptInSubrequest();
  182. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, $trustedHeaderName);
  183. }
  184. public function testHeadersPossiblyResultingIn304AreNotAssignedToSubrequest()
  185. {
  186. $expectedSubRequest = Request::create('/');
  187. if (Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) {
  188. $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
  189. $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
  190. }
  191. $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest));
  192. $request = Request::create('/', 'GET', array(), array(), array(), array('HTTP_IF_MODIFIED_SINCE' => 'Fri, 01 Jan 2016 00:00:00 GMT', 'HTTP_IF_NONE_MATCH' => '*'));
  193. $strategy->render('/', $request);
  194. }
  195. }
  196. class Bar
  197. {
  198. public $bar = 'bar';
  199. public function getBar()
  200. {
  201. return $this->bar;
  202. }
  203. }