‪TYPO3CMS  ‪main
RequestTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
22 use Psr\Http\Message\StreamInterface;
26 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
27 
33 final class ‪RequestTest extends UnitTestCase
34 {
35  protected ?‪Request ‪$request;
36 
37  protected function ‪setUp(): void
38  {
39  parent::setUp();
40  $this->request = new ‪Request();
41  }
42 
43  #[Test]
44  public function ‪getMethodIsGetByDefault(): void
45  {
46  self::assertEquals('GET', $this->request->getMethod());
47  }
48 
49  #[Test]
51  {
52  ‪$request = $this->request->‪withMethod('GET');
53  self::assertNotSame($this->request, ‪$request);
54  self::assertEquals('GET', ‪$request->‪getMethod());
55  }
56 
57  #[Test]
59  {
60  ‪$request = $this->request->‪withUri(new ‪Uri('https://example.com:10082/foo/bar?baz=bat'));
61  self::assertNotSame($this->request, ‪$request);
62  $request2 = ‪$request->‪withUri(new ‪Uri('/baz/bat?foo=bar'));
63  self::assertNotSame($this->request, $request2);
64  self::assertNotSame(‪$request, $request2);
65  self::assertEquals('/baz/bat?foo=bar', (string)$request2->getUri());
66  }
67 
68  #[Test]
70  {
71  $uri = new ‪Uri('http://example.com/');
72  $body = new ‪Stream('php://memory');
73  $headers = [
74  'x-foo' => ['bar'],
75  ];
76  ‪$request = new ‪Request(
77  $uri,
78  'POST',
79  $body,
80  $headers
81  );
82 
83  self::assertSame($uri, ‪$request->‪getUri());
84  self::assertEquals('POST', ‪$request->‪getMethod());
85  self::assertSame($body, ‪$request->‪getBody());
86  $testHeaders = ‪$request->‪getHeaders();
87  foreach ($headers as $key => $value) {
88  self::assertArrayHasKey($key, $testHeaders);
89  self::assertEquals($value, $testHeaders[$key]);
90  }
91  }
92 
93  #[Test]
95  {
96  $this->expectException(\InvalidArgumentException::class);
97  $this->expectExceptionCode(1436717275);
98  new ‪Request(null, 'BOGUS-METHOD');
99  }
100 
101  public static function ‪invalidRequestBodyDataProvider(): array
102  {
103  return [
104  'true' => [true],
105  'false' => [false],
106  'int' => [1],
107  'float' => [1.1],
108  'array' => [['BODY']],
109  'stdClass' => [(object)['body' => 'BODY']],
110  ];
111  }
112 
113  #[DataProvider('invalidRequestBodyDataProvider')]
114  #[Test]
115  public function ‪constructorRaisesExceptionForInvalidBody($body): void
116  {
117  $this->expectException(\InvalidArgumentException::class);
118  $this->expectExceptionCode(1436717271);
119  new ‪Request(null, 'GET', $body);
120  }
121 
122  public static function ‪validRequestBodyDataProvider(): array
123  {
124  return [
125  'stringResourceIdentifier' => ['php://input'],
126  'streamResource' => [fopen('php://memory', 'r')],
127  'streamInterface' => [new ‪Stream(fopen('php://memory', 'r'))],
128  'null' => [null],
129  ];
130  }
131 
135  #[DataProvider('validRequestBodyDataProvider')]
136  #[Test]
138  {
139  new ‪Request(null, 'GET', $body);
140  }
141 
142  #[Test]
143  public function ‪constructorIgnoresInvalidHeaders(): void
144  {
145  $headers = [
146  ['INVALID'],
147  'x-invalid-null' => null,
148  'x-invalid-object' => (object)['INVALID'],
149  'x-valid-true' => true,
150  'x-valid-false' => false,
151  'x-valid-int' => 1,
152  'x-valid-float' => 1.5,
153  'x-valid-string' => 'VALID',
154  'x-valid-array' => ['VALID'],
155  ];
156  $expected = [
157  'x-valid-true' => ['1'],
158  'x-valid-false' => [''],
159  'x-valid-int' => ['1'],
160  'x-valid-float' => ['1.5'],
161  'x-valid-string' => ['VALID'],
162  'x-valid-array' => ['VALID'],
163  ];
164  ‪$request = new ‪Request(null, 'GET', 'php://memory', $headers);
165  self::assertEquals($expected, ‪$request->‪getHeaders());
166  }
167 
168  #[Test]
170  {
171  ‪$request = new ‪Request();
172  self::assertEquals('/', ‪$request->‪getRequestTarget());
173  }
174 
175  #[Test]
177  {
178  ‪$request = (new ‪Request())
179  ->withUri(new ‪Uri('http://example.com'));
180  self::assertEquals('/', ‪$request->‪getRequestTarget());
181  }
182 
183  public static function ‪requestsWithUriDataProvider(): array
184  {
185  return [
186  'absolute-uri' => [
187  (new ‪Request())
188  ->withUri(new ‪Uri('https://api.example.com/user'))
189  ->withMethod('POST'),
190  '/user',
191  ],
192  'absolute-uri-with-query' => [
193  (new ‪Request())
194  ->withUri(new ‪Uri('https://api.example.com/user?foo=bar'))
195  ->withMethod('POST'),
196  '/user?foo=bar',
197  ],
198  'relative-uri' => [
199  (new ‪Request())
200  ->withUri(new ‪Uri('/user'))
201  ->withMethod('GET'),
202  '/user',
203  ],
204  'relative-uri-with-query' => [
205  (new ‪Request())
206  ->withUri(new ‪Uri('/user?foo=bar'))
207  ->withMethod('GET'),
208  '/user?foo=bar',
209  ],
210  ];
211  }
212 
213  #[DataProvider('requestsWithUriDataProvider')]
214  #[Test]
215  public function ‪getRequestTargetWhenUriIsPresent(‪$request, $expected): void
216  {
217  self::assertEquals($expected, ‪$request->‪getRequestTarget());
218  }
219 
220  public static function ‪validRequestTargetsDataProvider(): array
221  {
222  return [
223  'asterisk-form' => ['*'],
224  'authority-form' => ['api.example.com'],
225  'absolute-form' => ['https://api.example.com/users'],
226  'absolute-form-query' => ['https://api.example.com/users?foo=bar'],
227  'origin-form-path-only' => ['/users'],
228  'origin-form' => ['/users?id=foo'],
229  ];
230  }
231 
232  #[DataProvider('validRequestTargetsDataProvider')]
233  #[Test]
234  public function ‪getRequestTargetCanProvideARequestTarget($requestTarget): void
235  {
236  ‪$request = (new ‪Request())->withRequestTarget($requestTarget);
237  self::assertEquals($requestTarget, ‪$request->‪getRequestTarget());
238  }
239 
240  #[Test]
242  {
243  ‪$request = new ‪Request();
244  $this->expectException(\InvalidArgumentException::class);
245  $this->expectExceptionCode(1436717273);
246  ‪$request->‪withRequestTarget('foo bar baz');
247  }
248 
249  #[Test]
251  {
252  ‪$request = (new ‪Request())->withUri(new ‪Uri('https://example.com/foo/bar'));
253  $original = ‪$request->‪getRequestTarget();
254  $newRequest = ‪$request->‪withUri(new ‪Uri('http://mwop.net/bar/baz'));
255  self::assertNotEquals($original, $newRequest->getRequestTarget());
256  }
257 
258  #[Test]
259  public function ‪getRequestTargetIsResetWithNewUri(): void
260  {
261  ‪$request = (new ‪Request())->withUri(new ‪Uri('https://example.com/foo/bar'));
263  ‪$request->‪withUri(new ‪Uri('http://mwop.net/bar/baz'));
264  }
265 
266  #[Test]
268  {
269  ‪$request = new ‪Request('http://example.com');
270  $headers = ‪$request->‪getHeaders();
271  self::assertArrayHasKey('host', $headers);
272  self::assertContains('example.com', $headers['host']);
273  }
274 
275  #[Test]
277  {
278  ‪$request = new ‪Request();
279  $headers = ‪$request->‪getHeaders();
280  self::assertArrayNotHasKey('host', $headers);
281  }
282 
283  #[Test]
285  {
286  ‪$request = new ‪Request(new ‪Uri());
287  $headers = ‪$request->‪getHeaders();
288  self::assertArrayNotHasKey('host', $headers);
289  }
290 
291  #[Test]
293  {
294  ‪$request = new ‪Request('http://example.com');
295  $header = ‪$request->‪getHeader('host');
296  self::assertEquals(['example.com'], $header);
297  }
298 
299  #[Test]
301  {
302  ‪$request = new ‪Request();
303  self::assertSame([], ‪$request->‪getHeader('host'));
304  }
305 
306  #[Test]
308  {
309  ‪$request = new ‪Request(new ‪Uri());
310  self::assertSame([], ‪$request->‪getHeader('host'));
311  }
312 
313  #[Test]
315  {
316  ‪$request = new ‪Request('http://example.com');
317  $header = ‪$request->‪getHeaderLine('host');
318  self::assertStringContainsString('example.com', $header);
319  }
320 
321  #[Test]
323  {
324  ‪$request = new ‪Request();
325  self::assertSame('', ‪$request->‪getHeaderLine('host'));
326  }
327 
328  #[Test]
330  {
331  ‪$request = new ‪Request(new ‪Uri());
332  self::assertSame('', ‪$request->‪getHeaderLine('host'));
333  }
334 
335  #[Test]
337  {
338  ‪$request = (new ‪Request())
339  ->withAddedHeader('Host', 'example.com');
340 
341  $uri = (new ‪Uri())->withHost('www.example.com');
342  $new = ‪$request->‪withUri($uri, true);
343 
344  self::assertEquals('example.com', $new->getHeaderLine('Host'));
345  }
346 
347  #[Test]
349  {
350  ‪$request = (new ‪Request())
351  ->withAddedHeader('Host', 'example.com');
352 
353  $uri = new ‪Uri();
354  $new = ‪$request->‪withUri($uri);
355 
356  self::assertEquals('example.com', $new->getHeaderLine('Host'));
357  }
358 
359  #[Test]
361  {
362  ‪$request = (new ‪Request())
363  ->withAddedHeader('Host', 'example.com');
364 
365  $uri = (new ‪Uri())
366  ->withHost('www.example.com')
367  ->withPort(10081);
368  $new = ‪$request->‪withUri($uri);
369 
370  self::assertEquals('www.example.com:10081', $new->getHeaderLine('Host'));
371  }
372 
374  {
375  // 'name' => [$headerName, $headerValue, $expectedValue]
376  return [
377  'Foo' => ['Foo', 'bar', 'bar'],
378  'foo' => ['foo', 'bar', 'bar'],
379  'Foo-with-array' => ['Foo', ['bar'], 'bar'],
380  'foo-with-array' => ['foo', ['bar'], 'bar'],
381  ];
382  }
383 
384  #[DataProvider('headersWithUpperAndLowerCaseValuesDataProvider')]
385  #[Test]
386  public function ‪headerCanBeRetrieved($header, $value, $expected): void
387  {
388  ‪$request = new ‪Request(null, 'GET', 'php://memory', [$header => $value]);
389  self::assertEquals([$expected], ‪$request->‪getHeader(strtolower($header)));
390  self::assertEquals([$expected], ‪$request->‪getHeader(strtoupper($header)));
391  }
392 
393  public static function ‪headersWithInjectionVectorsDataProvider(): array
394  {
395  return [
396  'name-with-cr' => ["X-Foo\r-Bar", 'value'],
397  'name-with-lf' => ["X-Foo\n-Bar", 'value'],
398  'name-with-crlf' => ["X-Foo\r\n-Bar", 'value'],
399  'name-with-2crlf' => ["X-Foo\r\n\r\n-Bar", 'value'],
400  'value-with-cr' => ['X-Foo-Bar', "value\rinjection"],
401  'value-with-lf' => ['X-Foo-Bar', "value\ninjection"],
402  'value-with-crlf' => ['X-Foo-Bar', "value\r\ninjection"],
403  'value-with-2crlf' => ['X-Foo-Bar', "value\r\n\r\ninjection"],
404  'array-value-with-cr' => ['X-Foo-Bar', ["value\rinjection"]],
405  'array-value-with-lf' => ['X-Foo-Bar', ["value\ninjection"]],
406  'array-value-with-crlf' => ['X-Foo-Bar', ["value\r\ninjection"]],
407  'array-value-with-2crlf' => ['X-Foo-Bar', ["value\r\n\r\ninjection"]],
408  ];
409  }
410 
411  #[DataProvider('headersWithInjectionVectorsDataProvider')]
412  #[Test]
413  public function ‪constructorRaisesExceptionForHeadersWithCRLFVectors($name, $value): void
414  {
415  $this->expectException(\InvalidArgumentException::class);
416  new ‪Request(null, 'GET', 'php://memory', [$name => $value]);
417  }
418 
419  #[Test]
420  public function ‪supportedRequestMethodsWork(): void
421  {
422  ‪$request = new ‪Request('some-uri', 'PURGE');
423  self::assertEquals('PURGE', ‪$request->‪getMethod());
424  }
425 
426  #[Test]
428  {
429  $this->expectException(\InvalidArgumentException::class);
430  new ‪Request('some-uri', 'UNSUPPORTED');
431  }
432 }
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\setUp
‪setUp()
Definition: RequestTest.php:37
‪TYPO3\CMS\Core\Http\Message\getBody
‪StreamInterface getBody()
Definition: Message.php:287
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getRequestTargetIsResetWithNewUri
‪getRequestTargetIsResetWithNewUri()
Definition: RequestTest.php:259
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getRequestTargetIsSlashWhenUriHasNoPathOrQuery
‪getRequestTargetIsSlashWhenUriHasNoPathOrQuery()
Definition: RequestTest.php:176
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest
Definition: RequestTest.php:34
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeadersContainsNoHostHeaderIfUriDoesNotContainHost
‪getHeadersContainsNoHostHeaderIfUriDoesNotContainHost()
Definition: RequestTest.php:284
‪TYPO3\CMS\Core\Tests\Unit\Http
Definition: ApplicationTypeTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getMethodIsGetByDefault
‪getMethodIsGetByDefault()
Definition: RequestTest.php:44
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderLineWithHostDoesNotTakePrecedenceOverHostWithPortFromUri
‪getHeaderLineWithHostDoesNotTakePrecedenceOverHostWithPortFromUri()
Definition: RequestTest.php:360
‪TYPO3\CMS\Core\Http\Request\getRequestTarget
‪getRequestTarget()
Definition: Request.php:200
‪TYPO3\CMS\Core\Http\Message\getHeaderLine
‪string getHeaderLine(string $name)
Definition: Message.php:178
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderLineWithHostReturnsEmptyStringIfNoUriPresent
‪getHeaderLineWithHostReturnsEmptyStringIfNoUriPresent()
Definition: RequestTest.php:322
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\invalidRequestBodyDataProvider
‪static invalidRequestBodyDataProvider()
Definition: RequestTest.php:101
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\constructorCanAcceptAllMessageParts
‪constructorCanAcceptAllMessageParts()
Definition: RequestTest.php:69
‪TYPO3\CMS\Core\Http\Request\getUri
‪UriInterface getUri()
Definition: Request.php:285
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\validRequestTargetsDataProvider
‪static validRequestTargetsDataProvider()
Definition: RequestTest.php:220
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\constructorRaisesExceptionForInvalidMethodByString
‪constructorRaisesExceptionForInvalidMethodByString()
Definition: RequestTest.php:94
‪TYPO3\CMS\Core\Http\Request\withUri
‪withUri(UriInterface $uri, bool $preserveHost=false)
Definition: Request.php:320
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\requestsWithUriDataProvider
‪static requestsWithUriDataProvider()
Definition: RequestTest.php:183
‪TYPO3\CMS\Core\Http\Request\getMethod
‪getMethod()
Definition: Request.php:250
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:30
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\headersWithUpperAndLowerCaseValuesDataProvider
‪static headersWithUpperAndLowerCaseValuesDataProvider()
Definition: RequestTest.php:373
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\headerCanBeRetrieved
‪headerCanBeRetrieved($header, $value, $expected)
Definition: RequestTest.php:386
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderWithHostReturnsEmptyArrayIfNoUriPresent
‪getHeaderWithHostReturnsEmptyArrayIfNoUriPresent()
Definition: RequestTest.php:300
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getRequestTargetCanProvideARequestTarget
‪getRequestTargetCanProvideARequestTarget($requestTarget)
Definition: RequestTest.php:234
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\constructorRaisesExceptionForHeadersWithCRLFVectors
‪constructorRaisesExceptionForHeadersWithCRLFVectors($name, $value)
Definition: RequestTest.php:413
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\withRequestTargetCannotContainWhitespace
‪withRequestTargetCannotContainWhitespace()
Definition: RequestTest.php:241
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeadersContainsHostHeaderIfUriWithHostIsPresent
‪getHeadersContainsHostHeaderIfUriWithHostIsPresent()
Definition: RequestTest.php:267
‪TYPO3\CMS\Core\Http\Request\withRequestTarget
‪withRequestTarget(mixed $requestTarget)
Definition: Request.php:237
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeadersContainsNoHostHeaderIfNoUriPresent
‪getHeadersContainsNoHostHeaderIfNoUriPresent()
Definition: RequestTest.php:276
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\nonSupportedRequestMethodsRaisesException
‪nonSupportedRequestMethodsRaisesException()
Definition: RequestTest.php:427
‪TYPO3\CMS\Core\Http\Stream
Definition: Stream.php:31
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\supportedRequestMethodsWork
‪supportedRequestMethodsWork()
Definition: RequestTest.php:420
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\headersWithInjectionVectorsDataProvider
‪static headersWithInjectionVectorsDataProvider()
Definition: RequestTest.php:393
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getRequestTargetDoesNotCacheBetweenInstances
‪getRequestTargetDoesNotCacheBetweenInstances()
Definition: RequestTest.php:250
‪TYPO3\CMS\Core\Http\Request\getHeaders
‪array getHeaders()
Definition: Request.php:145
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getRequestTargetWhenUriIsPresent
‪getRequestTargetWhenUriIsPresent($request, $expected)
Definition: RequestTest.php:215
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\$request
‪Request $request
Definition: RequestTest.php:35
‪TYPO3\CMS\Core\Http\Request\withMethod
‪withMethod(string $method)
Definition: Request.php:269
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderLineWithHostReturnsEmptyStringIfUriDoesNotContainHost
‪getHeaderLineWithHostReturnsEmptyStringIfUriDoesNotContainHost()
Definition: RequestTest.php:329
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderWithHostReturnsUriHostWhenPresent
‪getHeaderWithHostReturnsUriHostWhenPresent()
Definition: RequestTest.php:292
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\constructorRaisesExceptionForInvalidBody
‪constructorRaisesExceptionForInvalidBody($body)
Definition: RequestTest.php:115
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderWithHostReturnsEmptyArrayIfUriDoesNotContainHost
‪getHeaderWithHostReturnsEmptyArrayIfUriDoesNotContainHost()
Definition: RequestTest.php:307
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderLineWithHostReturnsUriHostWhenPresent
‪getHeaderLineWithHostReturnsUriHostWhenPresent()
Definition: RequestTest.php:314
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderLineWithHostTakesPrecedenceOverModifiedUri
‪getHeaderLineWithHostTakesPrecedenceOverModifiedUri()
Definition: RequestTest.php:336
‪TYPO3\CMS\Core\Http\Request\getHeader
‪string[] getHeader(string $name)
Definition: Request.php:168
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\withUriReturnsNewInstanceWithNewUri
‪withUriReturnsNewInstanceWithNewUri()
Definition: RequestTest.php:58
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\constructorDoesNotRaiseExceptionForValidBody
‪constructorDoesNotRaiseExceptionForValidBody($body)
Definition: RequestTest.php:137
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\constructorIgnoresInvalidHeaders
‪constructorIgnoresInvalidHeaders()
Definition: RequestTest.php:143
‪TYPO3\CMS\Core\Http\Request
Definition: Request.php:35
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getRequestTargetIsSlashWhenNoUriPresent
‪getRequestTargetIsSlashWhenNoUriPresent()
Definition: RequestTest.php:169
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\validRequestBodyDataProvider
‪static validRequestBodyDataProvider()
Definition: RequestTest.php:122
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getMethodMutatorReturnsCloneWithChangedMethod
‪getMethodMutatorReturnsCloneWithChangedMethod()
Definition: RequestTest.php:50
‪TYPO3\CMS\Core\Tests\Unit\Http\RequestTest\getHeaderLineWithHostTakesPrecedenceOverEmptyUri
‪getHeaderLineWithHostTakesPrecedenceOverEmptyUri()
Definition: RequestTest.php:348