PageRenderTime 53ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php

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