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\HttpFoundation\Tests; 13 14use PHPUnit\Framework\TestCase; 15use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; 16use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; 17use Symfony\Component\HttpFoundation\Session\Session; 18use Symfony\Component\HttpFoundation\Request; 19 20class RequestTest extends TestCase 21{ 22 protected function tearDown() 23 { 24 // reset 25 Request::setTrustedProxies(array(), -1); 26 } 27 28 public function testInitialize() 29 { 30 $request = new Request(); 31 32 $request->initialize(array('foo' => 'bar')); 33 $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument'); 34 35 $request->initialize(array(), array('foo' => 'bar')); 36 $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument'); 37 38 $request->initialize(array(), array(), array('foo' => 'bar')); 39 $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument'); 40 41 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar')); 42 $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its sixth argument'); 43 } 44 45 public function testGetLocale() 46 { 47 $request = new Request(); 48 $request->setLocale('pl'); 49 $locale = $request->getLocale(); 50 $this->assertEquals('pl', $locale); 51 } 52 53 public function testGetUser() 54 { 55 $request = Request::create('http://user:password@test.com'); 56 $user = $request->getUser(); 57 58 $this->assertEquals('user', $user); 59 } 60 61 public function testGetPassword() 62 { 63 $request = Request::create('http://user:password@test.com'); 64 $password = $request->getPassword(); 65 66 $this->assertEquals('password', $password); 67 } 68 69 public function testIsNoCache() 70 { 71 $request = new Request(); 72 $isNoCache = $request->isNoCache(); 73 74 $this->assertFalse($isNoCache); 75 } 76 77 public function testGetContentType() 78 { 79 $request = new Request(); 80 $contentType = $request->getContentType(); 81 82 $this->assertNull($contentType); 83 } 84 85 public function testSetDefaultLocale() 86 { 87 $request = new Request(); 88 $request->setDefaultLocale('pl'); 89 $locale = $request->getLocale(); 90 91 $this->assertEquals('pl', $locale); 92 } 93 94 public function testCreate() 95 { 96 $request = Request::create('http://test.com/foo?bar=baz'); 97 $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); 98 $this->assertEquals('/foo', $request->getPathInfo()); 99 $this->assertEquals('bar=baz', $request->getQueryString()); 100 $this->assertEquals(80, $request->getPort()); 101 $this->assertEquals('test.com', $request->getHttpHost()); 102 $this->assertFalse($request->isSecure()); 103 104 $request = Request::create('http://test.com/foo', 'GET', array('bar' => 'baz')); 105 $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); 106 $this->assertEquals('/foo', $request->getPathInfo()); 107 $this->assertEquals('bar=baz', $request->getQueryString()); 108 $this->assertEquals(80, $request->getPort()); 109 $this->assertEquals('test.com', $request->getHttpHost()); 110 $this->assertFalse($request->isSecure()); 111 112 $request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz')); 113 $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); 114 $this->assertEquals('/foo', $request->getPathInfo()); 115 $this->assertEquals('bar=baz', $request->getQueryString()); 116 $this->assertEquals(80, $request->getPort()); 117 $this->assertEquals('test.com', $request->getHttpHost()); 118 $this->assertFalse($request->isSecure()); 119 120 $request = Request::create('https://test.com/foo?bar=baz'); 121 $this->assertEquals('https://test.com/foo?bar=baz', $request->getUri()); 122 $this->assertEquals('/foo', $request->getPathInfo()); 123 $this->assertEquals('bar=baz', $request->getQueryString()); 124 $this->assertEquals(443, $request->getPort()); 125 $this->assertEquals('test.com', $request->getHttpHost()); 126 $this->assertTrue($request->isSecure()); 127 128 $request = Request::create('test.com:90/foo'); 129 $this->assertEquals('http://test.com:90/foo', $request->getUri()); 130 $this->assertEquals('/foo', $request->getPathInfo()); 131 $this->assertEquals('test.com', $request->getHost()); 132 $this->assertEquals('test.com:90', $request->getHttpHost()); 133 $this->assertEquals(90, $request->getPort()); 134 $this->assertFalse($request->isSecure()); 135 136 $request = Request::create('https://test.com:90/foo'); 137 $this->assertEquals('https://test.com:90/foo', $request->getUri()); 138 $this->assertEquals('/foo', $request->getPathInfo()); 139 $this->assertEquals('test.com', $request->getHost()); 140 $this->assertEquals('test.com:90', $request->getHttpHost()); 141 $this->assertEquals(90, $request->getPort()); 142 $this->assertTrue($request->isSecure()); 143 144 $request = Request::create('https://127.0.0.1:90/foo'); 145 $this->assertEquals('https://127.0.0.1:90/foo', $request->getUri()); 146 $this->assertEquals('/foo', $request->getPathInfo()); 147 $this->assertEquals('127.0.0.1', $request->getHost()); 148 $this->assertEquals('127.0.0.1:90', $request->getHttpHost()); 149 $this->assertEquals(90, $request->getPort()); 150 $this->assertTrue($request->isSecure()); 151 152 $request = Request::create('https://[::1]:90/foo'); 153 $this->assertEquals('https://[::1]:90/foo', $request->getUri()); 154 $this->assertEquals('/foo', $request->getPathInfo()); 155 $this->assertEquals('[::1]', $request->getHost()); 156 $this->assertEquals('[::1]:90', $request->getHttpHost()); 157 $this->assertEquals(90, $request->getPort()); 158 $this->assertTrue($request->isSecure()); 159 160 $request = Request::create('https://[::1]/foo'); 161 $this->assertEquals('https://[::1]/foo', $request->getUri()); 162 $this->assertEquals('/foo', $request->getPathInfo()); 163 $this->assertEquals('[::1]', $request->getHost()); 164 $this->assertEquals('[::1]', $request->getHttpHost()); 165 $this->assertEquals(443, $request->getPort()); 166 $this->assertTrue($request->isSecure()); 167 168 $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}'; 169 $request = Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), $json); 170 $this->assertEquals($json, $request->getContent()); 171 $this->assertFalse($request->isSecure()); 172 173 $request = Request::create('http://test.com'); 174 $this->assertEquals('http://test.com/', $request->getUri()); 175 $this->assertEquals('/', $request->getPathInfo()); 176 $this->assertEquals('', $request->getQueryString()); 177 $this->assertEquals(80, $request->getPort()); 178 $this->assertEquals('test.com', $request->getHttpHost()); 179 $this->assertFalse($request->isSecure()); 180 181 $request = Request::create('http://test.com?test=1'); 182 $this->assertEquals('http://test.com/?test=1', $request->getUri()); 183 $this->assertEquals('/', $request->getPathInfo()); 184 $this->assertEquals('test=1', $request->getQueryString()); 185 $this->assertEquals(80, $request->getPort()); 186 $this->assertEquals('test.com', $request->getHttpHost()); 187 $this->assertFalse($request->isSecure()); 188 189 $request = Request::create('http://test.com:90/?test=1'); 190 $this->assertEquals('http://test.com:90/?test=1', $request->getUri()); 191 $this->assertEquals('/', $request->getPathInfo()); 192 $this->assertEquals('test=1', $request->getQueryString()); 193 $this->assertEquals(90, $request->getPort()); 194 $this->assertEquals('test.com:90', $request->getHttpHost()); 195 $this->assertFalse($request->isSecure()); 196 197 $request = Request::create('http://username:password@test.com'); 198 $this->assertEquals('http://test.com/', $request->getUri()); 199 $this->assertEquals('/', $request->getPathInfo()); 200 $this->assertEquals('', $request->getQueryString()); 201 $this->assertEquals(80, $request->getPort()); 202 $this->assertEquals('test.com', $request->getHttpHost()); 203 $this->assertEquals('username', $request->getUser()); 204 $this->assertEquals('password', $request->getPassword()); 205 $this->assertFalse($request->isSecure()); 206 207 $request = Request::create('http://username@test.com'); 208 $this->assertEquals('http://test.com/', $request->getUri()); 209 $this->assertEquals('/', $request->getPathInfo()); 210 $this->assertEquals('', $request->getQueryString()); 211 $this->assertEquals(80, $request->getPort()); 212 $this->assertEquals('test.com', $request->getHttpHost()); 213 $this->assertEquals('username', $request->getUser()); 214 $this->assertSame('', $request->getPassword()); 215 $this->assertFalse($request->isSecure()); 216 217 $request = Request::create('http://test.com/?foo'); 218 $this->assertEquals('/?foo', $request->getRequestUri()); 219 $this->assertEquals(array('foo' => ''), $request->query->all()); 220 221 // assume rewrite rule: (.*) --> app/app.php; app/ is a symlink to a symfony web/ directory 222 $request = Request::create('http://test.com/apparthotel-1234', 'GET', array(), array(), array(), 223 array( 224 'DOCUMENT_ROOT' => '/var/www/www.test.com', 225 'SCRIPT_FILENAME' => '/var/www/www.test.com/app/app.php', 226 'SCRIPT_NAME' => '/app/app.php', 227 'PHP_SELF' => '/app/app.php/apparthotel-1234', 228 )); 229 $this->assertEquals('http://test.com/apparthotel-1234', $request->getUri()); 230 $this->assertEquals('/apparthotel-1234', $request->getPathInfo()); 231 $this->assertEquals('', $request->getQueryString()); 232 $this->assertEquals(80, $request->getPort()); 233 $this->assertEquals('test.com', $request->getHttpHost()); 234 $this->assertFalse($request->isSecure()); 235 } 236 237 public function testCreateCheckPrecedence() 238 { 239 // server is used by default 240 $request = Request::create('/', 'DELETE', array(), array(), array(), array( 241 'HTTP_HOST' => 'example.com', 242 'HTTPS' => 'on', 243 'SERVER_PORT' => 443, 244 'PHP_AUTH_USER' => 'fabien', 245 'PHP_AUTH_PW' => 'pa$$', 246 'QUERY_STRING' => 'foo=bar', 247 'CONTENT_TYPE' => 'application/json', 248 )); 249 $this->assertEquals('example.com', $request->getHost()); 250 $this->assertEquals(443, $request->getPort()); 251 $this->assertTrue($request->isSecure()); 252 $this->assertEquals('fabien', $request->getUser()); 253 $this->assertEquals('pa$$', $request->getPassword()); 254 $this->assertEquals('', $request->getQueryString()); 255 $this->assertEquals('application/json', $request->headers->get('CONTENT_TYPE')); 256 257 // URI has precedence over server 258 $request = Request::create('http://thomas:pokemon@example.net:8080/?foo=bar', 'GET', array(), array(), array(), array( 259 'HTTP_HOST' => 'example.com', 260 'HTTPS' => 'on', 261 'SERVER_PORT' => 443, 262 )); 263 $this->assertEquals('example.net', $request->getHost()); 264 $this->assertEquals(8080, $request->getPort()); 265 $this->assertFalse($request->isSecure()); 266 $this->assertEquals('thomas', $request->getUser()); 267 $this->assertEquals('pokemon', $request->getPassword()); 268 $this->assertEquals('foo=bar', $request->getQueryString()); 269 } 270 271 public function testDuplicate() 272 { 273 $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar')); 274 $dup = $request->duplicate(); 275 276 $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters'); 277 $this->assertEquals($request->request->all(), $dup->request->all(), '->duplicate() duplicates a request an copy the current request parameters'); 278 $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes'); 279 $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers'); 280 281 $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar')); 282 283 $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided'); 284 $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided'); 285 $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided'); 286 $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided'); 287 } 288 289 public function testDuplicateWithFormat() 290 { 291 $request = new Request(array(), array(), array('_format' => 'json')); 292 $dup = $request->duplicate(); 293 294 $this->assertEquals('json', $dup->getRequestFormat()); 295 $this->assertEquals('json', $dup->attributes->get('_format')); 296 297 $request = new Request(); 298 $request->setRequestFormat('xml'); 299 $dup = $request->duplicate(); 300 301 $this->assertEquals('xml', $dup->getRequestFormat()); 302 } 303 304 /** 305 * @dataProvider getFormatToMimeTypeMapProviderWithAdditionalNullFormat 306 */ 307 public function testGetFormatFromMimeType($format, $mimeTypes) 308 { 309 $request = new Request(); 310 foreach ($mimeTypes as $mime) { 311 $this->assertEquals($format, $request->getFormat($mime)); 312 } 313 $request->setFormat($format, $mimeTypes); 314 foreach ($mimeTypes as $mime) { 315 $this->assertEquals($format, $request->getFormat($mime)); 316 317 if (null !== $format) { 318 $this->assertEquals($mimeTypes[0], $request->getMimeType($format)); 319 } 320 } 321 } 322 323 public function getFormatToMimeTypeMapProviderWithAdditionalNullFormat() 324 { 325 return array_merge( 326 array(array(null, array(null, 'unexistent-mime-type'))), 327 $this->getFormatToMimeTypeMapProvider() 328 ); 329 } 330 331 public function testGetFormatFromMimeTypeWithParameters() 332 { 333 $request = new Request(); 334 $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8')); 335 } 336 337 /** 338 * @dataProvider getFormatToMimeTypeMapProvider 339 */ 340 public function testGetMimeTypeFromFormat($format, $mimeTypes) 341 { 342 $request = new Request(); 343 $this->assertEquals($mimeTypes[0], $request->getMimeType($format)); 344 } 345 346 /** 347 * @dataProvider getFormatToMimeTypeMapProvider 348 */ 349 public function testGetMimeTypesFromFormat($format, $mimeTypes) 350 { 351 $this->assertEquals($mimeTypes, Request::getMimeTypes($format)); 352 } 353 354 public function testGetMimeTypesFromInexistentFormat() 355 { 356 $request = new Request(); 357 $this->assertNull($request->getMimeType('foo')); 358 $this->assertEquals(array(), Request::getMimeTypes('foo')); 359 } 360 361 public function testGetFormatWithCustomMimeType() 362 { 363 $request = new Request(); 364 $request->setFormat('custom', 'application/vnd.foo.api;myversion=2.3'); 365 $this->assertEquals('custom', $request->getFormat('application/vnd.foo.api;myversion=2.3')); 366 } 367 368 public function getFormatToMimeTypeMapProvider() 369 { 370 return array( 371 array('txt', array('text/plain')), 372 array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')), 373 array('css', array('text/css')), 374 array('json', array('application/json', 'application/x-json')), 375 array('jsonld', array('application/ld+json')), 376 array('xml', array('text/xml', 'application/xml', 'application/x-xml')), 377 array('rdf', array('application/rdf+xml')), 378 array('atom', array('application/atom+xml')), 379 ); 380 } 381 382 public function testGetUri() 383 { 384 $server = array(); 385 386 // Standard Request on non default PORT 387 // http://host:8080/index.php/path/info?query=string 388 389 $server['HTTP_HOST'] = 'host:8080'; 390 $server['SERVER_NAME'] = 'servername'; 391 $server['SERVER_PORT'] = '8080'; 392 393 $server['QUERY_STRING'] = 'query=string'; 394 $server['REQUEST_URI'] = '/index.php/path/info?query=string'; 395 $server['SCRIPT_NAME'] = '/index.php'; 396 $server['PATH_INFO'] = '/path/info'; 397 $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info'; 398 $server['PHP_SELF'] = '/index_dev.php/path/info'; 399 $server['SCRIPT_FILENAME'] = '/some/where/index.php'; 400 401 $request = new Request(); 402 403 $request->initialize(array(), array(), array(), array(), array(), $server); 404 405 $this->assertEquals('http://host:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port'); 406 407 // Use std port number 408 $server['HTTP_HOST'] = 'host'; 409 $server['SERVER_NAME'] = 'servername'; 410 $server['SERVER_PORT'] = '80'; 411 412 $request->initialize(array(), array(), array(), array(), array(), $server); 413 414 $this->assertEquals('http://host/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port'); 415 416 // Without HOST HEADER 417 unset($server['HTTP_HOST']); 418 $server['SERVER_NAME'] = 'servername'; 419 $server['SERVER_PORT'] = '80'; 420 421 $request->initialize(array(), array(), array(), array(), array(), $server); 422 423 $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER'); 424 425 // Request with URL REWRITING (hide index.php) 426 // RewriteCond %{REQUEST_FILENAME} !-f 427 // RewriteRule ^(.*)$ index.php [QSA,L] 428 // http://host:8080/path/info?query=string 429 $server = array(); 430 $server['HTTP_HOST'] = 'host:8080'; 431 $server['SERVER_NAME'] = 'servername'; 432 $server['SERVER_PORT'] = '8080'; 433 434 $server['REDIRECT_QUERY_STRING'] = 'query=string'; 435 $server['REDIRECT_URL'] = '/path/info'; 436 $server['SCRIPT_NAME'] = '/index.php'; 437 $server['QUERY_STRING'] = 'query=string'; 438 $server['REQUEST_URI'] = '/path/info?toto=test&1=1'; 439 $server['SCRIPT_NAME'] = '/index.php'; 440 $server['PHP_SELF'] = '/index.php'; 441 $server['SCRIPT_FILENAME'] = '/some/where/index.php'; 442 443 $request->initialize(array(), array(), array(), array(), array(), $server); 444 $this->assertEquals('http://host:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite'); 445 446 // Use std port number 447 // http://host/path/info?query=string 448 $server['HTTP_HOST'] = 'host'; 449 $server['SERVER_NAME'] = 'servername'; 450 $server['SERVER_PORT'] = '80'; 451 452 $request->initialize(array(), array(), array(), array(), array(), $server); 453 454 $this->assertEquals('http://host/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port'); 455 456 // Without HOST HEADER 457 unset($server['HTTP_HOST']); 458 $server['SERVER_NAME'] = 'servername'; 459 $server['SERVER_PORT'] = '80'; 460 461 $request->initialize(array(), array(), array(), array(), array(), $server); 462 463 $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER'); 464 465 // With encoded characters 466 467 $server = array( 468 'HTTP_HOST' => 'host:8080', 469 'SERVER_NAME' => 'servername', 470 'SERVER_PORT' => '8080', 471 'QUERY_STRING' => 'query=string', 472 'REQUEST_URI' => '/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', 473 'SCRIPT_NAME' => '/ba se/index_dev.php', 474 'PATH_TRANSLATED' => 'redirect:/index.php/foo bar/in+fo', 475 'PHP_SELF' => '/ba se/index_dev.php/path/info', 476 'SCRIPT_FILENAME' => '/some/where/ba se/index_dev.php', 477 ); 478 479 $request->initialize(array(), array(), array(), array(), array(), $server); 480 481 $this->assertEquals( 482 'http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', 483 $request->getUri() 484 ); 485 486 // with user info 487 488 $server['PHP_AUTH_USER'] = 'fabien'; 489 $request->initialize(array(), array(), array(), array(), array(), $server); 490 $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri()); 491 492 $server['PHP_AUTH_PW'] = 'symfony'; 493 $request->initialize(array(), array(), array(), array(), array(), $server); 494 $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri()); 495 } 496 497 public function testGetUriForPath() 498 { 499 $request = Request::create('http://test.com/foo?bar=baz'); 500 $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path')); 501 502 $request = Request::create('http://test.com:90/foo?bar=baz'); 503 $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path')); 504 505 $request = Request::create('https://test.com/foo?bar=baz'); 506 $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path')); 507 508 $request = Request::create('https://test.com:90/foo?bar=baz'); 509 $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path')); 510 511 $server = array(); 512 513 // Standard Request on non default PORT 514 // http://host:8080/index.php/path/info?query=string 515 516 $server['HTTP_HOST'] = 'host:8080'; 517 $server['SERVER_NAME'] = 'servername'; 518 $server['SERVER_PORT'] = '8080'; 519 520 $server['QUERY_STRING'] = 'query=string'; 521 $server['REQUEST_URI'] = '/index.php/path/info?query=string'; 522 $server['SCRIPT_NAME'] = '/index.php'; 523 $server['PATH_INFO'] = '/path/info'; 524 $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info'; 525 $server['PHP_SELF'] = '/index_dev.php/path/info'; 526 $server['SCRIPT_FILENAME'] = '/some/where/index.php'; 527 528 $request = new Request(); 529 530 $request->initialize(array(), array(), array(), array(), array(), $server); 531 532 $this->assertEquals('http://host:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port'); 533 534 // Use std port number 535 $server['HTTP_HOST'] = 'host'; 536 $server['SERVER_NAME'] = 'servername'; 537 $server['SERVER_PORT'] = '80'; 538 539 $request->initialize(array(), array(), array(), array(), array(), $server); 540 541 $this->assertEquals('http://host/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port'); 542 543 // Without HOST HEADER 544 unset($server['HTTP_HOST']); 545 $server['SERVER_NAME'] = 'servername'; 546 $server['SERVER_PORT'] = '80'; 547 548 $request->initialize(array(), array(), array(), array(), array(), $server); 549 550 $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER'); 551 552 // Request with URL REWRITING (hide index.php) 553 // RewriteCond %{REQUEST_FILENAME} !-f 554 // RewriteRule ^(.*)$ index.php [QSA,L] 555 // http://host:8080/path/info?query=string 556 $server = array(); 557 $server['HTTP_HOST'] = 'host:8080'; 558 $server['SERVER_NAME'] = 'servername'; 559 $server['SERVER_PORT'] = '8080'; 560 561 $server['REDIRECT_QUERY_STRING'] = 'query=string'; 562 $server['REDIRECT_URL'] = '/path/info'; 563 $server['SCRIPT_NAME'] = '/index.php'; 564 $server['QUERY_STRING'] = 'query=string'; 565 $server['REQUEST_URI'] = '/path/info?toto=test&1=1'; 566 $server['SCRIPT_NAME'] = '/index.php'; 567 $server['PHP_SELF'] = '/index.php'; 568 $server['SCRIPT_FILENAME'] = '/some/where/index.php'; 569 570 $request->initialize(array(), array(), array(), array(), array(), $server); 571 $this->assertEquals('http://host:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite'); 572 573 // Use std port number 574 // http://host/path/info?query=string 575 $server['HTTP_HOST'] = 'host'; 576 $server['SERVER_NAME'] = 'servername'; 577 $server['SERVER_PORT'] = '80'; 578 579 $request->initialize(array(), array(), array(), array(), array(), $server); 580 581 $this->assertEquals('http://host/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port'); 582 583 // Without HOST HEADER 584 unset($server['HTTP_HOST']); 585 $server['SERVER_NAME'] = 'servername'; 586 $server['SERVER_PORT'] = '80'; 587 588 $request->initialize(array(), array(), array(), array(), array(), $server); 589 590 $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER'); 591 $this->assertEquals('servername', $request->getHttpHost()); 592 593 // with user info 594 595 $server['PHP_AUTH_USER'] = 'fabien'; 596 $request->initialize(array(), array(), array(), array(), array(), $server); 597 $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path')); 598 599 $server['PHP_AUTH_PW'] = 'symfony'; 600 $request->initialize(array(), array(), array(), array(), array(), $server); 601 $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path')); 602 } 603 604 /** 605 * @dataProvider getRelativeUriForPathData() 606 */ 607 public function testGetRelativeUriForPath($expected, $pathinfo, $path) 608 { 609 $this->assertEquals($expected, Request::create($pathinfo)->getRelativeUriForPath($path)); 610 } 611 612 public function getRelativeUriForPathData() 613 { 614 return array( 615 array('me.png', '/foo', '/me.png'), 616 array('../me.png', '/foo/bar', '/me.png'), 617 array('me.png', '/foo/bar', '/foo/me.png'), 618 array('../baz/me.png', '/foo/bar/b', '/foo/baz/me.png'), 619 array('../../fooz/baz/me.png', '/foo/bar/b', '/fooz/baz/me.png'), 620 array('baz/me.png', '/foo/bar/b', 'baz/me.png'), 621 ); 622 } 623 624 public function testGetUserInfo() 625 { 626 $request = new Request(); 627 628 $server = array('PHP_AUTH_USER' => 'fabien'); 629 $request->initialize(array(), array(), array(), array(), array(), $server); 630 $this->assertEquals('fabien', $request->getUserInfo()); 631 632 $server['PHP_AUTH_USER'] = '0'; 633 $request->initialize(array(), array(), array(), array(), array(), $server); 634 $this->assertEquals('0', $request->getUserInfo()); 635 636 $server['PHP_AUTH_PW'] = '0'; 637 $request->initialize(array(), array(), array(), array(), array(), $server); 638 $this->assertEquals('0:0', $request->getUserInfo()); 639 } 640 641 public function testGetSchemeAndHttpHost() 642 { 643 $request = new Request(); 644 645 $server = array(); 646 $server['SERVER_NAME'] = 'servername'; 647 $server['SERVER_PORT'] = '90'; 648 $request->initialize(array(), array(), array(), array(), array(), $server); 649 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); 650 651 $server['PHP_AUTH_USER'] = 'fabien'; 652 $request->initialize(array(), array(), array(), array(), array(), $server); 653 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); 654 655 $server['PHP_AUTH_USER'] = '0'; 656 $request->initialize(array(), array(), array(), array(), array(), $server); 657 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); 658 659 $server['PHP_AUTH_PW'] = '0'; 660 $request->initialize(array(), array(), array(), array(), array(), $server); 661 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); 662 } 663 664 /** 665 * @dataProvider getQueryStringNormalizationData 666 */ 667 public function testGetQueryString($query, $expectedQuery, $msg) 668 { 669 $request = new Request(); 670 671 $request->server->set('QUERY_STRING', $query); 672 $this->assertSame($expectedQuery, $request->getQueryString(), $msg); 673 } 674 675 public function getQueryStringNormalizationData() 676 { 677 return array( 678 array('foo', 'foo', 'works with valueless parameters'), 679 array('foo=', 'foo=', 'includes a dangling equal sign'), 680 array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'), 681 array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'), 682 683 // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded). 684 // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. 685 array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'), 686 687 array('foo[]=1&foo[]=2', 'foo%5B%5D=1&foo%5B%5D=2', 'allows array notation'), 688 array('foo=1&foo=2', 'foo=1&foo=2', 'allows repeated parameters'), 689 array('pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'), 690 array('0', '0', 'allows "0"'), 691 array('Jane Doe&John%20Doe', 'Jane%20Doe&John%20Doe', 'normalizes encoding in keys'), 692 array('her=Jane Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes encoding in values'), 693 array('foo=bar&&&test&&', 'foo=bar&test', 'removes unneeded delimiters'), 694 array('formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'), 695 696 // Ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway. 697 // PHP also does not include them when building _GET. 698 array('foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'), 699 ); 700 } 701 702 public function testGetQueryStringReturnsNull() 703 { 704 $request = new Request(); 705 706 $this->assertNull($request->getQueryString(), '->getQueryString() returns null for non-existent query string'); 707 708 $request->server->set('QUERY_STRING', ''); 709 $this->assertNull($request->getQueryString(), '->getQueryString() returns null for empty query string'); 710 } 711 712 public function testGetHost() 713 { 714 $request = new Request(); 715 716 $request->initialize(array('foo' => 'bar')); 717 $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized'); 718 719 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com')); 720 $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header'); 721 722 // Host header with port number 723 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com:8080')); 724 $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header with port number'); 725 726 // Server values 727 $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com')); 728 $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from server name'); 729 730 $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com', 'HTTP_HOST' => 'www.host.com')); 731 $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME '); 732 } 733 734 public function testGetPort() 735 { 736 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 737 'HTTP_X_FORWARDED_PROTO' => 'https', 738 'HTTP_X_FORWARDED_PORT' => '443', 739 )); 740 $port = $request->getPort(); 741 742 $this->assertEquals(80, $port, 'Without trusted proxies FORWARDED_PROTO and FORWARDED_PORT are ignored.'); 743 744 Request::setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_ALL); 745 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 746 'HTTP_X_FORWARDED_PROTO' => 'https', 747 'HTTP_X_FORWARDED_PORT' => '8443', 748 )); 749 $this->assertEquals(80, $request->getPort(), 'With PROTO and PORT on untrusted connection server value takes precedence.'); 750 $request->server->set('REMOTE_ADDR', '1.1.1.1'); 751 $this->assertEquals(8443, $request->getPort(), 'With PROTO and PORT set PORT takes precedence.'); 752 753 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 754 'HTTP_X_FORWARDED_PROTO' => 'https', 755 )); 756 $this->assertEquals(80, $request->getPort(), 'With only PROTO set getPort() ignores trusted headers on untrusted connection.'); 757 $request->server->set('REMOTE_ADDR', '1.1.1.1'); 758 $this->assertEquals(443, $request->getPort(), 'With only PROTO set getPort() defaults to 443.'); 759 760 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 761 'HTTP_X_FORWARDED_PROTO' => 'http', 762 )); 763 $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() ignores trusted headers on untrusted connection.'); 764 $request->server->set('REMOTE_ADDR', '1.1.1.1'); 765 $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() returns port of the original request.'); 766 767 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 768 'HTTP_X_FORWARDED_PROTO' => 'On', 769 )); 770 $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is On, getPort() ignores trusted headers on untrusted connection.'); 771 $request->server->set('REMOTE_ADDR', '1.1.1.1'); 772 $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is On, getPort() defaults to 443.'); 773 774 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 775 'HTTP_X_FORWARDED_PROTO' => '1', 776 )); 777 $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is 1, getPort() ignores trusted headers on untrusted connection.'); 778 $request->server->set('REMOTE_ADDR', '1.1.1.1'); 779 $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is 1, getPort() defaults to 443.'); 780 781 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 782 'HTTP_X_FORWARDED_PROTO' => 'something-else', 783 )); 784 $port = $request->getPort(); 785 $this->assertEquals(80, $port, 'With only PROTO set and value is not recognized, getPort() defaults to 80.'); 786 } 787 788 /** 789 * @expectedException \RuntimeException 790 */ 791 public function testGetHostWithFakeHttpHostValue() 792 { 793 $request = new Request(); 794 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.host.com?query=string')); 795 $request->getHost(); 796 } 797 798 public function testGetSetMethod() 799 { 800 $request = new Request(); 801 802 $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined'); 803 804 $request->setMethod('get'); 805 $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string'); 806 807 $request->setMethod('PURGE'); 808 $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one'); 809 810 $request->setMethod('POST'); 811 $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined'); 812 813 $request->setMethod('POST'); 814 $request->request->set('_method', 'purge'); 815 $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled'); 816 817 $request = new Request(); 818 $request->setMethod('POST'); 819 $request->request->set('_method', 'purge'); 820 821 $this->assertFalse(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be disabled by default'); 822 823 Request::enableHttpMethodParameterOverride(); 824 825 $this->assertTrue(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be enabled now but it is not'); 826 827 $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST'); 828 $this->disableHttpMethodParameterOverride(); 829 830 $request = new Request(); 831 $request->setMethod('POST'); 832 $request->query->set('_method', 'purge'); 833 $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled'); 834 835 $request = new Request(); 836 $request->setMethod('POST'); 837 $request->query->set('_method', 'purge'); 838 Request::enableHttpMethodParameterOverride(); 839 $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST'); 840 $this->disableHttpMethodParameterOverride(); 841 842 $request = new Request(); 843 $request->setMethod('POST'); 844 $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete'); 845 $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override even though _method is set if defined and POST'); 846 847 $request = new Request(); 848 $request->setMethod('POST'); 849 $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete'); 850 $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override if defined and POST'); 851 } 852 853 /** 854 * @dataProvider getClientIpsProvider 855 */ 856 public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trustedProxies) 857 { 858 $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies); 859 860 $this->assertEquals($expected[0], $request->getClientIp()); 861 } 862 863 /** 864 * @dataProvider getClientIpsProvider 865 */ 866 public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $trustedProxies) 867 { 868 $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies); 869 870 $this->assertEquals($expected, $request->getClientIps()); 871 } 872 873 /** 874 * @dataProvider getClientIpsForwardedProvider 875 */ 876 public function testGetClientIpsForwarded($expected, $remoteAddr, $httpForwarded, $trustedProxies) 877 { 878 $request = $this->getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies); 879 880 $this->assertEquals($expected, $request->getClientIps()); 881 } 882 883 public function getClientIpsForwardedProvider() 884 { 885 // $expected $remoteAddr $httpForwarded $trustedProxies 886 return array( 887 array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', null), 888 array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')), 889 array(array('88.88.88.88'), '127.0.0.1', 'for="88.88.88.88:80"', array('127.0.0.1')), 890 array(array('192.0.2.60'), '::1', 'for=192.0.2.60;proto=http;by=203.0.113.43', array('::1')), 891 array(array('2620:0:1cfe:face:b00c::3', '192.0.2.43'), '::1', 'for=192.0.2.43, for=2620:0:1cfe:face:b00c::3', array('::1')), 892 array(array('2001:db8:cafe::17'), '::1', 'for="[2001:db8:cafe::17]:4711', array('::1')), 893 ); 894 } 895 896 public function getClientIpsProvider() 897 { 898 // $expected $remoteAddr $httpForwardedFor $trustedProxies 899 return array( 900 // simple IPv4 901 array(array('88.88.88.88'), '88.88.88.88', null, null), 902 // trust the IPv4 remote addr 903 array(array('88.88.88.88'), '88.88.88.88', null, array('88.88.88.88')), 904 905 // simple IPv6 906 array(array('::1'), '::1', null, null), 907 // trust the IPv6 remote addr 908 array(array('::1'), '::1', null, array('::1')), 909 910 // forwarded for with remote IPv4 addr not trusted 911 array(array('127.0.0.1'), '127.0.0.1', '88.88.88.88', null), 912 // forwarded for with remote IPv4 addr trusted 913 array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1')), 914 // forwarded for with remote IPv4 and all FF addrs trusted 915 array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1', '88.88.88.88')), 916 // forwarded for with remote IPv4 range trusted 917 array(array('88.88.88.88'), '123.45.67.89', '88.88.88.88', array('123.45.67.0/24')), 918 919 // forwarded for with remote IPv6 addr not trusted 920 array(array('1620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', null), 921 // forwarded for with remote IPv6 addr trusted 922 array(array('2620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')), 923 // forwarded for with remote IPv6 range trusted 924 array(array('88.88.88.88'), '2a01:198:603:0:396e:4789:8e99:890f', '88.88.88.88', array('2a01:198:603:0::/65')), 925 926 // multiple forwarded for with remote IPv4 addr trusted 927 array(array('88.88.88.88', '87.65.43.21', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89')), 928 // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted 929 array(array('87.65.43.21', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')), 930 // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle 931 array(array('88.88.88.88', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21')), 932 // multiple forwarded for with remote IPv4 addr and all reverse proxies trusted 933 array(array('127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21', '88.88.88.88', '127.0.0.1')), 934 935 // multiple forwarded for with remote IPv6 addr trusted 936 array(array('2620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')), 937 // multiple forwarded for with remote IPv6 addr and some reverse proxies trusted 938 array(array('3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3')), 939 // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle 940 array(array('2620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3,3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3')), 941 942 // client IP with port 943 array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88:12345, 127.0.0.1', array('127.0.0.1')), 944 945 // invalid forwarded IP is ignored 946 array(array('88.88.88.88'), '127.0.0.1', 'unknown,88.88.88.88', array('127.0.0.1')), 947 array(array('88.88.88.88'), '127.0.0.1', '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2,88.88.88.88', array('127.0.0.1')), 948 ); 949 } 950 951 /** 952 * @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException 953 * @dataProvider getClientIpsWithConflictingHeadersProvider 954 */ 955 public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXForwardedFor) 956 { 957 $request = new Request(); 958 959 $server = array( 960 'REMOTE_ADDR' => '88.88.88.88', 961 'HTTP_FORWARDED' => $httpForwarded, 962 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor, 963 ); 964 965 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL | Request::HEADER_FORWARDED); 966 967 $request->initialize(array(), array(), array(), array(), array(), $server); 968 969 $request->getClientIps(); 970 } 971 972 /** 973 * @dataProvider getClientIpsWithConflictingHeadersProvider 974 */ 975 public function testGetClientIpsOnlyXHttpForwardedForTrusted($httpForwarded, $httpXForwardedFor) 976 { 977 $request = new Request(); 978 979 $server = array( 980 'REMOTE_ADDR' => '88.88.88.88', 981 'HTTP_FORWARDED' => $httpForwarded, 982 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor, 983 ); 984 985 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_FOR); 986 987 $request->initialize(array(), array(), array(), array(), array(), $server); 988 989 $this->assertSame(array_reverse(explode(',', $httpXForwardedFor)), $request->getClientIps()); 990 } 991 992 public function getClientIpsWithConflictingHeadersProvider() 993 { 994 // $httpForwarded $httpXForwardedFor 995 return array( 996 array('for=87.65.43.21', '192.0.2.60'), 997 array('for=87.65.43.21, for=192.0.2.60', '192.0.2.60'), 998 array('for=192.0.2.60', '192.0.2.60,87.65.43.21'), 999 array('for="::face", for=192.0.2.60', '192.0.2.60,192.0.2.43'), 1000 array('for=87.65.43.21, for=192.0.2.60', '192.0.2.60,87.65.43.21'), 1001 ); 1002 } 1003 1004 /** 1005 * @dataProvider getClientIpsWithAgreeingHeadersProvider 1006 */ 1007 public function testGetClientIpsWithAgreeingHeaders($httpForwarded, $httpXForwardedFor, $expectedIps) 1008 { 1009 $request = new Request(); 1010 1011 $server = array( 1012 'REMOTE_ADDR' => '88.88.88.88', 1013 'HTTP_FORWARDED' => $httpForwarded, 1014 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor, 1015 ); 1016 1017 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL); 1018 1019 $request->initialize(array(), array(), array(), array(), array(), $server); 1020 1021 $clientIps = $request->getClientIps(); 1022 1023 $this->assertSame($expectedIps, $clientIps); 1024 } 1025 1026 public function getClientIpsWithAgreeingHeadersProvider() 1027 { 1028 // $httpForwarded $httpXForwardedFor 1029 return array( 1030 array('for="192.0.2.60"', '192.0.2.60', array('192.0.2.60')), 1031 array('for=192.0.2.60, for=87.65.43.21', '192.0.2.60,87.65.43.21', array('87.65.43.21', '192.0.2.60')), 1032 array('for="[::face]", for=192.0.2.60', '::face,192.0.2.60', array('192.0.2.60', '::face')), 1033 array('for="192.0.2.60:80"', '192.0.2.60', array('192.0.2.60')), 1034 array('for=192.0.2.60;proto=http;by=203.0.113.43', '192.0.2.60', array('192.0.2.60')), 1035 array('for="[2001:db8:cafe::17]:4711"', '2001:db8:cafe::17', array('2001:db8:cafe::17')), 1036 ); 1037 } 1038 1039 public function testGetContentWorksTwiceInDefaultMode() 1040 { 1041 $req = new Request(); 1042 $this->assertEquals('', $req->getContent()); 1043 $this->assertEquals('', $req->getContent()); 1044 } 1045 1046 public function testGetContentReturnsResource() 1047 { 1048 $req = new Request(); 1049 $retval = $req->getContent(true); 1050 $this->assertInternalType('resource', $retval); 1051 $this->assertEquals('', fread($retval, 1)); 1052 $this->assertTrue(feof($retval)); 1053 } 1054 1055 public function testGetContentReturnsResourceWhenContentSetInConstructor() 1056 { 1057 $req = new Request(array(), array(), array(), array(), array(), array(), 'MyContent'); 1058 $resource = $req->getContent(true); 1059 1060 $this->assertInternalType('resource', $resource); 1061 $this->assertEquals('MyContent', stream_get_contents($resource)); 1062 } 1063 1064 public function testContentAsResource() 1065 { 1066 $resource = fopen('php://memory', 'r+'); 1067 fwrite($resource, 'My other content'); 1068 rewind($resource); 1069 1070 $req = new Request(array(), array(), array(), array(), array(), array(), $resource); 1071 $this->assertEquals('My other content', stream_get_contents($req->getContent(true))); 1072 $this->assertEquals('My other content', $req->getContent()); 1073 } 1074 1075 /** 1076 * @expectedException \LogicException 1077 * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider 1078 */ 1079 public function testGetContentCantBeCalledTwiceWithResources($first, $second) 1080 { 1081 if (\PHP_VERSION_ID >= 50600) { 1082 $this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.'); 1083 } 1084 1085 $req = new Request(); 1086 $req->getContent($first); 1087 $req->getContent($second); 1088 } 1089 1090 public function getContentCantBeCalledTwiceWithResourcesProvider() 1091 { 1092 return array( 1093 'Resource then fetch' => array(true, false), 1094 'Resource then resource' => array(true, true), 1095 ); 1096 } 1097 1098 /** 1099 * @dataProvider getContentCanBeCalledTwiceWithResourcesProvider 1100 * @requires PHP 5.6 1101 */ 1102 public function testGetContentCanBeCalledTwiceWithResources($first, $second) 1103 { 1104 $req = new Request(); 1105 $a = $req->getContent($first); 1106 $b = $req->getContent($second); 1107 1108 if ($first) { 1109 $a = stream_get_contents($a); 1110 } 1111 1112 if ($second) { 1113 $b = stream_get_contents($b); 1114 } 1115 1116 $this->assertSame($a, $b); 1117 } 1118 1119 public function getContentCanBeCalledTwiceWithResourcesProvider() 1120 { 1121 return array( 1122 'Fetch then fetch' => array(false, false), 1123 'Fetch then resource' => array(false, true), 1124 'Resource then fetch' => array(true, false), 1125 'Resource then resource' => array(true, true), 1126 ); 1127 } 1128 1129 public function provideOverloadedMethods() 1130 { 1131 return array( 1132 array('PUT'), 1133 array('DELETE'), 1134 array('PATCH'), 1135 array('put'), 1136 array('delete'), 1137 array('patch'), 1138 ); 1139 } 1140 1141 /** 1142 * @dataProvider provideOverloadedMethods 1143 */ 1144 public function testCreateFromGlobals($method) 1145 { 1146 $normalizedMethod = strtoupper($method); 1147 1148 $_GET['foo1'] = 'bar1'; 1149 $_POST['foo2'] = 'bar2'; 1150 $_COOKIE['foo3'] = 'bar3'; 1151 $_FILES['foo4'] = array('bar4'); 1152 $_SERVER['foo5'] = 'bar5'; 1153 1154 $request = Request::createFromGlobals(); 1155 $this->assertEquals('bar1', $request->query->get('foo1'), '::fromGlobals() uses values from $_GET'); 1156 $this->assertEquals('bar2', $request->request->get('foo2'), '::fromGlobals() uses values from $_POST'); 1157 $this->assertEquals('bar3', $request->cookies->get('foo3'), '::fromGlobals() uses values from $_COOKIE'); 1158 $this->assertEquals(array('bar4'), $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES'); 1159 $this->assertEquals('bar5', $request->server->get('foo5'), '::fromGlobals() uses values from $_SERVER'); 1160 1161 unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']); 1162 1163 $_SERVER['REQUEST_METHOD'] = $method; 1164 $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; 1165 $request = RequestContentProxy::createFromGlobals(); 1166 $this->assertEquals($normalizedMethod, $request->getMethod()); 1167 $this->assertEquals('mycontent', $request->request->get('content')); 1168 1169 unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']); 1170 1171 Request::createFromGlobals(); 1172 Request::enableHttpMethodParameterOverride(); 1173 $_POST['_method'] = $method; 1174 $_POST['foo6'] = 'bar6'; 1175 $_SERVER['REQUEST_METHOD'] = 'PoSt'; 1176 $request = Request::createFromGlobals(); 1177 $this->assertEquals($normalizedMethod, $request->getMethod()); 1178 $this->assertEquals('POST', $request->getRealMethod()); 1179 $this->assertEquals('bar6', $request->request->get('foo6')); 1180 1181 unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']); 1182 $this->disableHttpMethodParameterOverride(); 1183 } 1184 1185 public function testOverrideGlobals() 1186 { 1187 $request = new Request(); 1188 $request->initialize(array('foo' => 'bar')); 1189 1190 // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it 1191 $server = $_SERVER; 1192 1193 $request->overrideGlobals(); 1194 1195 $this->assertEquals(array('foo' => 'bar'), $_GET); 1196 1197 $request->initialize(array(), array('foo' => 'bar')); 1198 $request->overrideGlobals(); 1199 1200 $this->assertEquals(array('foo' => 'bar'), $_POST); 1201 1202 $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER); 1203 1204 $request->headers->set('X_FORWARDED_PROTO', 'https'); 1205 1206 Request::setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_ALL); 1207 $this->assertFalse($request->isSecure()); 1208 $request->server->set('REMOTE_ADDR', '1.1.1.1'); 1209 $this->assertTrue($request->isSecure()); 1210 1211 $request->overrideGlobals(); 1212 1213 $this->assertArrayHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER); 1214 1215 $request->headers->set('CONTENT_TYPE', 'multipart/form-data'); 1216 $request->headers->set('CONTENT_LENGTH', 12345); 1217 1218 $request->overrideGlobals(); 1219 1220 $this->assertArrayHasKey('CONTENT_TYPE', $_SERVER); 1221 $this->assertArrayHasKey('CONTENT_LENGTH', $_SERVER); 1222 1223 $request->initialize(array('foo' => 'bar', 'baz' => 'foo')); 1224 $request->query->remove('baz'); 1225 1226 $request->overrideGlobals(); 1227 1228 $this->assertEquals(array('foo' => 'bar'), $_GET); 1229 $this->assertEquals('foo=bar', $_SERVER['QUERY_STRING']); 1230 $this->assertEquals('foo=bar', $request->server->get('QUERY_STRING')); 1231 1232 // restore initial $_SERVER array 1233 $_SERVER = $server; 1234 } 1235 1236 public function testGetScriptName() 1237 { 1238 $request = new Request(); 1239 $this->assertEquals('', $request->getScriptName()); 1240 1241 $server = array(); 1242 $server['SCRIPT_NAME'] = '/index.php'; 1243 1244 $request->initialize(array(), array(), array(), array(), array(), $server); 1245 1246 $this->assertEquals('/index.php', $request->getScriptName()); 1247 1248 $server = array(); 1249 $server['ORIG_SCRIPT_NAME'] = '/frontend.php'; 1250 $request->initialize(array(), array(), array(), array(), array(), $server); 1251 1252 $this->assertEquals('/frontend.php', $request->getScriptName()); 1253 1254 $server = array(); 1255 $server['SCRIPT_NAME'] = '/index.php'; 1256 $server['ORIG_SCRIPT_NAME'] = '/frontend.php'; 1257 $request->initialize(array(), array(), array(), array(), array(), $server); 1258 1259 $this->assertEquals('/index.php', $request->getScriptName()); 1260 } 1261 1262 public function testGetBasePath() 1263 { 1264 $request = new Request(); 1265 $this->assertEquals('', $request->getBasePath()); 1266 1267 $server = array(); 1268 $server['SCRIPT_FILENAME'] = '/some/where/index.php'; 1269 $request->initialize(array(), array(), array(), array(), array(), $server); 1270 $this->assertEquals('', $request->getBasePath()); 1271 1272 $server = array(); 1273 $server['SCRIPT_FILENAME'] = '/some/where/index.php'; 1274 $server['SCRIPT_NAME'] = '/index.php'; 1275 $request->initialize(array(), array(), array(), array(), array(), $server); 1276 1277 $this->assertEquals('', $request->getBasePath()); 1278 1279 $server = array(); 1280 $server['SCRIPT_FILENAME'] = '/some/where/index.php'; 1281 $server['PHP_SELF'] = '/index.php'; 1282 $request->initialize(array(), array(), array(), array(), array(), $server); 1283 1284 $this->assertEquals('', $request->getBasePath()); 1285 1286 $server = array(); 1287 $server['SCRIPT_FILENAME'] = '/some/where/index.php'; 1288 $server['ORIG_SCRIPT_NAME'] = '/index.php'; 1289 $request->initialize(array(), array(), array(), array(), array(), $server); 1290 1291 $this->assertEquals('', $request->getBasePath()); 1292 } 1293 1294 public function testGetPathInfo() 1295 { 1296 $request = new Request(); 1297 $this->assertEquals('/', $request->getPathInfo()); 1298 1299 $server = array(); 1300 $server['REQUEST_URI'] = '/path/info'; 1301 $request->initialize(array(), array(), array(), array(), array(), $server); 1302 1303 $this->assertEquals('/path/info', $request->getPathInfo()); 1304 1305 $server = array(); 1306 $server['REQUEST_URI'] = '/path%20test/info'; 1307 $request->initialize(array(), array(), array(), array(), array(), $server); 1308 1309 $this->assertEquals('/path%20test/info', $request->getPathInfo()); 1310 1311 $server = array(); 1312 $server['REQUEST_URI'] = '?a=b'; 1313 $request->initialize(array(), array(), array(), array(), array(), $server); 1314 1315 $this->assertEquals('/', $request->getPathInfo()); 1316 } 1317 1318 public function testGetParameterPrecedence() 1319 { 1320 $request = new Request(); 1321 $request->attributes->set('foo', 'attr'); 1322 $request->query->set('foo', 'query'); 1323 $request->request->set('foo', 'body'); 1324 1325 $this->assertSame('attr', $request->get('foo')); 1326 1327 $request->attributes->remove('foo'); 1328 $this->assertSame('query', $request->get('foo')); 1329 1330 $request->query->remove('foo'); 1331 $this->assertSame('body', $request->get('foo')); 1332 1333 $request->request->remove('foo'); 1334 $this->assertNull($request->get('foo')); 1335 } 1336 1337 public function testGetPreferredLanguage() 1338 { 1339 $request = new Request(); 1340 $this->assertNull($request->getPreferredLanguage()); 1341 $this->assertNull($request->getPreferredLanguage(array())); 1342 $this->assertEquals('fr', $request->getPreferredLanguage(array('fr'))); 1343 $this->assertEquals('fr', $request->getPreferredLanguage(array('fr', 'en'))); 1344 $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'fr'))); 1345 $this->assertEquals('fr-ch', $request->getPreferredLanguage(array('fr-ch', 'fr-fr'))); 1346 1347 $request = new Request(); 1348 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); 1349 $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'en-us'))); 1350 1351 $request = new Request(); 1352 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); 1353 $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); 1354 1355 $request = new Request(); 1356 $request->headers->set('Accept-language', 'zh, en-us; q=0.8'); 1357 $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); 1358 1359 $request = new Request(); 1360 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, fr-fr; q=0.6, fr; q=0.5'); 1361 $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); 1362 } 1363 1364 public function testIsXmlHttpRequest() 1365 { 1366 $request = new Request(); 1367 $this->assertFalse($request->isXmlHttpRequest()); 1368 1369 $request->headers->set('X-Requested-With', 'XMLHttpRequest'); 1370 $this->assertTrue($request->isXmlHttpRequest()); 1371 1372 $request->headers->remove('X-Requested-With'); 1373 $this->assertFalse($request->isXmlHttpRequest()); 1374 } 1375 1376 /** 1377 * @requires extension intl 1378 */ 1379 public function testIntlLocale() 1380 { 1381 $request = new Request(); 1382 1383 $request->setDefaultLocale('fr'); 1384 $this->assertEquals('fr', $request->getLocale()); 1385 $this->assertEquals('fr', \Locale::getDefault()); 1386 1387 $request->setLocale('en'); 1388 $this->assertEquals('en', $request->getLocale()); 1389 $this->assertEquals('en', \Locale::getDefault()); 1390 1391 $request->setDefaultLocale('de'); 1392 $this->assertEquals('en', $request->getLocale()); 1393 $this->assertEquals('en', \Locale::getDefault()); 1394 } 1395 1396 public function testGetCharsets() 1397 { 1398 $request = new Request(); 1399 $this->assertEquals(array(), $request->getCharsets()); 1400 $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6'); 1401 $this->assertEquals(array(), $request->getCharsets()); // testing caching 1402 1403 $request = new Request(); 1404 $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6'); 1405 $this->assertEquals(array('ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'), $request->getCharsets()); 1406 1407 $request = new Request(); 1408 $request->headers->set('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7'); 1409 $this->assertEquals(array('ISO-8859-1', 'utf-8', '*'), $request->getCharsets()); 1410 } 1411 1412 public function testGetEncodings() 1413 { 1414 $request = new Request(); 1415 $this->assertEquals(array(), $request->getEncodings()); 1416 $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch'); 1417 $this->assertEquals(array(), $request->getEncodings()); // testing caching 1418 1419 $request = new Request(); 1420 $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch'); 1421 $this->assertEquals(array('gzip', 'deflate', 'sdch'), $request->getEncodings()); 1422 1423 $request = new Request(); 1424 $request->headers->set('Accept-Encoding', 'gzip;q=0.4,deflate;q=0.9,compress;q=0.7'); 1425 $this->assertEquals(array('deflate', 'compress', 'gzip'), $request->getEncodings()); 1426 } 1427 1428 public function testGetAcceptableContentTypes() 1429 { 1430 $request = new Request(); 1431 $this->assertEquals(array(), $request->getAcceptableContentTypes()); 1432 $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*'); 1433 $this->assertEquals(array(), $request->getAcceptableContentTypes()); // testing caching 1434 1435 $request = new Request(); 1436 $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*'); 1437 $this->assertEquals(array('application/vnd.wap.wmlscriptc', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml', 'application/xhtml+xml', 'text/html', 'multipart/mixed', '*/*'), $request->getAcceptableContentTypes()); 1438 } 1439 1440 public function testGetLanguages() 1441 { 1442 $request = new Request(); 1443 $this->assertEquals(array(), $request->getLanguages()); 1444 1445 $request = new Request(); 1446 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); 1447 $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages()); 1448 $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages()); 1449 1450 $request = new Request(); 1451 $request->headers->set('Accept-language', 'zh, en-us; q=0.6, en; q=0.8'); 1452 $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test out of order qvalues 1453 1454 $request = new Request(); 1455 $request->headers->set('Accept-language', 'zh, en, en-us'); 1456 $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test equal weighting without qvalues 1457 1458 $request = new Request(); 1459 $request->headers->set('Accept-language', 'zh; q=0.6, en, en-us; q=0.6'); 1460 $this->assertEquals(array('en', 'zh', 'en_US'), $request->getLanguages()); // Test equal weighting with qvalues 1461 1462 $request = new Request(); 1463 $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6'); 1464 $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages()); 1465 } 1466 1467 public function testGetRequestFormat() 1468 { 1469 $request = new Request(); 1470 $this->assertEquals('html', $request->getRequestFormat()); 1471 1472 // Ensure that setting different default values over time is possible, 1473 // aka. setRequestFormat determines the state. 1474 $this->assertEquals('json', $request->getRequestFormat('json')); 1475 $this->assertEquals('html', $request->getRequestFormat('html')); 1476 1477 $request = new Request(); 1478 $this->assertNull($request->getRequestFormat(null)); 1479 1480 $request = new Request(); 1481 $this->assertNull($request->setRequestFormat('foo')); 1482 $this->assertEquals('foo', $request->getRequestFormat(null)); 1483 1484 $request = new Request(array('_format' => 'foo')); 1485 $this->assertEquals('html', $request->getRequestFormat()); 1486 } 1487 1488 public function testHasSession() 1489 { 1490 $request = new Request(); 1491 1492 $this->assertFalse($request->hasSession()); 1493 $request->setSession(new Session(new MockArraySessionStorage())); 1494 $this->assertTrue($request->hasSession()); 1495 } 1496 1497 public function testGetSession() 1498 { 1499 $request = new Request(); 1500 1501 $request->setSession(new Session(new MockArraySessionStorage())); 1502 $this->assertTrue($request->hasSession()); 1503 1504 $session = $request->getSession(); 1505 $this->assertObjectHasAttribute('storage', $session); 1506 $this->assertObjectHasAttribute('flashName', $session); 1507 $this->assertObjectHasAttribute('attributeName', $session); 1508 } 1509 1510 public function testHasPreviousSession() 1511 { 1512 $request = new Request(); 1513 1514 $this->assertFalse($request->hasPreviousSession()); 1515 $request->cookies->set('MOCKSESSID', 'foo'); 1516 $this->assertFalse($request->hasPreviousSession()); 1517 $request->setSession(new Session(new MockArraySessionStorage())); 1518 $this->assertTrue($request->hasPreviousSession()); 1519 } 1520 1521 public function testToString() 1522 { 1523 $request = new Request(); 1524 1525 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); 1526 $request->cookies->set('Foo', 'Bar'); 1527 1528 $asString = (string) $request; 1529 1530 $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString); 1531 $this->assertContains('Cookie: Foo=Bar', $asString); 1532 1533 $request->cookies->set('Another', 'Cookie'); 1534 1535 $asString = (string) $request; 1536 1537 $this->assertContains('Cookie: Foo=Bar; Another=Cookie', $asString); 1538 } 1539 1540 public function testIsMethod() 1541 { 1542 $request = new Request(); 1543 $request->setMethod('POST'); 1544 $this->assertTrue($request->isMethod('POST')); 1545 $this->assertTrue($request->isMethod('post')); 1546 $this->assertFalse($request->isMethod('GET')); 1547 $this->assertFalse($request->isMethod('get')); 1548 1549 $request->setMethod('GET'); 1550 $this->assertTrue($request->isMethod('GET')); 1551 $this->assertTrue($request->isMethod('get')); 1552 $this->assertFalse($request->isMethod('POST')); 1553 $this->assertFalse($request->isMethod('post')); 1554 } 1555 1556 /** 1557 * @dataProvider getBaseUrlData 1558 */ 1559 public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo) 1560 { 1561 $request = Request::create($uri, 'GET', array(), array(), array(), $server); 1562 1563 $this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl'); 1564 $this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo'); 1565 } 1566 1567 public function getBaseUrlData() 1568 { 1569 return array( 1570 array( 1571 '/fruit/strawberry/1234index.php/blah', 1572 array( 1573 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/fruit/index.php', 1574 'SCRIPT_NAME' => '/fruit/index.php', 1575 'PHP_SELF' => '/fruit/index.php', 1576 ), 1577 '/fruit', 1578 '/strawberry/1234index.php/blah', 1579 ), 1580 array( 1581 '/fruit/strawberry/1234index.php/blah', 1582 array( 1583 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/index.php', 1584 'SCRIPT_NAME' => '/index.php', 1585 'PHP_SELF' => '/index.php', 1586 ), 1587 '', 1588 '/fruit/strawberry/1234index.php/blah', 1589 ), 1590 array( 1591 '/foo%20bar/', 1592 array( 1593 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 1594 'SCRIPT_NAME' => '/foo bar/app.php', 1595 'PHP_SELF' => '/foo bar/app.php', 1596 ), 1597 '/foo%20bar', 1598 '/', 1599 ), 1600 array( 1601 '/foo%20bar/home', 1602 array( 1603 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 1604 'SCRIPT_NAME' => '/foo bar/app.php', 1605 'PHP_SELF' => '/foo bar/app.php', 1606 ), 1607 '/foo%20bar', 1608 '/home', 1609 ), 1610 array( 1611 '/foo%20bar/app.php/home', 1612 array( 1613 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 1614 'SCRIPT_NAME' => '/foo bar/app.php', 1615 'PHP_SELF' => '/foo bar/app.php', 1616 ), 1617 '/foo%20bar/app.php', 1618 '/home', 1619 ), 1620 array( 1621 '/foo%20bar/app.php/home%3Dbaz', 1622 array( 1623 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 1624 'SCRIPT_NAME' => '/foo bar/app.php', 1625 'PHP_SELF' => '/foo bar/app.php', 1626 ), 1627 '/foo%20bar/app.php', 1628 '/home%3Dbaz', 1629 ), 1630 array( 1631 '/foo/bar+baz', 1632 array( 1633 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php', 1634 'SCRIPT_NAME' => '/foo/app.php', 1635 'PHP_SELF' => '/foo/app.php', 1636 ), 1637 '/foo', 1638 '/bar+baz', 1639 ), 1640 ); 1641 } 1642 1643 /** 1644 * @dataProvider urlencodedStringPrefixData 1645 */ 1646 public function testUrlencodedStringPrefix($string, $prefix, $expect) 1647 { 1648 $request = new Request(); 1649 1650 $me = new \ReflectionMethod($request, 'getUrlencodedPrefix'); 1651 $me->setAccessible(true); 1652 1653 $this->assertSame($expect, $me->invoke($request, $string, $prefix)); 1654 } 1655 1656 public function urlencodedStringPrefixData() 1657 { 1658 return array( 1659 array('foo', 'foo', 'foo'), 1660 array('fo%6f', 'foo', 'fo%6f'), 1661 array('foo/bar', 'foo', 'foo'), 1662 array('fo%6f/bar', 'foo', 'fo%6f'), 1663 array('f%6f%6f/bar', 'foo', 'f%6f%6f'), 1664 array('%66%6F%6F/bar', 'foo', '%66%6F%6F'), 1665 array('fo+o/bar', 'fo+o', 'fo+o'), 1666 array('fo%2Bo/bar', 'fo+o', 'fo%2Bo'), 1667 ); 1668 } 1669 1670 private function disableHttpMethodParameterOverride() 1671 { 1672 $class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request'); 1673 $property = $class->getProperty('httpMethodParameterOverride'); 1674 $property->setAccessible(true); 1675 $property->setValue(false); 1676 } 1677 1678 private function getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies) 1679 { 1680 $request = new Request(); 1681 1682 $server = array('REMOTE_ADDR' => $remoteAddr); 1683 if (null !== $httpForwardedFor) { 1684 $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor; 1685 } 1686 1687 if ($trustedProxies) { 1688 Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL); 1689 } 1690 1691 $request->initialize(array(), array(), array(), array(), array(), $server); 1692 1693 return $request; 1694 } 1695 1696 private function getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies) 1697 { 1698 $request = new Request(); 1699 1700 $server = array('REMOTE_ADDR' => $remoteAddr); 1701 1702 if (null !== $httpForwarded) { 1703 $server['HTTP_FORWARDED'] = $httpForwarded; 1704 } 1705 1706 if ($trustedProxies) { 1707 Request::setTrustedProxies($trustedProxies, Request::HEADER_FORWARDED); 1708 } 1709 1710 $request->initialize(array(), array(), array(), array(), array(), $server); 1711 1712 return $request; 1713 } 1714 1715 public function testTrustedProxiesXForwardedFor() 1716 { 1717 $request = Request::create('http://example.com/'); 1718 $request->server->set('REMOTE_ADDR', '3.3.3.3'); 1719 $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2'); 1720 $request->headers->set('X_FORWARDED_HOST', 'foo.example.com:1234, real.example.com:8080'); 1721 $request->headers->set('X_FORWARDED_PROTO', 'https'); 1722 $request->headers->set('X_FORWARDED_PORT', 443); 1723 1724 // no trusted proxies 1725 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1726 $this->assertEquals('example.com', $request->getHost()); 1727 $this->assertEquals(80, $request->getPort()); 1728 $this->assertFalse($request->isSecure()); 1729 1730 // disabling proxy trusting 1731 Request::setTrustedProxies(array(), Request::HEADER_X_FORWARDED_ALL); 1732 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1733 $this->assertEquals('example.com', $request->getHost()); 1734 $this->assertEquals(80, $request->getPort()); 1735 $this->assertFalse($request->isSecure()); 1736 1737 // request is forwarded by a non-trusted proxy 1738 Request::setTrustedProxies(array('2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); 1739 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1740 $this->assertEquals('example.com', $request->getHost()); 1741 $this->assertEquals(80, $request->getPort()); 1742 $this->assertFalse($request->isSecure()); 1743 1744 // trusted proxy via setTrustedProxies() 1745 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); 1746 $this->assertEquals('1.1.1.1', $request->getClientIp()); 1747 $this->assertEquals('foo.example.com', $request->getHost()); 1748 $this->assertEquals(443, $request->getPort()); 1749 $this->assertTrue($request->isSecure()); 1750 1751 // trusted proxy via setTrustedProxies() 1752 Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); 1753 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1754 $this->assertEquals('example.com', $request->getHost()); 1755 $this->assertEquals(80, $request->getPort()); 1756 $this->assertFalse($request->isSecure()); 1757 1758 // check various X_FORWARDED_PROTO header values 1759 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); 1760 $request->headers->set('X_FORWARDED_PROTO', 'ssl'); 1761 $this->assertTrue($request->isSecure()); 1762 1763 $request->headers->set('X_FORWARDED_PROTO', 'https, http'); 1764 $this->assertTrue($request->isSecure()); 1765 } 1766 1767 /** 1768 * @group legacy 1769 * @expectedDeprecation The "Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. 1770 */ 1771 public function testLegacyTrustedProxies() 1772 { 1773 $request = Request::create('http://example.com/'); 1774 $request->server->set('REMOTE_ADDR', '3.3.3.3'); 1775 $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2'); 1776 $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080'); 1777 $request->headers->set('X_FORWARDED_PROTO', 'https'); 1778 $request->headers->set('X_FORWARDED_PORT', 443); 1779 $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4'); 1780 $request->headers->set('X_MY_HOST', 'my.example.com'); 1781 $request->headers->set('X_MY_PROTO', 'http'); 1782 $request->headers->set('X_MY_PORT', 81); 1783 1784 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); 1785 1786 // custom header names 1787 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_MY_FOR'); 1788 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_MY_HOST'); 1789 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_MY_PORT'); 1790 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_MY_PROTO'); 1791 $this->assertEquals('4.4.4.4', $request->getClientIp()); 1792 $this->assertEquals('my.example.com', $request->getHost()); 1793 $this->assertEquals(81, $request->getPort()); 1794 $this->assertFalse($request->isSecure()); 1795 1796 // disabling via empty header names 1797 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, null); 1798 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null); 1799 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, null); 1800 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, null); 1801 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1802 $this->assertEquals('example.com', $request->getHost()); 1803 $this->assertEquals(80, $request->getPort()); 1804 $this->assertFalse($request->isSecure()); 1805 1806 //reset 1807 Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED'); 1808 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR'); 1809 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST'); 1810 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT'); 1811 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); 1812 } 1813 1814 public function testTrustedProxiesForwarded() 1815 { 1816 $request = Request::create('http://example.com/'); 1817 $request->server->set('REMOTE_ADDR', '3.3.3.3'); 1818 $request->headers->set('FORWARDED', 'for=1.1.1.1, host=foo.example.com:8080, proto=https, for=2.2.2.2, host=real.example.com:8080'); 1819 1820 // no trusted proxies 1821 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1822 $this->assertEquals('example.com', $request->getHost()); 1823 $this->assertEquals(80, $request->getPort()); 1824 $this->assertFalse($request->isSecure()); 1825 1826 // disabling proxy trusting 1827 Request::setTrustedProxies(array(), Request::HEADER_FORWARDED); 1828 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1829 $this->assertEquals('example.com', $request->getHost()); 1830 $this->assertEquals(80, $request->getPort()); 1831 $this->assertFalse($request->isSecure()); 1832 1833 // request is forwarded by a non-trusted proxy 1834 Request::setTrustedProxies(array('2.2.2.2'), Request::HEADER_FORWARDED); 1835 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1836 $this->assertEquals('example.com', $request->getHost()); 1837 $this->assertEquals(80, $request->getPort()); 1838 $this->assertFalse($request->isSecure()); 1839 1840 // trusted proxy via setTrustedProxies() 1841 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_FORWARDED); 1842 $this->assertEquals('1.1.1.1', $request->getClientIp()); 1843 $this->assertEquals('foo.example.com', $request->getHost()); 1844 $this->assertEquals(8080, $request->getPort()); 1845 $this->assertTrue($request->isSecure()); 1846 1847 // trusted proxy via setTrustedProxies() 1848 Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'), Request::HEADER_FORWARDED); 1849 $this->assertEquals('3.3.3.3', $request->getClientIp()); 1850 $this->assertEquals('example.com', $request->getHost()); 1851 $this->assertEquals(80, $request->getPort()); 1852 $this->assertFalse($request->isSecure()); 1853 1854 // check various X_FORWARDED_PROTO header values 1855 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_FORWARDED); 1856 $request->headers->set('FORWARDED', 'proto=ssl'); 1857 $this->assertTrue($request->isSecure()); 1858 1859 $request->headers->set('FORWARDED', 'proto=https, proto=http'); 1860 $this->assertTrue($request->isSecure()); 1861 } 1862 1863 /** 1864 * @group legacy 1865 * @expectedException \InvalidArgumentException 1866 */ 1867 public function testSetTrustedProxiesInvalidHeaderName() 1868 { 1869 Request::create('http://example.com/'); 1870 Request::setTrustedHeaderName('bogus name', 'X_MY_FOR'); 1871 } 1872 1873 /** 1874 * @group legacy 1875 * @expectedException \InvalidArgumentException 1876 */ 1877 public function testGetTrustedProxiesInvalidHeaderName() 1878 { 1879 Request::create('http://example.com/'); 1880 Request::getTrustedHeaderName('bogus name'); 1881 } 1882 1883 /** 1884 * @dataProvider iisRequestUriProvider 1885 */ 1886 public function testIISRequestUri($headers, $server, $expectedRequestUri) 1887 { 1888 $request = new Request(); 1889 $request->headers->replace($headers); 1890 $request->server->replace($server); 1891 1892 $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct'); 1893 1894 $subRequestUri = '/bar/foo'; 1895 $subRequest = Request::create($subRequestUri, 'get', array(), array(), array(), $request->server->all()); 1896 $this->assertEquals($subRequestUri, $subRequest->getRequestUri(), '->getRequestUri() is correct in sub request'); 1897 } 1898 1899 public function iisRequestUriProvider() 1900 { 1901 return array( 1902 array( 1903 array( 1904 'X_ORIGINAL_URL' => '/foo/bar', 1905 ), 1906 array(), 1907 '/foo/bar', 1908 ), 1909 array( 1910 array( 1911 'X_REWRITE_URL' => '/foo/bar', 1912 ), 1913 array(), 1914 '/foo/bar', 1915 ), 1916 array( 1917 array(), 1918 array( 1919 'IIS_WasUrlRewritten' => '1', 1920 'UNENCODED_URL' => '/foo/bar', 1921 ), 1922 '/foo/bar', 1923 ), 1924 array( 1925 array( 1926 'X_ORIGINAL_URL' => '/foo/bar', 1927 ), 1928 array( 1929 'HTTP_X_ORIGINAL_URL' => '/foo/bar', 1930 ), 1931 '/foo/bar', 1932 ), 1933 array( 1934 array( 1935 'X_ORIGINAL_URL' => '/foo/bar', 1936 ), 1937 array( 1938 'IIS_WasUrlRewritten' => '1', 1939 'UNENCODED_URL' => '/foo/bar', 1940 ), 1941 '/foo/bar', 1942 ), 1943 array( 1944 array( 1945 'X_ORIGINAL_URL' => '/foo/bar', 1946 ), 1947 array( 1948 'HTTP_X_ORIGINAL_URL' => '/foo/bar', 1949 'IIS_WasUrlRewritten' => '1', 1950 'UNENCODED_URL' => '/foo/bar', 1951 ), 1952 '/foo/bar', 1953 ), 1954 array( 1955 array(), 1956 array( 1957 'ORIG_PATH_INFO' => '/foo/bar', 1958 ), 1959 '/foo/bar', 1960 ), 1961 array( 1962 array(), 1963 array( 1964 'ORIG_PATH_INFO' => '/foo/bar', 1965 'QUERY_STRING' => 'foo=bar', 1966 ), 1967 '/foo/bar?foo=bar', 1968 ), 1969 ); 1970 } 1971 1972 public function testTrustedHosts() 1973 { 1974 // create a request 1975 $request = Request::create('/'); 1976 1977 // no trusted host set -> no host check 1978 $request->headers->set('host', 'evil.com'); 1979 $this->assertEquals('evil.com', $request->getHost()); 1980 1981 // add a trusted domain and all its subdomains 1982 Request::setTrustedHosts(array('^([a-z]{9}\.)?trusted\.com$')); 1983 1984 // untrusted host 1985 $request->headers->set('host', 'evil.com'); 1986 try { 1987 $request->getHost(); 1988 $this->fail('Request::getHost() should throw an exception when host is not trusted.'); 1989 } catch (SuspiciousOperationException $e) { 1990 $this->assertEquals('Untrusted Host "evil.com".', $e->getMessage()); 1991 } 1992 1993 // trusted hosts 1994 $request->headers->set('host', 'trusted.com'); 1995 $this->assertEquals('trusted.com', $request->getHost()); 1996 $this->assertEquals(80, $request->getPort()); 1997 1998 $request->server->set('HTTPS', true); 1999 $request->headers->set('host', 'trusted.com'); 2000 $this->assertEquals('trusted.com', $request->getHost()); 2001 $this->assertEquals(443, $request->getPort()); 2002 $request->server->set('HTTPS', false); 2003 2004 $request->headers->set('host', 'trusted.com:8000'); 2005 $this->assertEquals('trusted.com', $request->getHost()); 2006 $this->assertEquals(8000, $request->getPort()); 2007 2008 $request->headers->set('host', 'subdomain.trusted.com'); 2009 $this->assertEquals('subdomain.trusted.com', $request->getHost()); 2010 2011 // reset request for following tests 2012 Request::setTrustedHosts(array()); 2013 } 2014 2015 public function testFactory() 2016 { 2017 Request::setFactory(function (array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { 2018 return new NewRequest(); 2019 }); 2020 2021 $this->assertEquals('foo', Request::create('/')->getFoo()); 2022 2023 Request::setFactory(null); 2024 } 2025 2026 /** 2027 * @dataProvider getLongHostNames 2028 */ 2029 public function testVeryLongHosts($host) 2030 { 2031 $start = microtime(true); 2032 2033 $request = Request::create('/'); 2034 $request->headers->set('host', $host); 2035 $this->assertEquals($host, $request->getHost()); 2036 $this->assertLessThan(5, microtime(true) - $start); 2037 } 2038 2039 /** 2040 * @dataProvider getHostValidities 2041 */ 2042 public function testHostValidity($host, $isValid, $expectedHost = null, $expectedPort = null) 2043 { 2044 $request = Request::create('/'); 2045 $request->headers->set('host', $host); 2046 2047 if ($isValid) { 2048 $this->assertSame($expectedHost ?: $host, $request->getHost()); 2049 if ($expectedPort) { 2050 $this->assertSame($expectedPort, $request->getPort()); 2051 } 2052 } else { 2053 if (method_exists($this, 'expectException')) { 2054 $this->expectException(SuspiciousOperationException::class); 2055 $this->expectExceptionMessage('Invalid Host'); 2056 } else { 2057 $this->setExpectedException(SuspiciousOperationException::class, 'Invalid Host'); 2058 } 2059 2060 $request->getHost(); 2061 } 2062 } 2063 2064 public function getHostValidities() 2065 { 2066 return array( 2067 array('.a', false), 2068 array('a..', false), 2069 array('a.', true), 2070 array("\xE9", false), 2071 array('[::1]', true), 2072 array('[::1]:80', true, '[::1]', 80), 2073 array(str_repeat('.', 101), false), 2074 ); 2075 } 2076 2077 public function getLongHostNames() 2078 { 2079 return array( 2080 array('a'.str_repeat('.a', 40000)), 2081 array(str_repeat(':', 101)), 2082 ); 2083 } 2084 2085 /** 2086 * @dataProvider methodIdempotentProvider 2087 */ 2088 public function testMethodIdempotent($method, $idempotent) 2089 { 2090 $request = new Request(); 2091 $request->setMethod($method); 2092 $this->assertEquals($idempotent, $request->isMethodIdempotent()); 2093 } 2094 2095 public function methodIdempotentProvider() 2096 { 2097 return array( 2098 array('HEAD', true), 2099 array('GET', true), 2100 array('POST', false), 2101 array('PUT', true), 2102 array('PATCH', false), 2103 array('DELETE', true), 2104 array('PURGE', true), 2105 array('OPTIONS', true), 2106 array('TRACE', true), 2107 array('CONNECT', false), 2108 ); 2109 } 2110 2111 /** 2112 * @dataProvider methodSafeProvider 2113 */ 2114 public function testMethodSafe($method, $safe) 2115 { 2116 $request = new Request(); 2117 $request->setMethod($method); 2118 $this->assertEquals($safe, $request->isMethodSafe(false)); 2119 } 2120 2121 public function methodSafeProvider() 2122 { 2123 return array( 2124 array('HEAD', true), 2125 array('GET', true), 2126 array('POST', false), 2127 array('PUT', false), 2128 array('PATCH', false), 2129 array('DELETE', false), 2130 array('PURGE', false), 2131 array('OPTIONS', true), 2132 array('TRACE', true), 2133 array('CONNECT', false), 2134 ); 2135 } 2136 2137 /** 2138 * @group legacy 2139 * @expectedDeprecation Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since Symfony 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead. 2140 */ 2141 public function testMethodSafeChecksCacheable() 2142 { 2143 $request = new Request(); 2144 $request->setMethod('OPTIONS'); 2145 $this->assertFalse($request->isMethodSafe()); 2146 } 2147 2148 /** 2149 * @dataProvider methodCacheableProvider 2150 */ 2151 public function testMethodCacheable($method, $chacheable) 2152 { 2153 $request = new Request(); 2154 $request->setMethod($method); 2155 $this->assertEquals($chacheable, $request->isMethodCacheable()); 2156 } 2157 2158 public function methodCacheableProvider() 2159 { 2160 return array( 2161 array('HEAD', true), 2162 array('GET', true), 2163 array('POST', false), 2164 array('PUT', false), 2165 array('PATCH', false), 2166 array('DELETE', false), 2167 array('PURGE', false), 2168 array('OPTIONS', false), 2169 array('TRACE', false), 2170 array('CONNECT', false), 2171 ); 2172 } 2173 2174 /** 2175 * @group legacy 2176 */ 2177 public function testGetTrustedHeaderName() 2178 { 2179 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL); 2180 2181 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); 2182 $this->assertSame('X_FORWARDED_FOR', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); 2183 $this->assertSame('X_FORWARDED_HOST', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); 2184 $this->assertSame('X_FORWARDED_PORT', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); 2185 $this->assertSame('X_FORWARDED_PROTO', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); 2186 2187 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); 2188 2189 $this->assertSame('FORWARDED', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); 2190 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); 2191 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); 2192 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); 2193 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); 2194 2195 Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'A'); 2196 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, ''); 2197 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'C'); 2198 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'D'); 2199 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'E'); 2200 2201 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); 2202 2203 $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); 2204 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); 2205 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); 2206 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); 2207 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); 2208 2209 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL); 2210 2211 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); 2212 $this->assertSame('', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); 2213 $this->assertSame('C', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); 2214 $this->assertSame('D', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); 2215 $this->assertSame('E', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); 2216 2217 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); 2218 2219 $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); 2220 2221 //reset 2222 Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED'); 2223 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR'); 2224 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST'); 2225 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT'); 2226 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); 2227 } 2228 2229 /** 2230 * @dataProvider protocolVersionProvider 2231 */ 2232 public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expected) 2233 { 2234 if ($trustedProxy) { 2235 Request::setTrustedProxies(array('1.1.1.1'), -1); 2236 } 2237 2238 $request = new Request(); 2239 $request->server->set('SERVER_PROTOCOL', $serverProtocol); 2240 $request->server->set('REMOTE_ADDR', '1.1.1.1'); 2241 $request->headers->set('Via', $via); 2242 2243 $this->assertSame($expected, $request->getProtocolVersion()); 2244 } 2245 2246 public function protocolVersionProvider() 2247 { 2248 return array( 2249 'untrusted without via' => array('HTTP/2.0', false, '', 'HTTP/2.0'), 2250 'untrusted with via' => array('HTTP/2.0', false, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/2.0'), 2251 'trusted without via' => array('HTTP/2.0', true, '', 'HTTP/2.0'), 2252 'trusted with via' => array('HTTP/2.0', true, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'), 2253 'trusted with via and protocol name' => array('HTTP/2.0', true, 'HTTP/1.0 fred, HTTP/1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'), 2254 'trusted with broken via' => array('HTTP/2.0', true, 'HTTP/1^0 foo', 'HTTP/2.0'), 2255 'trusted with partially-broken via' => array('HTTP/2.0', true, '1.0 fred, foo', 'HTTP/1.0'), 2256 ); 2257 } 2258 2259 public function nonstandardRequestsData() 2260 { 2261 return array( 2262 array('', '', '/', 'http://host:8080/', ''), 2263 array('/', '', '/', 'http://host:8080/', ''), 2264 2265 array('hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'), 2266 array('/hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'), 2267 2268 array('', 'a=b', '/', 'http://host:8080/?a=b'), 2269 array('?a=b', 'a=b', '/', 'http://host:8080/?a=b'), 2270 array('/?a=b', 'a=b', '/', 'http://host:8080/?a=b'), 2271 2272 array('x', 'a=b', '/x', 'http://host:8080/x?a=b'), 2273 array('x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'), 2274 array('/x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'), 2275 2276 array('hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'), 2277 array('/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'), 2278 2279 array('hello/app.php/x', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), 2280 array('hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), 2281 array('/hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), 2282 ); 2283 } 2284 2285 /** 2286 * @dataProvider nonstandardRequestsData 2287 */ 2288 public function testNonstandardRequests($requestUri, $queryString, $expectedPathInfo, $expectedUri, $expectedBasePath = '', $expectedBaseUrl = null) 2289 { 2290 if (null === $expectedBaseUrl) { 2291 $expectedBaseUrl = $expectedBasePath; 2292 } 2293 2294 $server = array( 2295 'HTTP_HOST' => 'host:8080', 2296 'SERVER_PORT' => '8080', 2297 'QUERY_STRING' => $queryString, 2298 'PHP_SELF' => '/hello/app.php', 2299 'SCRIPT_FILENAME' => '/some/path/app.php', 2300 'REQUEST_URI' => $requestUri, 2301 ); 2302 2303 $request = new Request(array(), array(), array(), array(), array(), $server); 2304 2305 $this->assertEquals($expectedPathInfo, $request->getPathInfo()); 2306 $this->assertEquals($expectedUri, $request->getUri()); 2307 $this->assertEquals($queryString, $request->getQueryString()); 2308 $this->assertEquals(8080, $request->getPort()); 2309 $this->assertEquals('host:8080', $request->getHttpHost()); 2310 $this->assertEquals($expectedBaseUrl, $request->getBaseUrl()); 2311 $this->assertEquals($expectedBasePath, $request->getBasePath()); 2312 } 2313} 2314 2315class RequestContentProxy extends Request 2316{ 2317 public function getContent($asResource = false) 2318 { 2319 return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent')); 2320 } 2321} 2322 2323class NewRequest extends Request 2324{ 2325 public function getFoo() 2326 { 2327 return 'foo'; 2328 } 2329} 2330