4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\HttpFoundation\Tests;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
16 use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
17 use Symfony\Component\HttpFoundation\Session\Session;
18 use Symfony\Component\HttpFoundation\Request;
20 class RequestTest extends TestCase
22 protected function tearDown()
25 Request::setTrustedProxies(array(), -1);
28 public function testInitialize()
30 $request = new Request();
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');
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');
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');
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');
45 public function testGetLocale()
47 $request = new Request();
48 $request->setLocale('pl');
49 $locale = $request->getLocale();
50 $this->assertEquals('pl', $locale);
53 public function testGetUser()
55 $request = Request::create('http://user:password@test.com');
56 $user = $request->getUser();
58 $this->assertEquals('user', $user);
61 public function testGetPassword()
63 $request = Request::create('http://user:password@test.com');
64 $password = $request->getPassword();
66 $this->assertEquals('password', $password);
69 public function testIsNoCache()
71 $request = new Request();
72 $isNoCache = $request->isNoCache();
74 $this->assertFalse($isNoCache);
77 public function testGetContentType()
79 $request = new Request();
80 $contentType = $request->getContentType();
82 $this->assertNull($contentType);
85 public function testSetDefaultLocale()
87 $request = new Request();
88 $request->setDefaultLocale('pl');
89 $locale = $request->getLocale();
91 $this->assertEquals('pl', $locale);
94 public function testCreate()
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
217 $request = Request::create('http://test.com/?foo');
218 $this->assertEquals('/?foo', $request->getRequestUri());
219 $this->assertEquals(array('foo' => ''), $request->query->all());
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(),
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',
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());
237 public function testCreateCheckPrecedence()
239 // server is used by default
240 $request = Request::create('/', 'DELETE', array(), array(), array(), array(
241 'HTTP_HOST' => 'example.com',
243 'SERVER_PORT' => 443,
244 'PHP_AUTH_USER' => 'fabien',
245 'PHP_AUTH_PW' => 'pa$$',
246 'QUERY_STRING' => 'foo=bar',
247 'CONTENT_TYPE' => 'application/json',
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'));
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',
261 'SERVER_PORT' => 443,
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());
271 public function testDuplicate()
273 $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar'));
274 $dup = $request->duplicate();
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');
281 $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar'));
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');
289 public function testDuplicateWithFormat()
291 $request = new Request(array(), array(), array('_format' => 'json'));
292 $dup = $request->duplicate();
294 $this->assertEquals('json', $dup->getRequestFormat());
295 $this->assertEquals('json', $dup->attributes->get('_format'));
297 $request = new Request();
298 $request->setRequestFormat('xml');
299 $dup = $request->duplicate();
301 $this->assertEquals('xml', $dup->getRequestFormat());
305 * @dataProvider getFormatToMimeTypeMapProviderWithAdditionalNullFormat
307 public function testGetFormatFromMimeType($format, $mimeTypes)
309 $request = new Request();
310 foreach ($mimeTypes as $mime) {
311 $this->assertEquals($format, $request->getFormat($mime));
313 $request->setFormat($format, $mimeTypes);
314 foreach ($mimeTypes as $mime) {
315 $this->assertEquals($format, $request->getFormat($mime));
317 if (null !== $format) {
318 $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
323 public function getFormatToMimeTypeMapProviderWithAdditionalNullFormat()
326 array(array(null, array(null, 'unexistent-mime-type'))),
327 $this->getFormatToMimeTypeMapProvider()
331 public function testGetFormatFromMimeTypeWithParameters()
333 $request = new Request();
334 $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8'));
338 * @dataProvider getFormatToMimeTypeMapProvider
340 public function testGetMimeTypeFromFormat($format, $mimeTypes)
342 $request = new Request();
343 $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
347 * @dataProvider getFormatToMimeTypeMapProvider
349 public function testGetMimeTypesFromFormat($format, $mimeTypes)
351 $this->assertEquals($mimeTypes, Request::getMimeTypes($format));
354 public function testGetMimeTypesFromInexistentFormat()
356 $request = new Request();
357 $this->assertNull($request->getMimeType('foo'));
358 $this->assertEquals(array(), Request::getMimeTypes('foo'));
361 public function testGetFormatWithCustomMimeType()
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'));
368 public function getFormatToMimeTypeMapProvider()
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')),
382 public function testGetUri()
386 // Standard Request on non default PORT
387 // http://host:8080/index.php/path/info?query=string
389 $server['HTTP_HOST'] = 'host:8080';
390 $server['SERVER_NAME'] = 'servername';
391 $server['SERVER_PORT'] = '8080';
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';
401 $request = new Request();
403 $request->initialize(array(), array(), array(), array(), array(), $server);
405 $this->assertEquals('http://host:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port');
407 // Use std port number
408 $server['HTTP_HOST'] = 'host';
409 $server['SERVER_NAME'] = 'servername';
410 $server['SERVER_PORT'] = '80';
412 $request->initialize(array(), array(), array(), array(), array(), $server);
414 $this->assertEquals('http://host/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port');
416 // Without HOST HEADER
417 unset($server['HTTP_HOST']);
418 $server['SERVER_NAME'] = 'servername';
419 $server['SERVER_PORT'] = '80';
421 $request->initialize(array(), array(), array(), array(), array(), $server);
423 $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER');
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
430 $server['HTTP_HOST'] = 'host:8080';
431 $server['SERVER_NAME'] = 'servername';
432 $server['SERVER_PORT'] = '8080';
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';
443 $request->initialize(array(), array(), array(), array(), array(), $server);
444 $this->assertEquals('http://host:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite');
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';
452 $request->initialize(array(), array(), array(), array(), array(), $server);
454 $this->assertEquals('http://host/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port');
456 // Without HOST HEADER
457 unset($server['HTTP_HOST']);
458 $server['SERVER_NAME'] = 'servername';
459 $server['SERVER_PORT'] = '80';
461 $request->initialize(array(), array(), array(), array(), array(), $server);
463 $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER');
465 // With encoded characters
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',
479 $request->initialize(array(), array(), array(), array(), array(), $server);
482 'http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string',
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());
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());
497 public function testGetUriForPath()
499 $request = Request::create('http://test.com/foo?bar=baz');
500 $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path'));
502 $request = Request::create('http://test.com:90/foo?bar=baz');
503 $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path'));
505 $request = Request::create('https://test.com/foo?bar=baz');
506 $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path'));
508 $request = Request::create('https://test.com:90/foo?bar=baz');
509 $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path'));
513 // Standard Request on non default PORT
514 // http://host:8080/index.php/path/info?query=string
516 $server['HTTP_HOST'] = 'host:8080';
517 $server['SERVER_NAME'] = 'servername';
518 $server['SERVER_PORT'] = '8080';
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';
528 $request = new Request();
530 $request->initialize(array(), array(), array(), array(), array(), $server);
532 $this->assertEquals('http://host:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port');
534 // Use std port number
535 $server['HTTP_HOST'] = 'host';
536 $server['SERVER_NAME'] = 'servername';
537 $server['SERVER_PORT'] = '80';
539 $request->initialize(array(), array(), array(), array(), array(), $server);
541 $this->assertEquals('http://host/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port');
543 // Without HOST HEADER
544 unset($server['HTTP_HOST']);
545 $server['SERVER_NAME'] = 'servername';
546 $server['SERVER_PORT'] = '80';
548 $request->initialize(array(), array(), array(), array(), array(), $server);
550 $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER');
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
557 $server['HTTP_HOST'] = 'host:8080';
558 $server['SERVER_NAME'] = 'servername';
559 $server['SERVER_PORT'] = '8080';
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';
570 $request->initialize(array(), array(), array(), array(), array(), $server);
571 $this->assertEquals('http://host:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite');
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';
579 $request->initialize(array(), array(), array(), array(), array(), $server);
581 $this->assertEquals('http://host/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port');
583 // Without HOST HEADER
584 unset($server['HTTP_HOST']);
585 $server['SERVER_NAME'] = 'servername';
586 $server['SERVER_PORT'] = '80';
588 $request->initialize(array(), array(), array(), array(), array(), $server);
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());
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'));
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'));
605 * @dataProvider getRelativeUriForPathData()
607 public function testGetRelativeUriForPath($expected, $pathinfo, $path)
609 $this->assertEquals($expected, Request::create($pathinfo)->getRelativeUriForPath($path));
612 public function getRelativeUriForPathData()
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'),
624 public function testGetUserInfo()
626 $request = new Request();
628 $server = array('PHP_AUTH_USER' => 'fabien');
629 $request->initialize(array(), array(), array(), array(), array(), $server);
630 $this->assertEquals('fabien', $request->getUserInfo());
632 $server['PHP_AUTH_USER'] = '0';
633 $request->initialize(array(), array(), array(), array(), array(), $server);
634 $this->assertEquals('0', $request->getUserInfo());
636 $server['PHP_AUTH_PW'] = '0';
637 $request->initialize(array(), array(), array(), array(), array(), $server);
638 $this->assertEquals('0:0', $request->getUserInfo());
641 public function testGetSchemeAndHttpHost()
643 $request = new Request();
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());
651 $server['PHP_AUTH_USER'] = 'fabien';
652 $request->initialize(array(), array(), array(), array(), array(), $server);
653 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
655 $server['PHP_AUTH_USER'] = '0';
656 $request->initialize(array(), array(), array(), array(), array(), $server);
657 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
659 $server['PHP_AUTH_PW'] = '0';
660 $request->initialize(array(), array(), array(), array(), array(), $server);
661 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
665 * @dataProvider getQueryStringNormalizationData
667 public function testGetQueryString($query, $expectedQuery, $msg)
669 $request = new Request();
671 $request->server->set('QUERY_STRING', $query);
672 $this->assertSame($expectedQuery, $request->getQueryString(), $msg);
675 public function getQueryStringNormalizationData()
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'),
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 "+"'),
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'),
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'),
702 public function testGetQueryStringReturnsNull()
704 $request = new Request();
706 $this->assertNull($request->getQueryString(), '->getQueryString() returns null for non-existent query string');
708 $request->server->set('QUERY_STRING', '');
709 $this->assertNull($request->getQueryString(), '->getQueryString() returns null for empty query string');
712 public function testGetHost()
714 $request = new Request();
716 $request->initialize(array('foo' => 'bar'));
717 $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized');
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');
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');
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');
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 ');
734 public function testGetPort()
736 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
737 'HTTP_X_FORWARDED_PROTO' => 'https',
738 'HTTP_X_FORWARDED_PORT' => '443',
740 $port = $request->getPort();
742 $this->assertEquals(80, $port, 'Without trusted proxies FORWARDED_PROTO and FORWARDED_PORT are ignored.');
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',
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.');
753 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
754 'HTTP_X_FORWARDED_PROTO' => 'https',
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.');
760 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
761 'HTTP_X_FORWARDED_PROTO' => 'http',
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.');
767 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
768 'HTTP_X_FORWARDED_PROTO' => 'On',
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.');
774 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
775 'HTTP_X_FORWARDED_PROTO' => '1',
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.');
781 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
782 'HTTP_X_FORWARDED_PROTO' => 'something-else',
784 $port = $request->getPort();
785 $this->assertEquals(80, $port, 'With only PROTO set and value is not recognized, getPort() defaults to 80.');
789 * @expectedException \RuntimeException
791 public function testGetHostWithFakeHttpHostValue()
793 $request = new Request();
794 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.host.com?query=string'));
798 public function testGetSetMethod()
800 $request = new Request();
802 $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined');
804 $request->setMethod('get');
805 $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string');
807 $request->setMethod('PURGE');
808 $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one');
810 $request->setMethod('POST');
811 $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined');
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');
817 $request = new Request();
818 $request->setMethod('POST');
819 $request->request->set('_method', 'purge');
821 $this->assertFalse(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be disabled by default');
823 Request::enableHttpMethodParameterOverride();
825 $this->assertTrue(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be enabled now but it is not');
827 $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
828 $this->disableHttpMethodParameterOverride();
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');
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();
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');
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');
854 * @dataProvider getClientIpsProvider
856 public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
858 $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);
860 $this->assertEquals($expected[0], $request->getClientIp());
864 * @dataProvider getClientIpsProvider
866 public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
868 $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);
870 $this->assertEquals($expected, $request->getClientIps());
874 * @dataProvider getClientIpsForwardedProvider
876 public function testGetClientIpsForwarded($expected, $remoteAddr, $httpForwarded, $trustedProxies)
878 $request = $this->getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies);
880 $this->assertEquals($expected, $request->getClientIps());
883 public function getClientIpsForwardedProvider()
885 // $expected $remoteAddr $httpForwarded $trustedProxies
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')),
896 public function getClientIpsProvider()
898 // $expected $remoteAddr $httpForwardedFor $trustedProxies
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')),
906 array(array('::1'), '::1', null, null),
907 // trust the IPv6 remote addr
908 array(array('::1'), '::1', null, array('::1')),
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')),
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')),
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')),
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')),
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')),
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')),
952 * @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException
953 * @dataProvider getClientIpsWithConflictingHeadersProvider
955 public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXForwardedFor)
957 $request = new Request();
960 'REMOTE_ADDR' => '88.88.88.88',
961 'HTTP_FORWARDED' => $httpForwarded,
962 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
965 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL | Request::HEADER_FORWARDED);
967 $request->initialize(array(), array(), array(), array(), array(), $server);
969 $request->getClientIps();
973 * @dataProvider getClientIpsWithConflictingHeadersProvider
975 public function testGetClientIpsOnlyXHttpForwardedForTrusted($httpForwarded, $httpXForwardedFor)
977 $request = new Request();
980 'REMOTE_ADDR' => '88.88.88.88',
981 'HTTP_FORWARDED' => $httpForwarded,
982 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
985 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_FOR);
987 $request->initialize(array(), array(), array(), array(), array(), $server);
989 $this->assertSame(array_reverse(explode(',', $httpXForwardedFor)), $request->getClientIps());
992 public function getClientIpsWithConflictingHeadersProvider()
994 // $httpForwarded $httpXForwardedFor
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'),
1005 * @dataProvider getClientIpsWithAgreeingHeadersProvider
1007 public function testGetClientIpsWithAgreeingHeaders($httpForwarded, $httpXForwardedFor, $expectedIps)
1009 $request = new Request();
1012 'REMOTE_ADDR' => '88.88.88.88',
1013 'HTTP_FORWARDED' => $httpForwarded,
1014 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
1017 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL);
1019 $request->initialize(array(), array(), array(), array(), array(), $server);
1021 $clientIps = $request->getClientIps();
1023 $this->assertSame($expectedIps, $clientIps);
1026 public function getClientIpsWithAgreeingHeadersProvider()
1028 // $httpForwarded $httpXForwardedFor
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')),
1039 public function testGetContentWorksTwiceInDefaultMode()
1041 $req = new Request();
1042 $this->assertEquals('', $req->getContent());
1043 $this->assertEquals('', $req->getContent());
1046 public function testGetContentReturnsResource()
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));
1055 public function testGetContentReturnsResourceWhenContentSetInConstructor()
1057 $req = new Request(array(), array(), array(), array(), array(), array(), 'MyContent');
1058 $resource = $req->getContent(true);
1060 $this->assertInternalType('resource', $resource);
1061 $this->assertEquals('MyContent', stream_get_contents($resource));
1064 public function testContentAsResource()
1066 $resource = fopen('php://memory', 'r+');
1067 fwrite($resource, 'My other content');
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());
1076 * @expectedException \LogicException
1077 * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider
1079 public function testGetContentCantBeCalledTwiceWithResources($first, $second)
1081 if (\PHP_VERSION_ID >= 50600) {
1082 $this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.');
1085 $req = new Request();
1086 $req->getContent($first);
1087 $req->getContent($second);
1090 public function getContentCantBeCalledTwiceWithResourcesProvider()
1093 'Resource then fetch' => array(true, false),
1094 'Resource then resource' => array(true, true),
1099 * @dataProvider getContentCanBeCalledTwiceWithResourcesProvider
1102 public function testGetContentCanBeCalledTwiceWithResources($first, $second)
1104 $req = new Request();
1105 $a = $req->getContent($first);
1106 $b = $req->getContent($second);
1109 $a = stream_get_contents($a);
1113 $b = stream_get_contents($b);
1116 $this->assertSame($a, $b);
1119 public function getContentCanBeCalledTwiceWithResourcesProvider()
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),
1129 public function provideOverloadedMethods()
1142 * @dataProvider provideOverloadedMethods
1144 public function testCreateFromGlobals($method)
1146 $normalizedMethod = strtoupper($method);
1148 $_GET['foo1'] = 'bar1';
1149 $_POST['foo2'] = 'bar2';
1150 $_COOKIE['foo3'] = 'bar3';
1151 $_FILES['foo4'] = array('bar4');
1152 $_SERVER['foo5'] = 'bar5';
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');
1161 unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']);
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'));
1169 unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']);
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'));
1181 unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']);
1182 $this->disableHttpMethodParameterOverride();
1185 public function testOverrideGlobals()
1187 $request = new Request();
1188 $request->initialize(array('foo' => 'bar'));
1190 // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it
1193 $request->overrideGlobals();
1195 $this->assertEquals(array('foo' => 'bar'), $_GET);
1197 $request->initialize(array(), array('foo' => 'bar'));
1198 $request->overrideGlobals();
1200 $this->assertEquals(array('foo' => 'bar'), $_POST);
1202 $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);
1204 $request->headers->set('X_FORWARDED_PROTO', 'https');
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());
1211 $request->overrideGlobals();
1213 $this->assertArrayHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);
1215 $request->headers->set('CONTENT_TYPE', 'multipart/form-data');
1216 $request->headers->set('CONTENT_LENGTH', 12345);
1218 $request->overrideGlobals();
1220 $this->assertArrayHasKey('CONTENT_TYPE', $_SERVER);
1221 $this->assertArrayHasKey('CONTENT_LENGTH', $_SERVER);
1223 $request->initialize(array('foo' => 'bar', 'baz' => 'foo'));
1224 $request->query->remove('baz');
1226 $request->overrideGlobals();
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'));
1232 // restore initial $_SERVER array
1236 public function testGetScriptName()
1238 $request = new Request();
1239 $this->assertEquals('', $request->getScriptName());
1242 $server['SCRIPT_NAME'] = '/index.php';
1244 $request->initialize(array(), array(), array(), array(), array(), $server);
1246 $this->assertEquals('/index.php', $request->getScriptName());
1249 $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
1250 $request->initialize(array(), array(), array(), array(), array(), $server);
1252 $this->assertEquals('/frontend.php', $request->getScriptName());
1255 $server['SCRIPT_NAME'] = '/index.php';
1256 $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
1257 $request->initialize(array(), array(), array(), array(), array(), $server);
1259 $this->assertEquals('/index.php', $request->getScriptName());
1262 public function testGetBasePath()
1264 $request = new Request();
1265 $this->assertEquals('', $request->getBasePath());
1268 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
1269 $request->initialize(array(), array(), array(), array(), array(), $server);
1270 $this->assertEquals('', $request->getBasePath());
1273 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
1274 $server['SCRIPT_NAME'] = '/index.php';
1275 $request->initialize(array(), array(), array(), array(), array(), $server);
1277 $this->assertEquals('', $request->getBasePath());
1280 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
1281 $server['PHP_SELF'] = '/index.php';
1282 $request->initialize(array(), array(), array(), array(), array(), $server);
1284 $this->assertEquals('', $request->getBasePath());
1287 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
1288 $server['ORIG_SCRIPT_NAME'] = '/index.php';
1289 $request->initialize(array(), array(), array(), array(), array(), $server);
1291 $this->assertEquals('', $request->getBasePath());
1294 public function testGetPathInfo()
1296 $request = new Request();
1297 $this->assertEquals('/', $request->getPathInfo());
1300 $server['REQUEST_URI'] = '/path/info';
1301 $request->initialize(array(), array(), array(), array(), array(), $server);
1303 $this->assertEquals('/path/info', $request->getPathInfo());
1306 $server['REQUEST_URI'] = '/path%20test/info';
1307 $request->initialize(array(), array(), array(), array(), array(), $server);
1309 $this->assertEquals('/path%20test/info', $request->getPathInfo());
1312 $server['REQUEST_URI'] = '?a=b';
1313 $request->initialize(array(), array(), array(), array(), array(), $server);
1315 $this->assertEquals('/', $request->getPathInfo());
1318 public function testGetParameterPrecedence()
1320 $request = new Request();
1321 $request->attributes->set('foo', 'attr');
1322 $request->query->set('foo', 'query');
1323 $request->request->set('foo', 'body');
1325 $this->assertSame('attr', $request->get('foo'));
1327 $request->attributes->remove('foo');
1328 $this->assertSame('query', $request->get('foo'));
1330 $request->query->remove('foo');
1331 $this->assertSame('body', $request->get('foo'));
1333 $request->request->remove('foo');
1334 $this->assertNull($request->get('foo'));
1337 public function testGetPreferredLanguage()
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')));
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')));
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')));
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')));
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')));
1364 public function testIsXmlHttpRequest()
1366 $request = new Request();
1367 $this->assertFalse($request->isXmlHttpRequest());
1369 $request->headers->set('X-Requested-With', 'XMLHttpRequest');
1370 $this->assertTrue($request->isXmlHttpRequest());
1372 $request->headers->remove('X-Requested-With');
1373 $this->assertFalse($request->isXmlHttpRequest());
1377 * @requires extension intl
1379 public function testIntlLocale()
1381 $request = new Request();
1383 $request->setDefaultLocale('fr');
1384 $this->assertEquals('fr', $request->getLocale());
1385 $this->assertEquals('fr', \Locale::getDefault());
1387 $request->setLocale('en');
1388 $this->assertEquals('en', $request->getLocale());
1389 $this->assertEquals('en', \Locale::getDefault());
1391 $request->setDefaultLocale('de');
1392 $this->assertEquals('en', $request->getLocale());
1393 $this->assertEquals('en', \Locale::getDefault());
1396 public function testGetCharsets()
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
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());
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());
1412 public function testGetEncodings()
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
1419 $request = new Request();
1420 $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch');
1421 $this->assertEquals(array('gzip', 'deflate', 'sdch'), $request->getEncodings());
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());
1428 public function testGetAcceptableContentTypes()
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
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());
1440 public function testGetLanguages()
1442 $request = new Request();
1443 $this->assertEquals(array(), $request->getLanguages());
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());
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
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
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
1462 $request = new Request();
1463 $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6');
1464 $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages());
1467 public function testGetRequestFormat()
1469 $request = new Request();
1470 $this->assertEquals('html', $request->getRequestFormat());
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'));
1477 $request = new Request();
1478 $this->assertNull($request->getRequestFormat(null));
1480 $request = new Request();
1481 $this->assertNull($request->setRequestFormat('foo'));
1482 $this->assertEquals('foo', $request->getRequestFormat(null));
1484 $request = new Request(array('_format' => 'foo'));
1485 $this->assertEquals('html', $request->getRequestFormat());
1488 public function testHasSession()
1490 $request = new Request();
1492 $this->assertFalse($request->hasSession());
1493 $request->setSession(new Session(new MockArraySessionStorage()));
1494 $this->assertTrue($request->hasSession());
1497 public function testGetSession()
1499 $request = new Request();
1501 $request->setSession(new Session(new MockArraySessionStorage()));
1502 $this->assertTrue($request->hasSession());
1504 $session = $request->getSession();
1505 $this->assertObjectHasAttribute('storage', $session);
1506 $this->assertObjectHasAttribute('flashName', $session);
1507 $this->assertObjectHasAttribute('attributeName', $session);
1510 public function testHasPreviousSession()
1512 $request = new Request();
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());
1521 public function testToString()
1523 $request = new Request();
1525 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
1526 $request->cookies->set('Foo', 'Bar');
1528 $asString = (string) $request;
1530 $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString);
1531 $this->assertContains('Cookie: Foo=Bar', $asString);
1533 $request->cookies->set('Another', 'Cookie');
1535 $asString = (string) $request;
1537 $this->assertContains('Cookie: Foo=Bar; Another=Cookie', $asString);
1540 public function testIsMethod()
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'));
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'));
1557 * @dataProvider getBaseUrlData
1559 public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo)
1561 $request = Request::create($uri, 'GET', array(), array(), array(), $server);
1563 $this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl');
1564 $this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo');
1567 public function getBaseUrlData()
1571 '/fruit/strawberry/1234index.php/blah',
1573 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/fruit/index.php',
1574 'SCRIPT_NAME' => '/fruit/index.php',
1575 'PHP_SELF' => '/fruit/index.php',
1578 '/strawberry/1234index.php/blah',
1581 '/fruit/strawberry/1234index.php/blah',
1583 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/index.php',
1584 'SCRIPT_NAME' => '/index.php',
1585 'PHP_SELF' => '/index.php',
1588 '/fruit/strawberry/1234index.php/blah',
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',
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',
1611 '/foo%20bar/app.php/home',
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',
1617 '/foo%20bar/app.php',
1621 '/foo%20bar/app.php/home%3Dbaz',
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',
1627 '/foo%20bar/app.php',
1633 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php',
1634 'SCRIPT_NAME' => '/foo/app.php',
1635 'PHP_SELF' => '/foo/app.php',
1644 * @dataProvider urlencodedStringPrefixData
1646 public function testUrlencodedStringPrefix($string, $prefix, $expect)
1648 $request = new Request();
1650 $me = new \ReflectionMethod($request, 'getUrlencodedPrefix');
1651 $me->setAccessible(true);
1653 $this->assertSame($expect, $me->invoke($request, $string, $prefix));
1656 public function urlencodedStringPrefixData()
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'),
1670 private function disableHttpMethodParameterOverride()
1672 $class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request');
1673 $property = $class->getProperty('httpMethodParameterOverride');
1674 $property->setAccessible(true);
1675 $property->setValue(false);
1678 private function getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies)
1680 $request = new Request();
1682 $server = array('REMOTE_ADDR' => $remoteAddr);
1683 if (null !== $httpForwardedFor) {
1684 $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor;
1687 if ($trustedProxies) {
1688 Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL);
1691 $request->initialize(array(), array(), array(), array(), array(), $server);
1696 private function getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies)
1698 $request = new Request();
1700 $server = array('REMOTE_ADDR' => $remoteAddr);
1702 if (null !== $httpForwarded) {
1703 $server['HTTP_FORWARDED'] = $httpForwarded;
1706 if ($trustedProxies) {
1707 Request::setTrustedProxies($trustedProxies, Request::HEADER_FORWARDED);
1710 $request->initialize(array(), array(), array(), array(), array(), $server);
1715 public function testTrustedProxiesXForwardedFor()
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);
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());
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());
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());
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());
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());
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());
1763 $request->headers->set('X_FORWARDED_PROTO', 'https, http');
1764 $this->assertTrue($request->isSecure());
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.
1771 public function testLegacyTrustedProxies()
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);
1784 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
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());
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());
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');
1814 public function testTrustedProxiesForwarded()
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');
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());
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());
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());
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());
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());
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());
1859 $request->headers->set('FORWARDED', 'proto=https, proto=http');
1860 $this->assertTrue($request->isSecure());
1865 * @expectedException \InvalidArgumentException
1867 public function testSetTrustedProxiesInvalidHeaderName()
1869 Request::create('http://example.com/');
1870 Request::setTrustedHeaderName('bogus name', 'X_MY_FOR');
1875 * @expectedException \InvalidArgumentException
1877 public function testGetTrustedProxiesInvalidHeaderName()
1879 Request::create('http://example.com/');
1880 Request::getTrustedHeaderName('bogus name');
1884 * @dataProvider iisRequestUriProvider
1886 public function testIISRequestUri($headers, $server, $expectedRequestUri)
1888 $request = new Request();
1889 $request->headers->replace($headers);
1890 $request->server->replace($server);
1892 $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct');
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');
1899 public function iisRequestUriProvider()
1904 'X_ORIGINAL_URL' => '/foo/bar',
1911 'X_REWRITE_URL' => '/foo/bar',
1919 'IIS_WasUrlRewritten' => '1',
1920 'UNENCODED_URL' => '/foo/bar',
1926 'X_ORIGINAL_URL' => '/foo/bar',
1929 'HTTP_X_ORIGINAL_URL' => '/foo/bar',
1935 'X_ORIGINAL_URL' => '/foo/bar',
1938 'IIS_WasUrlRewritten' => '1',
1939 'UNENCODED_URL' => '/foo/bar',
1945 'X_ORIGINAL_URL' => '/foo/bar',
1948 'HTTP_X_ORIGINAL_URL' => '/foo/bar',
1949 'IIS_WasUrlRewritten' => '1',
1950 'UNENCODED_URL' => '/foo/bar',
1957 'ORIG_PATH_INFO' => '/foo/bar',
1964 'ORIG_PATH_INFO' => '/foo/bar',
1965 'QUERY_STRING' => 'foo=bar',
1972 public function testTrustedHosts()
1975 $request = Request::create('/');
1977 // no trusted host set -> no host check
1978 $request->headers->set('host', 'evil.com');
1979 $this->assertEquals('evil.com', $request->getHost());
1981 // add a trusted domain and all its subdomains
1982 Request::setTrustedHosts(array('^([a-z]{9}\.)?trusted\.com$'));
1985 $request->headers->set('host', 'evil.com');
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());
1994 $request->headers->set('host', 'trusted.com');
1995 $this->assertEquals('trusted.com', $request->getHost());
1996 $this->assertEquals(80, $request->getPort());
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);
2004 $request->headers->set('host', 'trusted.com:8000');
2005 $this->assertEquals('trusted.com', $request->getHost());
2006 $this->assertEquals(8000, $request->getPort());
2008 $request->headers->set('host', 'subdomain.trusted.com');
2009 $this->assertEquals('subdomain.trusted.com', $request->getHost());
2011 // reset request for following tests
2012 Request::setTrustedHosts(array());
2015 public function testFactory()
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();
2021 $this->assertEquals('foo', Request::create('/')->getFoo());
2023 Request::setFactory(null);
2027 * @dataProvider getLongHostNames
2029 public function testVeryLongHosts($host)
2031 $start = microtime(true);
2033 $request = Request::create('/');
2034 $request->headers->set('host', $host);
2035 $this->assertEquals($host, $request->getHost());
2036 $this->assertLessThan(5, microtime(true) - $start);
2040 * @dataProvider getHostValidities
2042 public function testHostValidity($host, $isValid, $expectedHost = null, $expectedPort = null)
2044 $request = Request::create('/');
2045 $request->headers->set('host', $host);
2048 $this->assertSame($expectedHost ?: $host, $request->getHost());
2049 if ($expectedPort) {
2050 $this->assertSame($expectedPort, $request->getPort());
2053 if (method_exists($this, 'expectException')) {
2054 $this->expectException(SuspiciousOperationException::class);
2055 $this->expectExceptionMessage('Invalid Host');
2057 $this->setExpectedException(SuspiciousOperationException::class, 'Invalid Host');
2060 $request->getHost();
2064 public function getHostValidities()
2068 array('a..', false),
2070 array("\xE9", false),
2071 array('[::1]', true),
2072 array('[::1]:80', true, '[::1]', 80),
2073 array(str_repeat('.', 101), false),
2077 public function getLongHostNames()
2080 array('a'.str_repeat('.a', 40000)),
2081 array(str_repeat(':', 101)),
2086 * @dataProvider methodIdempotentProvider
2088 public function testMethodIdempotent($method, $idempotent)
2090 $request = new Request();
2091 $request->setMethod($method);
2092 $this->assertEquals($idempotent, $request->isMethodIdempotent());
2095 public function methodIdempotentProvider()
2098 array('HEAD', true),
2100 array('POST', false),
2102 array('PATCH', false),
2103 array('DELETE', true),
2104 array('PURGE', true),
2105 array('OPTIONS', true),
2106 array('TRACE', true),
2107 array('CONNECT', false),
2112 * @dataProvider methodSafeProvider
2114 public function testMethodSafe($method, $safe)
2116 $request = new Request();
2117 $request->setMethod($method);
2118 $this->assertEquals($safe, $request->isMethodSafe(false));
2121 public function methodSafeProvider()
2124 array('HEAD', 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),
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.
2141 public function testMethodSafeChecksCacheable()
2143 $request = new Request();
2144 $request->setMethod('OPTIONS');
2145 $this->assertFalse($request->isMethodSafe());
2149 * @dataProvider methodCacheableProvider
2151 public function testMethodCacheable($method, $cacheable)
2153 $request = new Request();
2154 $request->setMethod($method);
2155 $this->assertEquals($cacheable, $request->isMethodCacheable());
2158 public function methodCacheableProvider()
2161 array('HEAD', 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),
2177 public function testGetTrustedHeaderName()
2179 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL);
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));
2187 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
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));
2195 Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'A');
2196 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'B');
2197 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'C');
2198 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'D');
2199 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'E');
2201 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
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));
2209 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL);
2211 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
2212 $this->assertSame('B', 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));
2217 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
2219 $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
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');
2230 * @dataProvider protocolVersionProvider
2232 public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expected)
2234 if ($trustedProxy) {
2235 Request::setTrustedProxies(array('1.1.1.1'), -1);
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);
2243 $this->assertSame($expected, $request->getProtocolVersion());
2246 public function protocolVersionProvider()
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'),
2259 public function nonstandardRequestsData()
2262 array('', '', '/', 'http://host:8080/', ''),
2263 array('/', '', '/', 'http://host:8080/', ''),
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'),
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'),
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'),
2276 array('hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
2277 array('/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
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'),
2286 * @dataProvider nonstandardRequestsData
2288 public function testNonstandardRequests($requestUri, $queryString, $expectedPathInfo, $expectedUri, $expectedBasePath = '', $expectedBaseUrl = null)
2290 if (null === $expectedBaseUrl) {
2291 $expectedBaseUrl = $expectedBasePath;
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,
2303 $request = new Request(array(), array(), array(), array(), array(), $server);
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());
2315 class RequestContentProxy extends Request
2317 public function getContent($asResource = false)
2319 return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent'), '', '&');
2323 class NewRequest extends Request
2325 public function getFoo()