InlineFragmentRendererTest.php 11 KB

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