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);
26 Request::setTrustedHosts(array());
29 public function testInitialize()
31 $request = new Request();
33 $request->initialize(array('foo' => 'bar'));
34 $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument');
36 $request->initialize(array(), array('foo' => 'bar'));
37 $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument');
39 $request->initialize(array(), array(), array('foo' => 'bar'));
40 $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument');
42 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar'));
43 $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its sixth argument');
46 public function testGetLocale()
48 $request = new Request();
49 $request->setLocale('pl');
50 $locale = $request->getLocale();
51 $this->assertEquals('pl', $locale);
54 public function testGetUser()
56 $request = Request::create('http://user:password@test.com');
57 $user = $request->getUser();
59 $this->assertEquals('user', $user);
62 public function testGetPassword()
64 $request = Request::create('http://user:password@test.com');
65 $password = $request->getPassword();
67 $this->assertEquals('password', $password);
70 public function testIsNoCache()
72 $request = new Request();
73 $isNoCache = $request->isNoCache();
75 $this->assertFalse($isNoCache);
78 public function testGetContentType()
80 $request = new Request();
81 $contentType = $request->getContentType();
83 $this->assertNull($contentType);
86 public function testSetDefaultLocale()
88 $request = new Request();
89 $request->setDefaultLocale('pl');
90 $locale = $request->getLocale();
92 $this->assertEquals('pl', $locale);
95 public function testCreate()
97 $request = Request::create('http://test.com/foo?bar=baz');
98 $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
99 $this->assertEquals('/foo', $request->getPathInfo());
100 $this->assertEquals('bar=baz', $request->getQueryString());
101 $this->assertEquals(80, $request->getPort());
102 $this->assertEquals('test.com', $request->getHttpHost());
103 $this->assertFalse($request->isSecure());
105 $request = Request::create('http://test.com/foo', 'GET', array('bar' => 'baz'));
106 $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
107 $this->assertEquals('/foo', $request->getPathInfo());
108 $this->assertEquals('bar=baz', $request->getQueryString());
109 $this->assertEquals(80, $request->getPort());
110 $this->assertEquals('test.com', $request->getHttpHost());
111 $this->assertFalse($request->isSecure());
113 $request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz'));
114 $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
115 $this->assertEquals('/foo', $request->getPathInfo());
116 $this->assertEquals('bar=baz', $request->getQueryString());
117 $this->assertEquals(80, $request->getPort());
118 $this->assertEquals('test.com', $request->getHttpHost());
119 $this->assertFalse($request->isSecure());
121 $request = Request::create('https://test.com/foo?bar=baz');
122 $this->assertEquals('https://test.com/foo?bar=baz', $request->getUri());
123 $this->assertEquals('/foo', $request->getPathInfo());
124 $this->assertEquals('bar=baz', $request->getQueryString());
125 $this->assertEquals(443, $request->getPort());
126 $this->assertEquals('test.com', $request->getHttpHost());
127 $this->assertTrue($request->isSecure());
129 $request = Request::create('test.com:90/foo');
130 $this->assertEquals('http://test.com:90/foo', $request->getUri());
131 $this->assertEquals('/foo', $request->getPathInfo());
132 $this->assertEquals('test.com', $request->getHost());
133 $this->assertEquals('test.com:90', $request->getHttpHost());
134 $this->assertEquals(90, $request->getPort());
135 $this->assertFalse($request->isSecure());
137 $request = Request::create('https://test.com:90/foo');
138 $this->assertEquals('https://test.com:90/foo', $request->getUri());
139 $this->assertEquals('/foo', $request->getPathInfo());
140 $this->assertEquals('test.com', $request->getHost());
141 $this->assertEquals('test.com:90', $request->getHttpHost());
142 $this->assertEquals(90, $request->getPort());
143 $this->assertTrue($request->isSecure());
145 $request = Request::create('https://127.0.0.1:90/foo');
146 $this->assertEquals('https://127.0.0.1:90/foo', $request->getUri());
147 $this->assertEquals('/foo', $request->getPathInfo());
148 $this->assertEquals('127.0.0.1', $request->getHost());
149 $this->assertEquals('127.0.0.1:90', $request->getHttpHost());
150 $this->assertEquals(90, $request->getPort());
151 $this->assertTrue($request->isSecure());
153 $request = Request::create('https://[::1]:90/foo');
154 $this->assertEquals('https://[::1]:90/foo', $request->getUri());
155 $this->assertEquals('/foo', $request->getPathInfo());
156 $this->assertEquals('[::1]', $request->getHost());
157 $this->assertEquals('[::1]:90', $request->getHttpHost());
158 $this->assertEquals(90, $request->getPort());
159 $this->assertTrue($request->isSecure());
161 $request = Request::create('https://[::1]/foo');
162 $this->assertEquals('https://[::1]/foo', $request->getUri());
163 $this->assertEquals('/foo', $request->getPathInfo());
164 $this->assertEquals('[::1]', $request->getHost());
165 $this->assertEquals('[::1]', $request->getHttpHost());
166 $this->assertEquals(443, $request->getPort());
167 $this->assertTrue($request->isSecure());
169 $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}';
170 $request = Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), $json);
171 $this->assertEquals($json, $request->getContent());
172 $this->assertFalse($request->isSecure());
174 $request = Request::create('http://test.com');
175 $this->assertEquals('http://test.com/', $request->getUri());
176 $this->assertEquals('/', $request->getPathInfo());
177 $this->assertEquals('', $request->getQueryString());
178 $this->assertEquals(80, $request->getPort());
179 $this->assertEquals('test.com', $request->getHttpHost());
180 $this->assertFalse($request->isSecure());
182 $request = Request::create('http://test.com?test=1');
183 $this->assertEquals('http://test.com/?test=1', $request->getUri());
184 $this->assertEquals('/', $request->getPathInfo());
185 $this->assertEquals('test=1', $request->getQueryString());
186 $this->assertEquals(80, $request->getPort());
187 $this->assertEquals('test.com', $request->getHttpHost());
188 $this->assertFalse($request->isSecure());
190 $request = Request::create('http://test.com:90/?test=1');
191 $this->assertEquals('http://test.com:90/?test=1', $request->getUri());
192 $this->assertEquals('/', $request->getPathInfo());
193 $this->assertEquals('test=1', $request->getQueryString());
194 $this->assertEquals(90, $request->getPort());
195 $this->assertEquals('test.com:90', $request->getHttpHost());
196 $this->assertFalse($request->isSecure());
198 $request = Request::create('http://username:password@test.com');
199 $this->assertEquals('http://test.com/', $request->getUri());
200 $this->assertEquals('/', $request->getPathInfo());
201 $this->assertEquals('', $request->getQueryString());
202 $this->assertEquals(80, $request->getPort());
203 $this->assertEquals('test.com', $request->getHttpHost());
204 $this->assertEquals('username', $request->getUser());
205 $this->assertEquals('password', $request->getPassword());
206 $this->assertFalse($request->isSecure());
208 $request = Request::create('http://username@test.com');
209 $this->assertEquals('http://test.com/', $request->getUri());
210 $this->assertEquals('/', $request->getPathInfo());
211 $this->assertEquals('', $request->getQueryString());
212 $this->assertEquals(80, $request->getPort());
213 $this->assertEquals('test.com', $request->getHttpHost());
214 $this->assertEquals('username', $request->getUser());
215 $this->assertSame('', $request->getPassword());
216 $this->assertFalse($request->isSecure());
218 $request = Request::create('http://test.com/?foo');
219 $this->assertEquals('/?foo', $request->getRequestUri());
220 $this->assertEquals(array('foo' => ''), $request->query->all());
222 // assume rewrite rule: (.*) --> app/app.php; app/ is a symlink to a symfony web/ directory
223 $request = Request::create('http://test.com/apparthotel-1234', 'GET', array(), array(), array(),
225 'DOCUMENT_ROOT' => '/var/www/www.test.com',
226 'SCRIPT_FILENAME' => '/var/www/www.test.com/app/app.php',
227 'SCRIPT_NAME' => '/app/app.php',
228 'PHP_SELF' => '/app/app.php/apparthotel-1234',
230 $this->assertEquals('http://test.com/apparthotel-1234', $request->getUri());
231 $this->assertEquals('/apparthotel-1234', $request->getPathInfo());
232 $this->assertEquals('', $request->getQueryString());
233 $this->assertEquals(80, $request->getPort());
234 $this->assertEquals('test.com', $request->getHttpHost());
235 $this->assertFalse($request->isSecure());
238 public function testCreateCheckPrecedence()
240 // server is used by default
241 $request = Request::create('/', 'DELETE', array(), array(), array(), array(
242 'HTTP_HOST' => 'example.com',
244 'SERVER_PORT' => 443,
245 'PHP_AUTH_USER' => 'fabien',
246 'PHP_AUTH_PW' => 'pa$$',
247 'QUERY_STRING' => 'foo=bar',
248 'CONTENT_TYPE' => 'application/json',
250 $this->assertEquals('example.com', $request->getHost());
251 $this->assertEquals(443, $request->getPort());
252 $this->assertTrue($request->isSecure());
253 $this->assertEquals('fabien', $request->getUser());
254 $this->assertEquals('pa$$', $request->getPassword());
255 $this->assertEquals('', $request->getQueryString());
256 $this->assertEquals('application/json', $request->headers->get('CONTENT_TYPE'));
258 // URI has precedence over server
259 $request = Request::create('http://thomas:pokemon@example.net:8080/?foo=bar', 'GET', array(), array(), array(), array(
260 'HTTP_HOST' => 'example.com',
262 'SERVER_PORT' => 443,
264 $this->assertEquals('example.net', $request->getHost());
265 $this->assertEquals(8080, $request->getPort());
266 $this->assertFalse($request->isSecure());
267 $this->assertEquals('thomas', $request->getUser());
268 $this->assertEquals('pokemon', $request->getPassword());
269 $this->assertEquals('foo=bar', $request->getQueryString());
272 public function testDuplicate()
274 $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar'));
275 $dup = $request->duplicate();
277 $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters');
278 $this->assertEquals($request->request->all(), $dup->request->all(), '->duplicate() duplicates a request an copy the current request parameters');
279 $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes');
280 $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers');
282 $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar'));
284 $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided');
285 $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided');
286 $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided');
287 $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided');
290 public function testDuplicateWithFormat()
292 $request = new Request(array(), array(), array('_format' => 'json'));
293 $dup = $request->duplicate();
295 $this->assertEquals('json', $dup->getRequestFormat());
296 $this->assertEquals('json', $dup->attributes->get('_format'));
298 $request = new Request();
299 $request->setRequestFormat('xml');
300 $dup = $request->duplicate();
302 $this->assertEquals('xml', $dup->getRequestFormat());
306 * @dataProvider getFormatToMimeTypeMapProviderWithAdditionalNullFormat
308 public function testGetFormatFromMimeType($format, $mimeTypes)
310 $request = new Request();
311 foreach ($mimeTypes as $mime) {
312 $this->assertEquals($format, $request->getFormat($mime));
314 $request->setFormat($format, $mimeTypes);
315 foreach ($mimeTypes as $mime) {
316 $this->assertEquals($format, $request->getFormat($mime));
318 if (null !== $format) {
319 $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
324 public function getFormatToMimeTypeMapProviderWithAdditionalNullFormat()
327 array(array(null, array(null, 'unexistent-mime-type'))),
328 $this->getFormatToMimeTypeMapProvider()
332 public function testGetFormatFromMimeTypeWithParameters()
334 $request = new Request();
335 $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8'));
339 * @dataProvider getFormatToMimeTypeMapProvider
341 public function testGetMimeTypeFromFormat($format, $mimeTypes)
343 $request = new Request();
344 $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
348 * @dataProvider getFormatToMimeTypeMapProvider
350 public function testGetMimeTypesFromFormat($format, $mimeTypes)
352 $this->assertEquals($mimeTypes, Request::getMimeTypes($format));
355 public function testGetMimeTypesFromInexistentFormat()
357 $request = new Request();
358 $this->assertNull($request->getMimeType('foo'));
359 $this->assertEquals(array(), Request::getMimeTypes('foo'));
362 public function testGetFormatWithCustomMimeType()
364 $request = new Request();
365 $request->setFormat('custom', 'application/vnd.foo.api;myversion=2.3');
366 $this->assertEquals('custom', $request->getFormat('application/vnd.foo.api;myversion=2.3'));
369 public function getFormatToMimeTypeMapProvider()
372 array('txt', array('text/plain')),
373 array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')),
374 array('css', array('text/css')),
375 array('json', array('application/json', 'application/x-json')),
376 array('jsonld', array('application/ld+json')),
377 array('xml', array('text/xml', 'application/xml', 'application/x-xml')),
378 array('rdf', array('application/rdf+xml')),
379 array('atom', array('application/atom+xml')),
383 public function testGetUri()
387 // Standard Request on non default PORT
388 // http://host:8080/index.php/path/info?query=string
390 $server['HTTP_HOST'] = 'host:8080';
391 $server['SERVER_NAME'] = 'servername';
392 $server['SERVER_PORT'] = '8080';
394 $server['QUERY_STRING'] = 'query=string';
395 $server['REQUEST_URI'] = '/index.php/path/info?query=string';
396 $server['SCRIPT_NAME'] = '/index.php';
397 $server['PATH_INFO'] = '/path/info';
398 $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
399 $server['PHP_SELF'] = '/index_dev.php/path/info';
400 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
402 $request = new Request();
404 $request->initialize(array(), array(), array(), array(), array(), $server);
406 $this->assertEquals('http://host:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port');
408 // Use std port number
409 $server['HTTP_HOST'] = 'host';
410 $server['SERVER_NAME'] = 'servername';
411 $server['SERVER_PORT'] = '80';
413 $request->initialize(array(), array(), array(), array(), array(), $server);
415 $this->assertEquals('http://host/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port');
417 // Without HOST HEADER
418 unset($server['HTTP_HOST']);
419 $server['SERVER_NAME'] = 'servername';
420 $server['SERVER_PORT'] = '80';
422 $request->initialize(array(), array(), array(), array(), array(), $server);
424 $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER');
426 // Request with URL REWRITING (hide index.php)
427 // RewriteCond %{REQUEST_FILENAME} !-f
428 // RewriteRule ^(.*)$ index.php [QSA,L]
429 // http://host:8080/path/info?query=string
431 $server['HTTP_HOST'] = 'host:8080';
432 $server['SERVER_NAME'] = 'servername';
433 $server['SERVER_PORT'] = '8080';
435 $server['REDIRECT_QUERY_STRING'] = 'query=string';
436 $server['REDIRECT_URL'] = '/path/info';
437 $server['SCRIPT_NAME'] = '/index.php';
438 $server['QUERY_STRING'] = 'query=string';
439 $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
440 $server['SCRIPT_NAME'] = '/index.php';
441 $server['PHP_SELF'] = '/index.php';
442 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
444 $request->initialize(array(), array(), array(), array(), array(), $server);
445 $this->assertEquals('http://host:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite');
447 // Use std port number
448 // http://host/path/info?query=string
449 $server['HTTP_HOST'] = 'host';
450 $server['SERVER_NAME'] = 'servername';
451 $server['SERVER_PORT'] = '80';
453 $request->initialize(array(), array(), array(), array(), array(), $server);
455 $this->assertEquals('http://host/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port');
457 // Without HOST HEADER
458 unset($server['HTTP_HOST']);
459 $server['SERVER_NAME'] = 'servername';
460 $server['SERVER_PORT'] = '80';
462 $request->initialize(array(), array(), array(), array(), array(), $server);
464 $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER');
466 // With encoded characters
469 'HTTP_HOST' => 'host:8080',
470 'SERVER_NAME' => 'servername',
471 'SERVER_PORT' => '8080',
472 'QUERY_STRING' => 'query=string',
473 'REQUEST_URI' => '/ba%20se/index_dev.php/foo%20bar/in+fo?query=string',
474 'SCRIPT_NAME' => '/ba se/index_dev.php',
475 'PATH_TRANSLATED' => 'redirect:/index.php/foo bar/in+fo',
476 'PHP_SELF' => '/ba se/index_dev.php/path/info',
477 'SCRIPT_FILENAME' => '/some/where/ba se/index_dev.php',
480 $request->initialize(array(), array(), array(), array(), array(), $server);
483 'http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string',
489 $server['PHP_AUTH_USER'] = 'fabien';
490 $request->initialize(array(), array(), array(), array(), array(), $server);
491 $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri());
493 $server['PHP_AUTH_PW'] = 'symfony';
494 $request->initialize(array(), array(), array(), array(), array(), $server);
495 $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri());
498 public function testGetUriForPath()
500 $request = Request::create('http://test.com/foo?bar=baz');
501 $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path'));
503 $request = Request::create('http://test.com:90/foo?bar=baz');
504 $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path'));
506 $request = Request::create('https://test.com/foo?bar=baz');
507 $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path'));
509 $request = Request::create('https://test.com:90/foo?bar=baz');
510 $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path'));
514 // Standard Request on non default PORT
515 // http://host:8080/index.php/path/info?query=string
517 $server['HTTP_HOST'] = 'host:8080';
518 $server['SERVER_NAME'] = 'servername';
519 $server['SERVER_PORT'] = '8080';
521 $server['QUERY_STRING'] = 'query=string';
522 $server['REQUEST_URI'] = '/index.php/path/info?query=string';
523 $server['SCRIPT_NAME'] = '/index.php';
524 $server['PATH_INFO'] = '/path/info';
525 $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
526 $server['PHP_SELF'] = '/index_dev.php/path/info';
527 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
529 $request = new Request();
531 $request->initialize(array(), array(), array(), array(), array(), $server);
533 $this->assertEquals('http://host:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port');
535 // Use std port number
536 $server['HTTP_HOST'] = 'host';
537 $server['SERVER_NAME'] = 'servername';
538 $server['SERVER_PORT'] = '80';
540 $request->initialize(array(), array(), array(), array(), array(), $server);
542 $this->assertEquals('http://host/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port');
544 // Without HOST HEADER
545 unset($server['HTTP_HOST']);
546 $server['SERVER_NAME'] = 'servername';
547 $server['SERVER_PORT'] = '80';
549 $request->initialize(array(), array(), array(), array(), array(), $server);
551 $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER');
553 // Request with URL REWRITING (hide index.php)
554 // RewriteCond %{REQUEST_FILENAME} !-f
555 // RewriteRule ^(.*)$ index.php [QSA,L]
556 // http://host:8080/path/info?query=string
558 $server['HTTP_HOST'] = 'host:8080';
559 $server['SERVER_NAME'] = 'servername';
560 $server['SERVER_PORT'] = '8080';
562 $server['REDIRECT_QUERY_STRING'] = 'query=string';
563 $server['REDIRECT_URL'] = '/path/info';
564 $server['SCRIPT_NAME'] = '/index.php';
565 $server['QUERY_STRING'] = 'query=string';
566 $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
567 $server['SCRIPT_NAME'] = '/index.php';
568 $server['PHP_SELF'] = '/index.php';
569 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
571 $request->initialize(array(), array(), array(), array(), array(), $server);
572 $this->assertEquals('http://host:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite');
574 // Use std port number
575 // http://host/path/info?query=string
576 $server['HTTP_HOST'] = 'host';
577 $server['SERVER_NAME'] = 'servername';
578 $server['SERVER_PORT'] = '80';
580 $request->initialize(array(), array(), array(), array(), array(), $server);
582 $this->assertEquals('http://host/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port');
584 // Without HOST HEADER
585 unset($server['HTTP_HOST']);
586 $server['SERVER_NAME'] = 'servername';
587 $server['SERVER_PORT'] = '80';
589 $request->initialize(array(), array(), array(), array(), array(), $server);
591 $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER');
592 $this->assertEquals('servername', $request->getHttpHost());
596 $server['PHP_AUTH_USER'] = 'fabien';
597 $request->initialize(array(), array(), array(), array(), array(), $server);
598 $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'));
600 $server['PHP_AUTH_PW'] = 'symfony';
601 $request->initialize(array(), array(), array(), array(), array(), $server);
602 $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'));
606 * @dataProvider getRelativeUriForPathData()
608 public function testGetRelativeUriForPath($expected, $pathinfo, $path)
610 $this->assertEquals($expected, Request::create($pathinfo)->getRelativeUriForPath($path));
613 public function getRelativeUriForPathData()
616 array('me.png', '/foo', '/me.png'),
617 array('../me.png', '/foo/bar', '/me.png'),
618 array('me.png', '/foo/bar', '/foo/me.png'),
619 array('../baz/me.png', '/foo/bar/b', '/foo/baz/me.png'),
620 array('../../fooz/baz/me.png', '/foo/bar/b', '/fooz/baz/me.png'),
621 array('baz/me.png', '/foo/bar/b', 'baz/me.png'),
625 public function testGetUserInfo()
627 $request = new Request();
629 $server = array('PHP_AUTH_USER' => 'fabien');
630 $request->initialize(array(), array(), array(), array(), array(), $server);
631 $this->assertEquals('fabien', $request->getUserInfo());
633 $server['PHP_AUTH_USER'] = '0';
634 $request->initialize(array(), array(), array(), array(), array(), $server);
635 $this->assertEquals('0', $request->getUserInfo());
637 $server['PHP_AUTH_PW'] = '0';
638 $request->initialize(array(), array(), array(), array(), array(), $server);
639 $this->assertEquals('0:0', $request->getUserInfo());
642 public function testGetSchemeAndHttpHost()
644 $request = new Request();
647 $server['SERVER_NAME'] = 'servername';
648 $server['SERVER_PORT'] = '90';
649 $request->initialize(array(), array(), array(), array(), array(), $server);
650 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
652 $server['PHP_AUTH_USER'] = 'fabien';
653 $request->initialize(array(), array(), array(), array(), array(), $server);
654 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
656 $server['PHP_AUTH_USER'] = '0';
657 $request->initialize(array(), array(), array(), array(), array(), $server);
658 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
660 $server['PHP_AUTH_PW'] = '0';
661 $request->initialize(array(), array(), array(), array(), array(), $server);
662 $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
666 * @dataProvider getQueryStringNormalizationData
668 public function testGetQueryString($query, $expectedQuery, $msg)
670 $request = new Request();
672 $request->server->set('QUERY_STRING', $query);
673 $this->assertSame($expectedQuery, $request->getQueryString(), $msg);
676 public function getQueryStringNormalizationData()
679 array('foo', 'foo', 'works with valueless parameters'),
680 array('foo=', 'foo=', 'includes a dangling equal sign'),
681 array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'),
682 array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'),
684 // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded).
685 // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str.
686 array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'),
688 array('foo[]=1&foo[]=2', 'foo%5B%5D=1&foo%5B%5D=2', 'allows array notation'),
689 array('foo=1&foo=2', 'foo=1&foo=2', 'allows repeated parameters'),
690 array('pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'),
691 array('0', '0', 'allows "0"'),
692 array('Jane Doe&John%20Doe', 'Jane%20Doe&John%20Doe', 'normalizes encoding in keys'),
693 array('her=Jane Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes encoding in values'),
694 array('foo=bar&&&test&&', 'foo=bar&test', 'removes unneeded delimiters'),
695 array('formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'),
697 // Ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway.
698 // PHP also does not include them when building _GET.
699 array('foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'),
703 public function testGetQueryStringReturnsNull()
705 $request = new Request();
707 $this->assertNull($request->getQueryString(), '->getQueryString() returns null for non-existent query string');
709 $request->server->set('QUERY_STRING', '');
710 $this->assertNull($request->getQueryString(), '->getQueryString() returns null for empty query string');
713 public function testGetHost()
715 $request = new Request();
717 $request->initialize(array('foo' => 'bar'));
718 $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized');
720 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com'));
721 $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header');
723 // Host header with port number
724 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com:8080'));
725 $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header with port number');
728 $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com'));
729 $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from server name');
731 $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com', 'HTTP_HOST' => 'www.host.com'));
732 $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME ');
735 public function testGetPort()
737 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
738 'HTTP_X_FORWARDED_PROTO' => 'https',
739 'HTTP_X_FORWARDED_PORT' => '443',
741 $port = $request->getPort();
743 $this->assertEquals(80, $port, 'Without trusted proxies FORWARDED_PROTO and FORWARDED_PORT are ignored.');
745 Request::setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_ALL);
746 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
747 'HTTP_X_FORWARDED_PROTO' => 'https',
748 'HTTP_X_FORWARDED_PORT' => '8443',
750 $this->assertEquals(80, $request->getPort(), 'With PROTO and PORT on untrusted connection server value takes precedence.');
751 $request->server->set('REMOTE_ADDR', '1.1.1.1');
752 $this->assertEquals(8443, $request->getPort(), 'With PROTO and PORT set PORT takes precedence.');
754 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
755 'HTTP_X_FORWARDED_PROTO' => 'https',
757 $this->assertEquals(80, $request->getPort(), 'With only PROTO set getPort() ignores trusted headers on untrusted connection.');
758 $request->server->set('REMOTE_ADDR', '1.1.1.1');
759 $this->assertEquals(443, $request->getPort(), 'With only PROTO set getPort() defaults to 443.');
761 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
762 'HTTP_X_FORWARDED_PROTO' => 'http',
764 $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() ignores trusted headers on untrusted connection.');
765 $request->server->set('REMOTE_ADDR', '1.1.1.1');
766 $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() returns port of the original request.');
768 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
769 'HTTP_X_FORWARDED_PROTO' => 'On',
771 $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is On, getPort() ignores trusted headers on untrusted connection.');
772 $request->server->set('REMOTE_ADDR', '1.1.1.1');
773 $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is On, getPort() defaults to 443.');
775 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
776 'HTTP_X_FORWARDED_PROTO' => '1',
778 $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is 1, getPort() ignores trusted headers on untrusted connection.');
779 $request->server->set('REMOTE_ADDR', '1.1.1.1');
780 $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is 1, getPort() defaults to 443.');
782 $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
783 'HTTP_X_FORWARDED_PROTO' => 'something-else',
785 $port = $request->getPort();
786 $this->assertEquals(80, $port, 'With only PROTO set and value is not recognized, getPort() defaults to 80.');
790 * @expectedException \RuntimeException
792 public function testGetHostWithFakeHttpHostValue()
794 $request = new Request();
795 $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.host.com?query=string'));
799 public function testGetSetMethod()
801 $request = new Request();
803 $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined');
805 $request->setMethod('get');
806 $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string');
808 $request->setMethod('PURGE');
809 $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one');
811 $request->setMethod('POST');
812 $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined');
814 $request->setMethod('POST');
815 $request->request->set('_method', 'purge');
816 $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled');
818 $request = new Request();
819 $request->setMethod('POST');
820 $request->request->set('_method', 'purge');
822 $this->assertFalse(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be disabled by default');
824 Request::enableHttpMethodParameterOverride();
826 $this->assertTrue(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be enabled now but it is not');
828 $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
829 $this->disableHttpMethodParameterOverride();
831 $request = new Request();
832 $request->setMethod('POST');
833 $request->query->set('_method', 'purge');
834 $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled');
836 $request = new Request();
837 $request->setMethod('POST');
838 $request->query->set('_method', 'purge');
839 Request::enableHttpMethodParameterOverride();
840 $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
841 $this->disableHttpMethodParameterOverride();
843 $request = new Request();
844 $request->setMethod('POST');
845 $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
846 $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override even though _method is set if defined and POST');
848 $request = new Request();
849 $request->setMethod('POST');
850 $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
851 $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override if defined and POST');
855 * @dataProvider getClientIpsProvider
857 public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
859 $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);
861 $this->assertEquals($expected[0], $request->getClientIp());
865 * @dataProvider getClientIpsProvider
867 public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
869 $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);
871 $this->assertEquals($expected, $request->getClientIps());
875 * @dataProvider getClientIpsForwardedProvider
877 public function testGetClientIpsForwarded($expected, $remoteAddr, $httpForwarded, $trustedProxies)
879 $request = $this->getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies);
881 $this->assertEquals($expected, $request->getClientIps());
884 public function getClientIpsForwardedProvider()
886 // $expected $remoteAddr $httpForwarded $trustedProxies
888 array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', null),
889 array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')),
890 array(array('88.88.88.88'), '127.0.0.1', 'for="88.88.88.88:80"', array('127.0.0.1')),
891 array(array('192.0.2.60'), '::1', 'for=192.0.2.60;proto=http;by=203.0.113.43', array('::1')),
892 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')),
893 array(array('2001:db8:cafe::17'), '::1', 'for="[2001:db8:cafe::17]:4711', array('::1')),
897 public function getClientIpsProvider()
899 // $expected $remoteAddr $httpForwardedFor $trustedProxies
902 array(array('88.88.88.88'), '88.88.88.88', null, null),
903 // trust the IPv4 remote addr
904 array(array('88.88.88.88'), '88.88.88.88', null, array('88.88.88.88')),
907 array(array('::1'), '::1', null, null),
908 // trust the IPv6 remote addr
909 array(array('::1'), '::1', null, array('::1')),
911 // forwarded for with remote IPv4 addr not trusted
912 array(array('127.0.0.1'), '127.0.0.1', '88.88.88.88', null),
913 // forwarded for with remote IPv4 addr trusted
914 array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1')),
915 // forwarded for with remote IPv4 and all FF addrs trusted
916 array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1', '88.88.88.88')),
917 // forwarded for with remote IPv4 range trusted
918 array(array('88.88.88.88'), '123.45.67.89', '88.88.88.88', array('123.45.67.0/24')),
920 // forwarded for with remote IPv6 addr not trusted
921 array(array('1620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', null),
922 // forwarded for with remote IPv6 addr trusted
923 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')),
924 // forwarded for with remote IPv6 range trusted
925 array(array('88.88.88.88'), '2a01:198:603:0:396e:4789:8e99:890f', '88.88.88.88', array('2a01:198:603:0::/65')),
927 // multiple forwarded for with remote IPv4 addr trusted
928 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')),
929 // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted
930 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')),
931 // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle
932 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')),
933 // multiple forwarded for with remote IPv4 addr and all reverse proxies trusted
934 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')),
936 // multiple forwarded for with remote IPv6 addr trusted
937 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')),
938 // multiple forwarded for with remote IPv6 addr and some reverse proxies trusted
939 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')),
940 // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle
941 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')),
943 // client IP with port
944 array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88:12345, 127.0.0.1', array('127.0.0.1')),
946 // invalid forwarded IP is ignored
947 array(array('88.88.88.88'), '127.0.0.1', 'unknown,88.88.88.88', array('127.0.0.1')),
948 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')),
953 * @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException
954 * @dataProvider getClientIpsWithConflictingHeadersProvider
956 public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXForwardedFor)
958 $request = new Request();
961 'REMOTE_ADDR' => '88.88.88.88',
962 'HTTP_FORWARDED' => $httpForwarded,
963 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
966 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL | Request::HEADER_FORWARDED);
968 $request->initialize(array(), array(), array(), array(), array(), $server);
970 $request->getClientIps();
974 * @dataProvider getClientIpsWithConflictingHeadersProvider
976 public function testGetClientIpsOnlyXHttpForwardedForTrusted($httpForwarded, $httpXForwardedFor)
978 $request = new Request();
981 'REMOTE_ADDR' => '88.88.88.88',
982 'HTTP_FORWARDED' => $httpForwarded,
983 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
986 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_FOR);
988 $request->initialize(array(), array(), array(), array(), array(), $server);
990 $this->assertSame(array_reverse(explode(',', $httpXForwardedFor)), $request->getClientIps());
993 public function getClientIpsWithConflictingHeadersProvider()
995 // $httpForwarded $httpXForwardedFor
997 array('for=87.65.43.21', '192.0.2.60'),
998 array('for=87.65.43.21, for=192.0.2.60', '192.0.2.60'),
999 array('for=192.0.2.60', '192.0.2.60,87.65.43.21'),
1000 array('for="::face", for=192.0.2.60', '192.0.2.60,192.0.2.43'),
1001 array('for=87.65.43.21, for=192.0.2.60', '192.0.2.60,87.65.43.21'),
1006 * @dataProvider getClientIpsWithAgreeingHeadersProvider
1008 public function testGetClientIpsWithAgreeingHeaders($httpForwarded, $httpXForwardedFor, $expectedIps)
1010 $request = new Request();
1013 'REMOTE_ADDR' => '88.88.88.88',
1014 'HTTP_FORWARDED' => $httpForwarded,
1015 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
1018 Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL);
1020 $request->initialize(array(), array(), array(), array(), array(), $server);
1022 $clientIps = $request->getClientIps();
1024 $this->assertSame($expectedIps, $clientIps);
1027 public function getClientIpsWithAgreeingHeadersProvider()
1029 // $httpForwarded $httpXForwardedFor
1031 array('for="192.0.2.60"', '192.0.2.60', array('192.0.2.60')),
1032 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')),
1033 array('for="[::face]", for=192.0.2.60', '::face,192.0.2.60', array('192.0.2.60', '::face')),
1034 array('for="192.0.2.60:80"', '192.0.2.60', array('192.0.2.60')),
1035 array('for=192.0.2.60;proto=http;by=203.0.113.43', '192.0.2.60', array('192.0.2.60')),
1036 array('for="[2001:db8:cafe::17]:4711"', '2001:db8:cafe::17', array('2001:db8:cafe::17')),
1040 public function testGetContentWorksTwiceInDefaultMode()
1042 $req = new Request();
1043 $this->assertEquals('', $req->getContent());
1044 $this->assertEquals('', $req->getContent());
1047 public function testGetContentReturnsResource()
1049 $req = new Request();
1050 $retval = $req->getContent(true);
1051 $this->assertInternalType('resource', $retval);
1052 $this->assertEquals('', fread($retval, 1));
1053 $this->assertTrue(feof($retval));
1056 public function testGetContentReturnsResourceWhenContentSetInConstructor()
1058 $req = new Request(array(), array(), array(), array(), array(), array(), 'MyContent');
1059 $resource = $req->getContent(true);
1061 $this->assertInternalType('resource', $resource);
1062 $this->assertEquals('MyContent', stream_get_contents($resource));
1065 public function testContentAsResource()
1067 $resource = fopen('php://memory', 'r+');
1068 fwrite($resource, 'My other content');
1071 $req = new Request(array(), array(), array(), array(), array(), array(), $resource);
1072 $this->assertEquals('My other content', stream_get_contents($req->getContent(true)));
1073 $this->assertEquals('My other content', $req->getContent());
1077 * @expectedException \LogicException
1078 * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider
1080 public function testGetContentCantBeCalledTwiceWithResources($first, $second)
1082 if (\PHP_VERSION_ID >= 50600) {
1083 $this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.');
1086 $req = new Request();
1087 $req->getContent($first);
1088 $req->getContent($second);
1091 public function getContentCantBeCalledTwiceWithResourcesProvider()
1094 'Resource then fetch' => array(true, false),
1095 'Resource then resource' => array(true, true),
1100 * @dataProvider getContentCanBeCalledTwiceWithResourcesProvider
1103 public function testGetContentCanBeCalledTwiceWithResources($first, $second)
1105 $req = new Request();
1106 $a = $req->getContent($first);
1107 $b = $req->getContent($second);
1110 $a = stream_get_contents($a);
1114 $b = stream_get_contents($b);
1117 $this->assertSame($a, $b);
1120 public function getContentCanBeCalledTwiceWithResourcesProvider()
1123 'Fetch then fetch' => array(false, false),
1124 'Fetch then resource' => array(false, true),
1125 'Resource then fetch' => array(true, false),
1126 'Resource then resource' => array(true, true),
1130 public function provideOverloadedMethods()
1143 * @dataProvider provideOverloadedMethods
1145 public function testCreateFromGlobals($method)
1147 $normalizedMethod = strtoupper($method);
1149 $_GET['foo1'] = 'bar1';
1150 $_POST['foo2'] = 'bar2';
1151 $_COOKIE['foo3'] = 'bar3';
1152 $_FILES['foo4'] = array('bar4');
1153 $_SERVER['foo5'] = 'bar5';
1155 $request = Request::createFromGlobals();
1156 $this->assertEquals('bar1', $request->query->get('foo1'), '::fromGlobals() uses values from $_GET');
1157 $this->assertEquals('bar2', $request->request->get('foo2'), '::fromGlobals() uses values from $_POST');
1158 $this->assertEquals('bar3', $request->cookies->get('foo3'), '::fromGlobals() uses values from $_COOKIE');
1159 $this->assertEquals(array('bar4'), $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES');
1160 $this->assertEquals('bar5', $request->server->get('foo5'), '::fromGlobals() uses values from $_SERVER');
1162 unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']);
1164 $_SERVER['REQUEST_METHOD'] = $method;
1165 $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
1166 $request = RequestContentProxy::createFromGlobals();
1167 $this->assertEquals($normalizedMethod, $request->getMethod());
1168 $this->assertEquals('mycontent', $request->request->get('content'));
1170 unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']);
1172 Request::createFromGlobals();
1173 Request::enableHttpMethodParameterOverride();
1174 $_POST['_method'] = $method;
1175 $_POST['foo6'] = 'bar6';
1176 $_SERVER['REQUEST_METHOD'] = 'PoSt';
1177 $request = Request::createFromGlobals();
1178 $this->assertEquals($normalizedMethod, $request->getMethod());
1179 $this->assertEquals('POST', $request->getRealMethod());
1180 $this->assertEquals('bar6', $request->request->get('foo6'));
1182 unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']);
1183 $this->disableHttpMethodParameterOverride();
1186 public function testOverrideGlobals()
1188 $request = new Request();
1189 $request->initialize(array('foo' => 'bar'));
1191 // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it
1194 $request->overrideGlobals();
1196 $this->assertEquals(array('foo' => 'bar'), $_GET);
1198 $request->initialize(array(), array('foo' => 'bar'));
1199 $request->overrideGlobals();
1201 $this->assertEquals(array('foo' => 'bar'), $_POST);
1203 $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);
1205 $request->headers->set('X_FORWARDED_PROTO', 'https');
1207 Request::setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_ALL);
1208 $this->assertFalse($request->isSecure());
1209 $request->server->set('REMOTE_ADDR', '1.1.1.1');
1210 $this->assertTrue($request->isSecure());
1212 $request->overrideGlobals();
1214 $this->assertArrayHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);
1216 $request->headers->set('CONTENT_TYPE', 'multipart/form-data');
1217 $request->headers->set('CONTENT_LENGTH', 12345);
1219 $request->overrideGlobals();
1221 $this->assertArrayHasKey('CONTENT_TYPE', $_SERVER);
1222 $this->assertArrayHasKey('CONTENT_LENGTH', $_SERVER);
1224 $request->initialize(array('foo' => 'bar', 'baz' => 'foo'));
1225 $request->query->remove('baz');
1227 $request->overrideGlobals();
1229 $this->assertEquals(array('foo' => 'bar'), $_GET);
1230 $this->assertEquals('foo=bar', $_SERVER['QUERY_STRING']);
1231 $this->assertEquals('foo=bar', $request->server->get('QUERY_STRING'));
1233 // restore initial $_SERVER array
1237 public function testGetScriptName()
1239 $request = new Request();
1240 $this->assertEquals('', $request->getScriptName());
1243 $server['SCRIPT_NAME'] = '/index.php';
1245 $request->initialize(array(), array(), array(), array(), array(), $server);
1247 $this->assertEquals('/index.php', $request->getScriptName());
1250 $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
1251 $request->initialize(array(), array(), array(), array(), array(), $server);
1253 $this->assertEquals('/frontend.php', $request->getScriptName());
1256 $server['SCRIPT_NAME'] = '/index.php';
1257 $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
1258 $request->initialize(array(), array(), array(), array(), array(), $server);
1260 $this->assertEquals('/index.php', $request->getScriptName());
1263 public function testGetBasePath()
1265 $request = new Request();
1266 $this->assertEquals('', $request->getBasePath());
1269 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
1270 $request->initialize(array(), array(), array(), array(), array(), $server);
1271 $this->assertEquals('', $request->getBasePath());
1274 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
1275 $server['SCRIPT_NAME'] = '/index.php';
1276 $request->initialize(array(), array(), array(), array(), array(), $server);
1278 $this->assertEquals('', $request->getBasePath());
1281 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
1282 $server['PHP_SELF'] = '/index.php';
1283 $request->initialize(array(), array(), array(), array(), array(), $server);
1285 $this->assertEquals('', $request->getBasePath());
1288 $server['SCRIPT_FILENAME'] = '/some/where/index.php';
1289 $server['ORIG_SCRIPT_NAME'] = '/index.php';
1290 $request->initialize(array(), array(), array(), array(), array(), $server);
1292 $this->assertEquals('', $request->getBasePath());
1295 public function testGetPathInfo()
1297 $request = new Request();
1298 $this->assertEquals('/', $request->getPathInfo());
1301 $server['REQUEST_URI'] = '/path/info';
1302 $request->initialize(array(), array(), array(), array(), array(), $server);
1304 $this->assertEquals('/path/info', $request->getPathInfo());
1307 $server['REQUEST_URI'] = '/path%20test/info';
1308 $request->initialize(array(), array(), array(), array(), array(), $server);
1310 $this->assertEquals('/path%20test/info', $request->getPathInfo());
1313 $server['REQUEST_URI'] = '?a=b';
1314 $request->initialize(array(), array(), array(), array(), array(), $server);
1316 $this->assertEquals('/', $request->getPathInfo());
1319 public function testGetParameterPrecedence()
1321 $request = new Request();
1322 $request->attributes->set('foo', 'attr');
1323 $request->query->set('foo', 'query');
1324 $request->request->set('foo', 'body');
1326 $this->assertSame('attr', $request->get('foo'));
1328 $request->attributes->remove('foo');
1329 $this->assertSame('query', $request->get('foo'));
1331 $request->query->remove('foo');
1332 $this->assertSame('body', $request->get('foo'));
1334 $request->request->remove('foo');
1335 $this->assertNull($request->get('foo'));
1338 public function testGetPreferredLanguage()
1340 $request = new Request();
1341 $this->assertNull($request->getPreferredLanguage());
1342 $this->assertNull($request->getPreferredLanguage(array()));
1343 $this->assertEquals('fr', $request->getPreferredLanguage(array('fr')));
1344 $this->assertEquals('fr', $request->getPreferredLanguage(array('fr', 'en')));
1345 $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'fr')));
1346 $this->assertEquals('fr-ch', $request->getPreferredLanguage(array('fr-ch', 'fr-fr')));
1348 $request = new Request();
1349 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
1350 $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'en-us')));
1352 $request = new Request();
1353 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
1354 $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));
1356 $request = new Request();
1357 $request->headers->set('Accept-language', 'zh, en-us; q=0.8');
1358 $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));
1360 $request = new Request();
1361 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, fr-fr; q=0.6, fr; q=0.5');
1362 $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));
1365 public function testIsXmlHttpRequest()
1367 $request = new Request();
1368 $this->assertFalse($request->isXmlHttpRequest());
1370 $request->headers->set('X-Requested-With', 'XMLHttpRequest');
1371 $this->assertTrue($request->isXmlHttpRequest());
1373 $request->headers->remove('X-Requested-With');
1374 $this->assertFalse($request->isXmlHttpRequest());
1378 * @requires extension intl
1380 public function testIntlLocale()
1382 $request = new Request();
1384 $request->setDefaultLocale('fr');
1385 $this->assertEquals('fr', $request->getLocale());
1386 $this->assertEquals('fr', \Locale::getDefault());
1388 $request->setLocale('en');
1389 $this->assertEquals('en', $request->getLocale());
1390 $this->assertEquals('en', \Locale::getDefault());
1392 $request->setDefaultLocale('de');
1393 $this->assertEquals('en', $request->getLocale());
1394 $this->assertEquals('en', \Locale::getDefault());
1397 public function testGetCharsets()
1399 $request = new Request();
1400 $this->assertEquals(array(), $request->getCharsets());
1401 $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6');
1402 $this->assertEquals(array(), $request->getCharsets()); // testing caching
1404 $request = new Request();
1405 $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6');
1406 $this->assertEquals(array('ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'), $request->getCharsets());
1408 $request = new Request();
1409 $request->headers->set('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7');
1410 $this->assertEquals(array('ISO-8859-1', 'utf-8', '*'), $request->getCharsets());
1413 public function testGetEncodings()
1415 $request = new Request();
1416 $this->assertEquals(array(), $request->getEncodings());
1417 $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch');
1418 $this->assertEquals(array(), $request->getEncodings()); // testing caching
1420 $request = new Request();
1421 $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch');
1422 $this->assertEquals(array('gzip', 'deflate', 'sdch'), $request->getEncodings());
1424 $request = new Request();
1425 $request->headers->set('Accept-Encoding', 'gzip;q=0.4,deflate;q=0.9,compress;q=0.7');
1426 $this->assertEquals(array('deflate', 'compress', 'gzip'), $request->getEncodings());
1429 public function testGetAcceptableContentTypes()
1431 $request = new Request();
1432 $this->assertEquals(array(), $request->getAcceptableContentTypes());
1433 $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*');
1434 $this->assertEquals(array(), $request->getAcceptableContentTypes()); // testing caching
1436 $request = new Request();
1437 $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*');
1438 $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());
1441 public function testGetLanguages()
1443 $request = new Request();
1444 $this->assertEquals(array(), $request->getLanguages());
1446 $request = new Request();
1447 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
1448 $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages());
1449 $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages());
1451 $request = new Request();
1452 $request->headers->set('Accept-language', 'zh, en-us; q=0.6, en; q=0.8');
1453 $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test out of order qvalues
1455 $request = new Request();
1456 $request->headers->set('Accept-language', 'zh, en, en-us');
1457 $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test equal weighting without qvalues
1459 $request = new Request();
1460 $request->headers->set('Accept-language', 'zh; q=0.6, en, en-us; q=0.6');
1461 $this->assertEquals(array('en', 'zh', 'en_US'), $request->getLanguages()); // Test equal weighting with qvalues
1463 $request = new Request();
1464 $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6');
1465 $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages());
1468 public function testGetRequestFormat()
1470 $request = new Request();
1471 $this->assertEquals('html', $request->getRequestFormat());
1473 // Ensure that setting different default values over time is possible,
1474 // aka. setRequestFormat determines the state.
1475 $this->assertEquals('json', $request->getRequestFormat('json'));
1476 $this->assertEquals('html', $request->getRequestFormat('html'));
1478 $request = new Request();
1479 $this->assertNull($request->getRequestFormat(null));
1481 $request = new Request();
1482 $this->assertNull($request->setRequestFormat('foo'));
1483 $this->assertEquals('foo', $request->getRequestFormat(null));
1485 $request = new Request(array('_format' => 'foo'));
1486 $this->assertEquals('html', $request->getRequestFormat());
1489 public function testHasSession()
1491 $request = new Request();
1493 $this->assertFalse($request->hasSession());
1494 $request->setSession(new Session(new MockArraySessionStorage()));
1495 $this->assertTrue($request->hasSession());
1498 public function testGetSession()
1500 $request = new Request();
1502 $request->setSession(new Session(new MockArraySessionStorage()));
1503 $this->assertTrue($request->hasSession());
1505 $session = $request->getSession();
1506 $this->assertObjectHasAttribute('storage', $session);
1507 $this->assertObjectHasAttribute('flashName', $session);
1508 $this->assertObjectHasAttribute('attributeName', $session);
1511 public function testHasPreviousSession()
1513 $request = new Request();
1515 $this->assertFalse($request->hasPreviousSession());
1516 $request->cookies->set('MOCKSESSID', 'foo');
1517 $this->assertFalse($request->hasPreviousSession());
1518 $request->setSession(new Session(new MockArraySessionStorage()));
1519 $this->assertTrue($request->hasPreviousSession());
1522 public function testToString()
1524 $request = new Request();
1526 $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
1527 $request->cookies->set('Foo', 'Bar');
1529 $asString = (string) $request;
1531 $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString);
1532 $this->assertContains('Cookie: Foo=Bar', $asString);
1534 $request->cookies->set('Another', 'Cookie');
1536 $asString = (string) $request;
1538 $this->assertContains('Cookie: Foo=Bar; Another=Cookie', $asString);
1541 public function testIsMethod()
1543 $request = new Request();
1544 $request->setMethod('POST');
1545 $this->assertTrue($request->isMethod('POST'));
1546 $this->assertTrue($request->isMethod('post'));
1547 $this->assertFalse($request->isMethod('GET'));
1548 $this->assertFalse($request->isMethod('get'));
1550 $request->setMethod('GET');
1551 $this->assertTrue($request->isMethod('GET'));
1552 $this->assertTrue($request->isMethod('get'));
1553 $this->assertFalse($request->isMethod('POST'));
1554 $this->assertFalse($request->isMethod('post'));
1558 * @dataProvider getBaseUrlData
1560 public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo)
1562 $request = Request::create($uri, 'GET', array(), array(), array(), $server);
1564 $this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl');
1565 $this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo');
1568 public function getBaseUrlData()
1572 '/fruit/strawberry/1234index.php/blah',
1574 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/fruit/index.php',
1575 'SCRIPT_NAME' => '/fruit/index.php',
1576 'PHP_SELF' => '/fruit/index.php',
1579 '/strawberry/1234index.php/blah',
1582 '/fruit/strawberry/1234index.php/blah',
1584 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/index.php',
1585 'SCRIPT_NAME' => '/index.php',
1586 'PHP_SELF' => '/index.php',
1589 '/fruit/strawberry/1234index.php/blah',
1594 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
1595 'SCRIPT_NAME' => '/foo bar/app.php',
1596 'PHP_SELF' => '/foo bar/app.php',
1604 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
1605 'SCRIPT_NAME' => '/foo bar/app.php',
1606 'PHP_SELF' => '/foo bar/app.php',
1612 '/foo%20bar/app.php/home',
1614 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
1615 'SCRIPT_NAME' => '/foo bar/app.php',
1616 'PHP_SELF' => '/foo bar/app.php',
1618 '/foo%20bar/app.php',
1622 '/foo%20bar/app.php/home%3Dbaz',
1624 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
1625 'SCRIPT_NAME' => '/foo bar/app.php',
1626 'PHP_SELF' => '/foo bar/app.php',
1628 '/foo%20bar/app.php',
1634 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php',
1635 'SCRIPT_NAME' => '/foo/app.php',
1636 'PHP_SELF' => '/foo/app.php',
1645 * @dataProvider urlencodedStringPrefixData
1647 public function testUrlencodedStringPrefix($string, $prefix, $expect)
1649 $request = new Request();
1651 $me = new \ReflectionMethod($request, 'getUrlencodedPrefix');
1652 $me->setAccessible(true);
1654 $this->assertSame($expect, $me->invoke($request, $string, $prefix));
1657 public function urlencodedStringPrefixData()
1660 array('foo', 'foo', 'foo'),
1661 array('fo%6f', 'foo', 'fo%6f'),
1662 array('foo/bar', 'foo', 'foo'),
1663 array('fo%6f/bar', 'foo', 'fo%6f'),
1664 array('f%6f%6f/bar', 'foo', 'f%6f%6f'),
1665 array('%66%6F%6F/bar', 'foo', '%66%6F%6F'),
1666 array('fo+o/bar', 'fo+o', 'fo+o'),
1667 array('fo%2Bo/bar', 'fo+o', 'fo%2Bo'),
1671 private function disableHttpMethodParameterOverride()
1673 $class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request');
1674 $property = $class->getProperty('httpMethodParameterOverride');
1675 $property->setAccessible(true);
1676 $property->setValue(false);
1679 private function getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies)
1681 $request = new Request();
1683 $server = array('REMOTE_ADDR' => $remoteAddr);
1684 if (null !== $httpForwardedFor) {
1685 $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor;
1688 if ($trustedProxies) {
1689 Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL);
1692 $request->initialize(array(), array(), array(), array(), array(), $server);
1697 private function getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies)
1699 $request = new Request();
1701 $server = array('REMOTE_ADDR' => $remoteAddr);
1703 if (null !== $httpForwarded) {
1704 $server['HTTP_FORWARDED'] = $httpForwarded;
1707 if ($trustedProxies) {
1708 Request::setTrustedProxies($trustedProxies, Request::HEADER_FORWARDED);
1711 $request->initialize(array(), array(), array(), array(), array(), $server);
1716 public function testTrustedProxiesXForwardedFor()
1718 $request = Request::create('http://example.com/');
1719 $request->server->set('REMOTE_ADDR', '3.3.3.3');
1720 $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2');
1721 $request->headers->set('X_FORWARDED_HOST', 'foo.example.com:1234, real.example.com:8080');
1722 $request->headers->set('X_FORWARDED_PROTO', 'https');
1723 $request->headers->set('X_FORWARDED_PORT', 443);
1725 // no trusted proxies
1726 $this->assertEquals('3.3.3.3', $request->getClientIp());
1727 $this->assertEquals('example.com', $request->getHost());
1728 $this->assertEquals(80, $request->getPort());
1729 $this->assertFalse($request->isSecure());
1731 // disabling proxy trusting
1732 Request::setTrustedProxies(array(), Request::HEADER_X_FORWARDED_ALL);
1733 $this->assertEquals('3.3.3.3', $request->getClientIp());
1734 $this->assertEquals('example.com', $request->getHost());
1735 $this->assertEquals(80, $request->getPort());
1736 $this->assertFalse($request->isSecure());
1738 // request is forwarded by a non-trusted proxy
1739 Request::setTrustedProxies(array('2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
1740 $this->assertEquals('3.3.3.3', $request->getClientIp());
1741 $this->assertEquals('example.com', $request->getHost());
1742 $this->assertEquals(80, $request->getPort());
1743 $this->assertFalse($request->isSecure());
1745 // trusted proxy via setTrustedProxies()
1746 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
1747 $this->assertEquals('1.1.1.1', $request->getClientIp());
1748 $this->assertEquals('foo.example.com', $request->getHost());
1749 $this->assertEquals(443, $request->getPort());
1750 $this->assertTrue($request->isSecure());
1752 // trusted proxy via setTrustedProxies()
1753 Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
1754 $this->assertEquals('3.3.3.3', $request->getClientIp());
1755 $this->assertEquals('example.com', $request->getHost());
1756 $this->assertEquals(80, $request->getPort());
1757 $this->assertFalse($request->isSecure());
1759 // check various X_FORWARDED_PROTO header values
1760 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
1761 $request->headers->set('X_FORWARDED_PROTO', 'ssl');
1762 $this->assertTrue($request->isSecure());
1764 $request->headers->set('X_FORWARDED_PROTO', 'https, http');
1765 $this->assertTrue($request->isSecure());
1770 * @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.
1772 public function testLegacyTrustedProxies()
1774 $request = Request::create('http://example.com/');
1775 $request->server->set('REMOTE_ADDR', '3.3.3.3');
1776 $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2');
1777 $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080');
1778 $request->headers->set('X_FORWARDED_PROTO', 'https');
1779 $request->headers->set('X_FORWARDED_PORT', 443);
1780 $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4');
1781 $request->headers->set('X_MY_HOST', 'my.example.com');
1782 $request->headers->set('X_MY_PROTO', 'http');
1783 $request->headers->set('X_MY_PORT', 81);
1785 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
1787 // custom header names
1788 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_MY_FOR');
1789 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_MY_HOST');
1790 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_MY_PORT');
1791 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_MY_PROTO');
1792 $this->assertEquals('4.4.4.4', $request->getClientIp());
1793 $this->assertEquals('my.example.com', $request->getHost());
1794 $this->assertEquals(81, $request->getPort());
1795 $this->assertFalse($request->isSecure());
1797 // disabling via empty header names
1798 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, null);
1799 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null);
1800 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, null);
1801 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, null);
1802 $this->assertEquals('3.3.3.3', $request->getClientIp());
1803 $this->assertEquals('example.com', $request->getHost());
1804 $this->assertEquals(80, $request->getPort());
1805 $this->assertFalse($request->isSecure());
1808 Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED');
1809 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR');
1810 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST');
1811 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT');
1812 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO');
1815 public function testTrustedProxiesForwarded()
1817 $request = Request::create('http://example.com/');
1818 $request->server->set('REMOTE_ADDR', '3.3.3.3');
1819 $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');
1821 // no trusted proxies
1822 $this->assertEquals('3.3.3.3', $request->getClientIp());
1823 $this->assertEquals('example.com', $request->getHost());
1824 $this->assertEquals(80, $request->getPort());
1825 $this->assertFalse($request->isSecure());
1827 // disabling proxy trusting
1828 Request::setTrustedProxies(array(), Request::HEADER_FORWARDED);
1829 $this->assertEquals('3.3.3.3', $request->getClientIp());
1830 $this->assertEquals('example.com', $request->getHost());
1831 $this->assertEquals(80, $request->getPort());
1832 $this->assertFalse($request->isSecure());
1834 // request is forwarded by a non-trusted proxy
1835 Request::setTrustedProxies(array('2.2.2.2'), Request::HEADER_FORWARDED);
1836 $this->assertEquals('3.3.3.3', $request->getClientIp());
1837 $this->assertEquals('example.com', $request->getHost());
1838 $this->assertEquals(80, $request->getPort());
1839 $this->assertFalse($request->isSecure());
1841 // trusted proxy via setTrustedProxies()
1842 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_FORWARDED);
1843 $this->assertEquals('1.1.1.1', $request->getClientIp());
1844 $this->assertEquals('foo.example.com', $request->getHost());
1845 $this->assertEquals(8080, $request->getPort());
1846 $this->assertTrue($request->isSecure());
1848 // trusted proxy via setTrustedProxies()
1849 Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'), Request::HEADER_FORWARDED);
1850 $this->assertEquals('3.3.3.3', $request->getClientIp());
1851 $this->assertEquals('example.com', $request->getHost());
1852 $this->assertEquals(80, $request->getPort());
1853 $this->assertFalse($request->isSecure());
1855 // check various X_FORWARDED_PROTO header values
1856 Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_FORWARDED);
1857 $request->headers->set('FORWARDED', 'proto=ssl');
1858 $this->assertTrue($request->isSecure());
1860 $request->headers->set('FORWARDED', 'proto=https, proto=http');
1861 $this->assertTrue($request->isSecure());
1866 * @expectedException \InvalidArgumentException
1868 public function testSetTrustedProxiesInvalidHeaderName()
1870 Request::create('http://example.com/');
1871 Request::setTrustedHeaderName('bogus name', 'X_MY_FOR');
1876 * @expectedException \InvalidArgumentException
1878 public function testGetTrustedProxiesInvalidHeaderName()
1880 Request::create('http://example.com/');
1881 Request::getTrustedHeaderName('bogus name');
1885 * @dataProvider iisRequestUriProvider
1887 public function testIISRequestUri($headers, $server, $expectedRequestUri)
1889 $request = new Request();
1890 $request->headers->replace($headers);
1891 $request->server->replace($server);
1893 $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct');
1895 $subRequestUri = '/bar/foo';
1896 $subRequest = Request::create($subRequestUri, 'get', array(), array(), array(), $request->server->all());
1897 $this->assertEquals($subRequestUri, $subRequest->getRequestUri(), '->getRequestUri() is correct in sub request');
1900 public function iisRequestUriProvider()
1905 'X_ORIGINAL_URL' => '/foo/bar',
1912 'X_REWRITE_URL' => '/foo/bar',
1920 'IIS_WasUrlRewritten' => '1',
1921 'UNENCODED_URL' => '/foo/bar',
1927 'X_ORIGINAL_URL' => '/foo/bar',
1930 'HTTP_X_ORIGINAL_URL' => '/foo/bar',
1936 'X_ORIGINAL_URL' => '/foo/bar',
1939 'IIS_WasUrlRewritten' => '1',
1940 'UNENCODED_URL' => '/foo/bar',
1946 'X_ORIGINAL_URL' => '/foo/bar',
1949 'HTTP_X_ORIGINAL_URL' => '/foo/bar',
1950 'IIS_WasUrlRewritten' => '1',
1951 'UNENCODED_URL' => '/foo/bar',
1958 'ORIG_PATH_INFO' => '/foo/bar',
1965 'ORIG_PATH_INFO' => '/foo/bar',
1966 'QUERY_STRING' => 'foo=bar',
1973 public function testTrustedHosts()
1976 $request = Request::create('/');
1978 // no trusted host set -> no host check
1979 $request->headers->set('host', 'evil.com');
1980 $this->assertEquals('evil.com', $request->getHost());
1982 // add a trusted domain and all its subdomains
1983 Request::setTrustedHosts(array('^([a-z]{9}\.)?trusted\.com$'));
1986 $request->headers->set('host', 'evil.com');
1988 $request->getHost();
1989 $this->fail('Request::getHost() should throw an exception when host is not trusted.');
1990 } catch (SuspiciousOperationException $e) {
1991 $this->assertEquals('Untrusted Host "evil.com".', $e->getMessage());
1995 $request->headers->set('host', 'trusted.com');
1996 $this->assertEquals('trusted.com', $request->getHost());
1997 $this->assertEquals(80, $request->getPort());
1999 $request->server->set('HTTPS', true);
2000 $request->headers->set('host', 'trusted.com');
2001 $this->assertEquals('trusted.com', $request->getHost());
2002 $this->assertEquals(443, $request->getPort());
2003 $request->server->set('HTTPS', false);
2005 $request->headers->set('host', 'trusted.com:8000');
2006 $this->assertEquals('trusted.com', $request->getHost());
2007 $this->assertEquals(8000, $request->getPort());
2009 $request->headers->set('host', 'subdomain.trusted.com');
2010 $this->assertEquals('subdomain.trusted.com', $request->getHost());
2013 public function testSetTrustedHostsDoesNotBreakOnSpecialCharacters()
2015 Request::setTrustedHosts(array('localhost(\.local){0,1}#,example.com', 'localhost'));
2017 $request = Request::create('/');
2018 $request->headers->set('host', 'localhost');
2019 $this->assertSame('localhost', $request->getHost());
2022 public function testFactory()
2024 Request::setFactory(function (array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) {
2025 return new NewRequest();
2028 $this->assertEquals('foo', Request::create('/')->getFoo());
2030 Request::setFactory(null);
2034 * @dataProvider getLongHostNames
2036 public function testVeryLongHosts($host)
2038 $start = microtime(true);
2040 $request = Request::create('/');
2041 $request->headers->set('host', $host);
2042 $this->assertEquals($host, $request->getHost());
2043 $this->assertLessThan(5, microtime(true) - $start);
2047 * @dataProvider getHostValidities
2049 public function testHostValidity($host, $isValid, $expectedHost = null, $expectedPort = null)
2051 $request = Request::create('/');
2052 $request->headers->set('host', $host);
2055 $this->assertSame($expectedHost ?: $host, $request->getHost());
2056 if ($expectedPort) {
2057 $this->assertSame($expectedPort, $request->getPort());
2060 if (method_exists($this, 'expectException')) {
2061 $this->expectException(SuspiciousOperationException::class);
2062 $this->expectExceptionMessage('Invalid Host');
2064 $this->setExpectedException(SuspiciousOperationException::class, 'Invalid Host');
2067 $request->getHost();
2071 public function getHostValidities()
2075 array('a..', false),
2077 array("\xE9", false),
2078 array('[::1]', true),
2079 array('[::1]:80', true, '[::1]', 80),
2080 array(str_repeat('.', 101), false),
2084 public function getLongHostNames()
2087 array('a'.str_repeat('.a', 40000)),
2088 array(str_repeat(':', 101)),
2093 * @dataProvider methodIdempotentProvider
2095 public function testMethodIdempotent($method, $idempotent)
2097 $request = new Request();
2098 $request->setMethod($method);
2099 $this->assertEquals($idempotent, $request->isMethodIdempotent());
2102 public function methodIdempotentProvider()
2105 array('HEAD', true),
2107 array('POST', false),
2109 array('PATCH', false),
2110 array('DELETE', true),
2111 array('PURGE', true),
2112 array('OPTIONS', true),
2113 array('TRACE', true),
2114 array('CONNECT', false),
2119 * @dataProvider methodSafeProvider
2121 public function testMethodSafe($method, $safe)
2123 $request = new Request();
2124 $request->setMethod($method);
2125 $this->assertEquals($safe, $request->isMethodSafe(false));
2128 public function methodSafeProvider()
2131 array('HEAD', true),
2133 array('POST', false),
2134 array('PUT', false),
2135 array('PATCH', false),
2136 array('DELETE', false),
2137 array('PURGE', false),
2138 array('OPTIONS', true),
2139 array('TRACE', true),
2140 array('CONNECT', false),
2146 * @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.
2148 public function testMethodSafeChecksCacheable()
2150 $request = new Request();
2151 $request->setMethod('OPTIONS');
2152 $this->assertFalse($request->isMethodSafe());
2156 * @dataProvider methodCacheableProvider
2158 public function testMethodCacheable($method, $cacheable)
2160 $request = new Request();
2161 $request->setMethod($method);
2162 $this->assertEquals($cacheable, $request->isMethodCacheable());
2165 public function methodCacheableProvider()
2168 array('HEAD', true),
2170 array('POST', false),
2171 array('PUT', false),
2172 array('PATCH', false),
2173 array('DELETE', false),
2174 array('PURGE', false),
2175 array('OPTIONS', false),
2176 array('TRACE', false),
2177 array('CONNECT', false),
2184 public function testGetTrustedHeaderName()
2186 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL);
2188 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
2189 $this->assertSame('X_FORWARDED_FOR', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP));
2190 $this->assertSame('X_FORWARDED_HOST', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST));
2191 $this->assertSame('X_FORWARDED_PORT', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT));
2192 $this->assertSame('X_FORWARDED_PROTO', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO));
2194 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
2196 $this->assertSame('FORWARDED', Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
2197 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP));
2198 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST));
2199 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT));
2200 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO));
2202 Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'A');
2203 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'B');
2204 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'C');
2205 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'D');
2206 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'E');
2208 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
2210 $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
2211 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP));
2212 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST));
2213 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT));
2214 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO));
2216 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL);
2218 $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
2219 $this->assertSame('B', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP));
2220 $this->assertSame('C', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST));
2221 $this->assertSame('D', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT));
2222 $this->assertSame('E', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO));
2224 Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
2226 $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
2229 Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED');
2230 Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR');
2231 Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST');
2232 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT');
2233 Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO');
2237 * @dataProvider protocolVersionProvider
2239 public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expected)
2241 if ($trustedProxy) {
2242 Request::setTrustedProxies(array('1.1.1.1'), -1);
2245 $request = new Request();
2246 $request->server->set('SERVER_PROTOCOL', $serverProtocol);
2247 $request->server->set('REMOTE_ADDR', '1.1.1.1');
2248 $request->headers->set('Via', $via);
2250 $this->assertSame($expected, $request->getProtocolVersion());
2253 public function protocolVersionProvider()
2256 'untrusted without via' => array('HTTP/2.0', false, '', 'HTTP/2.0'),
2257 'untrusted with via' => array('HTTP/2.0', false, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/2.0'),
2258 'trusted without via' => array('HTTP/2.0', true, '', 'HTTP/2.0'),
2259 'trusted with via' => array('HTTP/2.0', true, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'),
2260 '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'),
2261 'trusted with broken via' => array('HTTP/2.0', true, 'HTTP/1^0 foo', 'HTTP/2.0'),
2262 'trusted with partially-broken via' => array('HTTP/2.0', true, '1.0 fred, foo', 'HTTP/1.0'),
2266 public function nonstandardRequestsData()
2269 array('', '', '/', 'http://host:8080/', ''),
2270 array('/', '', '/', 'http://host:8080/', ''),
2272 array('hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'),
2273 array('/hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'),
2275 array('', 'a=b', '/', 'http://host:8080/?a=b'),
2276 array('?a=b', 'a=b', '/', 'http://host:8080/?a=b'),
2277 array('/?a=b', 'a=b', '/', 'http://host:8080/?a=b'),
2279 array('x', 'a=b', '/x', 'http://host:8080/x?a=b'),
2280 array('x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'),
2281 array('/x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'),
2283 array('hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
2284 array('/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
2286 array('hello/app.php/x', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
2287 array('hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
2288 array('/hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
2293 * @dataProvider nonstandardRequestsData
2295 public function testNonstandardRequests($requestUri, $queryString, $expectedPathInfo, $expectedUri, $expectedBasePath = '', $expectedBaseUrl = null)
2297 if (null === $expectedBaseUrl) {
2298 $expectedBaseUrl = $expectedBasePath;
2302 'HTTP_HOST' => 'host:8080',
2303 'SERVER_PORT' => '8080',
2304 'QUERY_STRING' => $queryString,
2305 'PHP_SELF' => '/hello/app.php',
2306 'SCRIPT_FILENAME' => '/some/path/app.php',
2307 'REQUEST_URI' => $requestUri,
2310 $request = new Request(array(), array(), array(), array(), array(), $server);
2312 $this->assertEquals($expectedPathInfo, $request->getPathInfo());
2313 $this->assertEquals($expectedUri, $request->getUri());
2314 $this->assertEquals($queryString, $request->getQueryString());
2315 $this->assertEquals(8080, $request->getPort());
2316 $this->assertEquals('host:8080', $request->getHttpHost());
2317 $this->assertEquals($expectedBaseUrl, $request->getBaseUrl());
2318 $this->assertEquals($expectedBasePath, $request->getBasePath());
2322 class RequestContentProxy extends Request
2324 public function getContent($asResource = false)
2326 return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent'), '', '&');
2330 class NewRequest extends Request
2332 public function getFoo()