1<?php 2 3/* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Symfony\Component\HttpKernel\Tests\EventListener; 13 14use PHPUnit\Framework\TestCase; 15use Symfony\Component\EventDispatcher\EventDispatcher; 16use Symfony\Component\HttpFoundation\Request; 17use Symfony\Component\HttpFoundation\RequestStack; 18use Symfony\Component\HttpFoundation\Response; 19use Symfony\Component\HttpKernel\Controller\ArgumentResolver; 20use Symfony\Component\HttpKernel\Controller\ControllerResolver; 21use Symfony\Component\HttpKernel\Event\GetResponseEvent; 22use Symfony\Component\HttpKernel\EventListener\ExceptionListener; 23use Symfony\Component\HttpKernel\EventListener\RouterListener; 24use Symfony\Component\HttpKernel\EventListener\ValidateRequestListener; 25use Symfony\Component\HttpKernel\HttpKernel; 26use Symfony\Component\HttpKernel\HttpKernelInterface; 27use Symfony\Component\Routing\Exception\NoConfigurationException; 28use Symfony\Component\Routing\RequestContext; 29 30class RouterListenerTest extends TestCase 31{ 32 private $requestStack; 33 34 protected function setUp() 35 { 36 $this->requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->disableOriginalConstructor()->getMock(); 37 } 38 39 /** 40 * @dataProvider getPortData 41 */ 42 public function testPort($defaultHttpPort, $defaultHttpsPort, $uri, $expectedHttpPort, $expectedHttpsPort) 43 { 44 $urlMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface') 45 ->disableOriginalConstructor() 46 ->getMock(); 47 $context = new RequestContext(); 48 $context->setHttpPort($defaultHttpPort); 49 $context->setHttpsPort($defaultHttpsPort); 50 $urlMatcher->expects($this->any()) 51 ->method('getContext') 52 ->willReturn($context); 53 54 $listener = new RouterListener($urlMatcher, $this->requestStack); 55 $event = $this->createGetResponseEventForUri($uri); 56 $listener->onKernelRequest($event); 57 58 $this->assertEquals($expectedHttpPort, $context->getHttpPort()); 59 $this->assertEquals($expectedHttpsPort, $context->getHttpsPort()); 60 $this->assertEquals(0 === strpos($uri, 'https') ? 'https' : 'http', $context->getScheme()); 61 } 62 63 public function getPortData() 64 { 65 return [ 66 [80, 443, 'http://localhost/', 80, 443], 67 [80, 443, 'http://localhost:90/', 90, 443], 68 [80, 443, 'https://localhost/', 80, 443], 69 [80, 443, 'https://localhost:90/', 80, 90], 70 ]; 71 } 72 73 /** 74 * @param string $uri 75 * 76 * @return GetResponseEvent 77 */ 78 private function createGetResponseEventForUri($uri) 79 { 80 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); 81 $request = Request::create($uri); 82 $request->attributes->set('_controller', null); // Prevents going in to routing process 83 84 return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); 85 } 86 87 public function testInvalidMatcher() 88 { 89 $this->expectException('InvalidArgumentException'); 90 new RouterListener(new \stdClass(), $this->requestStack); 91 } 92 93 public function testRequestMatcher() 94 { 95 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); 96 $request = Request::create('http://localhost/'); 97 $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); 98 99 $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); 100 $requestMatcher->expects($this->once()) 101 ->method('matchRequest') 102 ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) 103 ->willReturn([]); 104 105 $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext()); 106 $listener->onKernelRequest($event); 107 } 108 109 public function testSubRequestWithDifferentMethod() 110 { 111 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); 112 $request = Request::create('http://localhost/', 'post'); 113 $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); 114 115 $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); 116 $requestMatcher->expects($this->any()) 117 ->method('matchRequest') 118 ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) 119 ->willReturn([]); 120 121 $context = new RequestContext(); 122 123 $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext()); 124 $listener->onKernelRequest($event); 125 126 // sub-request with another HTTP method 127 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); 128 $request = Request::create('http://localhost/', 'get'); 129 $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST); 130 131 $listener->onKernelRequest($event); 132 133 $this->assertEquals('GET', $context->getMethod()); 134 } 135 136 /** 137 * @dataProvider getLoggingParameterData 138 */ 139 public function testLoggingParameter($parameter, $log, $parameters) 140 { 141 $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); 142 $requestMatcher->expects($this->once()) 143 ->method('matchRequest') 144 ->willReturn($parameter); 145 146 $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); 147 $logger->expects($this->once()) 148 ->method('info') 149 ->with($this->equalTo($log), $this->equalTo($parameters)); 150 151 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); 152 $request = Request::create('http://localhost/'); 153 154 $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext(), $logger); 155 $listener->onKernelRequest(new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST)); 156 } 157 158 public function getLoggingParameterData() 159 { 160 return [ 161 [['_route' => 'foo'], 'Matched route "{route}".', ['route' => 'foo', 'route_parameters' => ['_route' => 'foo'], 'request_uri' => 'http://localhost/', 'method' => 'GET']], 162 [[], 'Matched route "{route}".', ['route' => 'n/a', 'route_parameters' => [], 'request_uri' => 'http://localhost/', 'method' => 'GET']], 163 ]; 164 } 165 166 public function testWithBadRequest() 167 { 168 $requestStack = new RequestStack(); 169 170 $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); 171 $requestMatcher->expects($this->never())->method('matchRequest'); 172 173 $dispatcher = new EventDispatcher(); 174 $dispatcher->addSubscriber(new ValidateRequestListener()); 175 $dispatcher->addSubscriber(new RouterListener($requestMatcher, $requestStack, new RequestContext())); 176 $dispatcher->addSubscriber(new ExceptionListener(function () { 177 return new Response('Exception handled', 400); 178 })); 179 180 $kernel = new HttpKernel($dispatcher, new ControllerResolver(), $requestStack, new ArgumentResolver()); 181 182 $request = Request::create('http://localhost/'); 183 $request->headers->set('host', '###'); 184 $response = $kernel->handle($request); 185 $this->assertSame(400, $response->getStatusCode()); 186 } 187 188 public function testNoRoutingConfigurationResponse() 189 { 190 $requestStack = new RequestStack(); 191 192 $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); 193 $requestMatcher 194 ->expects($this->once()) 195 ->method('matchRequest') 196 ->willThrowException(new NoConfigurationException()) 197 ; 198 199 $dispatcher = new EventDispatcher(); 200 $dispatcher->addSubscriber(new RouterListener($requestMatcher, $requestStack, new RequestContext())); 201 202 $kernel = new HttpKernel($dispatcher, new ControllerResolver(), $requestStack, new ArgumentResolver()); 203 204 $request = Request::create('http://localhost/'); 205 $response = $kernel->handle($request); 206 $this->assertSame(404, $response->getStatusCode()); 207 $this->assertStringContainsString('Welcome', $response->getContent()); 208 } 209 210 public function testRequestWithBadHost() 211 { 212 $this->expectException('Symfony\Component\HttpKernel\Exception\BadRequestHttpException'); 213 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); 214 $request = Request::create('http://bad host %22/'); 215 $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); 216 217 $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); 218 219 $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext()); 220 $listener->onKernelRequest($event); 221 } 222} 223