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