HttpKernelTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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;
  11. use Symfony\Component\HttpKernel\HttpKernel;
  12. use Symfony\Component\HttpKernel\HttpKernelInterface;
  13. use Symfony\Component\HttpKernel\KernelEvents;
  14. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  15. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\HttpFoundation\Response;
  18. use Symfony\Component\HttpFoundation\RedirectResponse;
  19. use Symfony\Component\EventDispatcher\EventDispatcher;
  20. class HttpKernelTest extends \PHPUnit_Framework_TestCase
  21. {
  22. /**
  23. * @expectedException \RuntimeException
  24. */
  25. public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrue()
  26. {
  27. $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); }));
  28. $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
  29. }
  30. /**
  31. * @expectedException \RuntimeException
  32. */
  33. public function testHandleWhenControllerThrowsAnExceptionAndCatchIsFalseAndNoListenerIsRegistered()
  34. {
  35. $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); }));
  36. $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false);
  37. }
  38. public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrueWithAHandlingListener()
  39. {
  40. $dispatcher = new EventDispatcher();
  41. $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
  42. $event->setResponse(new Response($event->getException()->getMessage()));
  43. });
  44. $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); }));
  45. $response = $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
  46. $this->assertEquals('500', $response->getStatusCode());
  47. $this->assertEquals('foo', $response->getContent());
  48. }
  49. public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrueWithANonHandlingListener()
  50. {
  51. $exception = new \RuntimeException();
  52. $dispatcher = new EventDispatcher();
  53. $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
  54. // should set a response, but does not
  55. });
  56. $kernel = new HttpKernel($dispatcher, $this->getResolver(function () use ($exception) { throw $exception; }));
  57. try {
  58. $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
  59. $this->fail('LogicException expected');
  60. } catch (\RuntimeException $e) {
  61. $this->assertSame($exception, $e);
  62. }
  63. }
  64. public function testHandleExceptionWithARedirectionResponse()
  65. {
  66. $dispatcher = new EventDispatcher();
  67. $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
  68. $event->setResponse(new RedirectResponse('/login', 301));
  69. });
  70. $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new AccessDeniedHttpException(); }));
  71. $response = $kernel->handle(new Request());
  72. $this->assertEquals('301', $response->getStatusCode());
  73. $this->assertEquals('/login', $response->headers->get('Location'));
  74. }
  75. public function testHandleHttpException()
  76. {
  77. $dispatcher = new EventDispatcher();
  78. $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
  79. $event->setResponse(new Response($event->getException()->getMessage()));
  80. });
  81. $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new MethodNotAllowedHttpException(array('POST')); }));
  82. $response = $kernel->handle(new Request());
  83. $this->assertEquals('405', $response->getStatusCode());
  84. $this->assertEquals('POST', $response->headers->get('Allow'));
  85. }
  86. /**
  87. * @dataProvider getStatusCodes
  88. */
  89. public function testHandleWhenAnExceptionIsHandledWithASpecificStatusCode($responseStatusCode, $expectedStatusCode)
  90. {
  91. $dispatcher = new EventDispatcher();
  92. $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) use ($responseStatusCode, $expectedStatusCode) {
  93. $event->setResponse(new Response('', $responseStatusCode, array('X-Status-Code' => $expectedStatusCode)));
  94. });
  95. $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException(); }));
  96. $response = $kernel->handle(new Request());
  97. $this->assertEquals($expectedStatusCode, $response->getStatusCode());
  98. $this->assertFalse($response->headers->has('X-Status-Code'));
  99. }
  100. public function getStatusCodes()
  101. {
  102. return array(
  103. array(200, 404),
  104. array(404, 200),
  105. array(301, 200),
  106. array(500, 200),
  107. );
  108. }
  109. public function testHandleWhenAListenerReturnsAResponse()
  110. {
  111. $dispatcher = new EventDispatcher();
  112. $dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
  113. $event->setResponse(new Response('hello'));
  114. });
  115. $kernel = new HttpKernel($dispatcher, $this->getResolver());
  116. $this->assertEquals('hello', $kernel->handle(new Request())->getContent());
  117. }
  118. /**
  119. * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
  120. */
  121. public function testHandleWhenNoControllerIsFound()
  122. {
  123. $dispatcher = new EventDispatcher();
  124. $kernel = new HttpKernel($dispatcher, $this->getResolver(false));
  125. $kernel->handle(new Request());
  126. }
  127. public function testHandleWhenTheControllerIsAClosure()
  128. {
  129. $response = new Response('foo');
  130. $dispatcher = new EventDispatcher();
  131. $kernel = new HttpKernel($dispatcher, $this->getResolver(function () use ($response) { return $response; }));
  132. $this->assertSame($response, $kernel->handle(new Request()));
  133. }
  134. public function testHandleWhenTheControllerIsAnObjectWithInvoke()
  135. {
  136. $dispatcher = new EventDispatcher();
  137. $kernel = new HttpKernel($dispatcher, $this->getResolver(new Controller()));
  138. $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
  139. }
  140. public function testHandleWhenTheControllerIsAFunction()
  141. {
  142. $dispatcher = new EventDispatcher();
  143. $kernel = new HttpKernel($dispatcher, $this->getResolver('Symfony\Component\HttpKernel\Tests\controller_func'));
  144. $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
  145. }
  146. public function testHandleWhenTheControllerIsAnArray()
  147. {
  148. $dispatcher = new EventDispatcher();
  149. $kernel = new HttpKernel($dispatcher, $this->getResolver(array(new Controller(), 'controller')));
  150. $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
  151. }
  152. public function testHandleWhenTheControllerIsAStaticArray()
  153. {
  154. $dispatcher = new EventDispatcher();
  155. $kernel = new HttpKernel($dispatcher, $this->getResolver(array('Symfony\Component\HttpKernel\Tests\Controller', 'staticcontroller')));
  156. $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
  157. }
  158. /**
  159. * @expectedException \LogicException
  160. */
  161. public function testHandleWhenTheControllerDoesNotReturnAResponse()
  162. {
  163. $dispatcher = new EventDispatcher();
  164. $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; }));
  165. $kernel->handle(new Request());
  166. }
  167. public function testHandleWhenTheControllerDoesNotReturnAResponseButAViewIsRegistered()
  168. {
  169. $dispatcher = new EventDispatcher();
  170. $dispatcher->addListener(KernelEvents::VIEW, function ($event) {
  171. $event->setResponse(new Response($event->getControllerResult()));
  172. });
  173. $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; }));
  174. $this->assertEquals('foo', $kernel->handle(new Request())->getContent());
  175. }
  176. public function testHandleWithAResponseListener()
  177. {
  178. $dispatcher = new EventDispatcher();
  179. $dispatcher->addListener(KernelEvents::RESPONSE, function ($event) {
  180. $event->setResponse(new Response('foo'));
  181. });
  182. $kernel = new HttpKernel($dispatcher, $this->getResolver());
  183. $this->assertEquals('foo', $kernel->handle(new Request())->getContent());
  184. }
  185. public function testTerminate()
  186. {
  187. $dispatcher = new EventDispatcher();
  188. $kernel = new HttpKernel($dispatcher, $this->getResolver());
  189. $dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel, &$capturedRequest, &$capturedResponse) {
  190. $called = true;
  191. $capturedKernel = $event->getKernel();
  192. $capturedRequest = $event->getRequest();
  193. $capturedResponse = $event->getResponse();
  194. });
  195. $kernel->terminate($request = Request::create('/'), $response = new Response());
  196. $this->assertTrue($called);
  197. $this->assertEquals($kernel, $capturedKernel);
  198. $this->assertEquals($request, $capturedRequest);
  199. $this->assertEquals($response, $capturedResponse);
  200. }
  201. public function testVerifyRequestStackPushPopDuringHandle()
  202. {
  203. $request = new Request();
  204. $stack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array('push', 'pop'));
  205. $stack->expects($this->at(0))->method('push')->with($this->equalTo($request));
  206. $stack->expects($this->at(1))->method('pop');
  207. $dispatcher = new EventDispatcher();
  208. $kernel = new HttpKernel($dispatcher, $this->getResolver(), $stack);
  209. $kernel->handle($request, HttpKernelInterface::MASTER_REQUEST);
  210. }
  211. /**
  212. * @expectedException Symfony\Component\HttpKernel\Exception\BadRequestHttpException
  213. */
  214. public function testInconsistentClientIpsOnMasterRequests()
  215. {
  216. $dispatcher = new EventDispatcher();
  217. $dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
  218. $event->getRequest()->getClientIp();
  219. });
  220. $kernel = new HttpKernel($dispatcher, $this->getResolver());
  221. $request = new Request();
  222. $request->setTrustedProxies(array('1.1.1.1'));
  223. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  224. $request->headers->set('FORWARDED', '2.2.2.2');
  225. $request->headers->set('X_FORWARDED_FOR', '3.3.3.3');
  226. $kernel->handle($request, $kernel::MASTER_REQUEST, false);
  227. }
  228. protected function getResolver($controller = null)
  229. {
  230. if (null === $controller) {
  231. $controller = function () { return new Response('Hello'); };
  232. }
  233. $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
  234. $resolver->expects($this->any())
  235. ->method('getController')
  236. ->will($this->returnValue($controller));
  237. $resolver->expects($this->any())
  238. ->method('getArguments')
  239. ->will($this->returnValue(array()));
  240. return $resolver;
  241. }
  242. protected function assertResponseEquals(Response $expected, Response $actual)
  243. {
  244. $expected->setDate($actual->getDate());
  245. $this->assertEquals($expected, $actual);
  246. }
  247. }
  248. class Controller
  249. {
  250. public function __invoke()
  251. {
  252. return new Response('foo');
  253. }
  254. public function controller()
  255. {
  256. return new Response('foo');
  257. }
  258. public static function staticController()
  259. {
  260. return new Response('foo');
  261. }
  262. }
  263. function controller_func()
  264. {
  265. return new Response('foo');
  266. }