‪TYPO3CMS  ‪main
MessageTest.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;
24 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
25 
31 final class ‪MessageTest extends UnitTestCase
32 {
33  protected ?‪Stream ‪$stream;
34  protected ?‪Message ‪$message;
35 
36  protected function ‪setUp(): void
37  {
38  parent::setUp();
39  $this->stream = new ‪Stream('php://memory', 'wb+');
40  $this->message = (new ‪Message())->withBody($this->stream);
41  }
42 
43  #[Test]
44  public function ‪protocolHasAcceptableDefault(): void
45  {
46  self::assertEquals('1.1', $this->message->getProtocolVersion());
47  }
48 
49  #[Test]
51  {
52  ‪$message = $this->message->‪withProtocolVersion('1.0');
53  self::assertNotSame($this->message, ‪$message);
54  self::assertEquals('1.0', ‪$message->‪getProtocolVersion());
55  }
56 
57  #[Test]
59  {
60  self::assertSame($this->stream, $this->message->getBody());
61  }
62 
63  #[Test]
64  public function ‪bodyMutatorReturnsCloneWithChanges(): void
65  {
66  ‪$stream = new ‪Stream('php://memory', 'wb+');
67  ‪$message = $this->message->‪withBody(‪$stream);
68  self::assertNotSame($this->message, ‪$message);
69  self::assertSame(‪$stream, ‪$message->‪getBody());
70  }
71 
72  #[Test]
73  public function ‪getHeaderReturnsHeaderValueAsArray(): void
74  {
75  ‪$message = $this->message->‪withHeader('X-Foo', ['Foo', 'Bar']);
76  self::assertNotSame($this->message, ‪$message);
77  self::assertEquals(['Foo', 'Bar'], ‪$message->‪getHeader('X-Foo'));
78  }
79 
80  #[Test]
82  {
83  ‪$message = $this->message->‪withHeader('X-Foo', ['Foo', 'Bar']);
84  self::assertNotSame($this->message, ‪$message);
85  self::assertEquals('Foo,Bar', ‪$message->‪getHeaderLine('X-Foo'));
86  }
87 
88  #[Test]
90  {
91  ‪$message = $this->message->‪withHeader('X-Foo', ['Foo', 'Bar']);
92  self::assertNotSame($this->message, ‪$message);
93  self::assertEquals(['X-Foo' => ['Foo', 'Bar']], ‪$message->‪getHeaders());
94  }
95 
96  #[Test]
98  {
99  ‪$message = $this->message
100  ->‪withHeader('X-Foo', 'Foo')
101  ->withAddedHeader('x-foo', 'Bar');
102  self::assertNotSame($this->message, ‪$message);
103  self::assertEquals(['X-Foo' => ['Foo', 'Bar']], ‪$message->‪getHeaders());
104  }
105 
106  #[Test]
108  {
109  self::assertFalse($this->message->hasHeader('X-Foo'));
110  }
111 
112  #[Test]
114  {
115  ‪$message = $this->message->‪withHeader('X-Foo', 'Foo');
116  self::assertNotSame($this->message, ‪$message);
117  self::assertTrue(‪$message->‪hasHeader('X-Foo'));
118  }
119 
120  #[Test]
121  public function ‪addHeaderAppendsToExistingHeader(): void
122  {
123  ‪$message = $this->message->‪withHeader('X-Foo', 'Foo');
124  self::assertNotSame($this->message, ‪$message);
125  $message2 = ‪$message->‪withAddedHeader('X-Foo', 'Bar');
126  self::assertNotSame(‪$message, $message2);
127  self::assertEquals('Foo,Bar', $message2->getHeaderLine('X-Foo'));
128  }
129 
130  #[Test]
131  public function ‪canRemoveHeaders(): void
132  {
133  ‪$message = $this->message->‪withHeader('X-Foo', 'Foo');
134  self::assertNotSame($this->message, ‪$message);
135  self::assertTrue(‪$message->‪hasHeader('x-foo'));
136  $message2 = ‪$message->‪withoutHeader('x-foo');
137  self::assertNotSame($this->message, $message2);
138  self::assertNotSame(‪$message, $message2);
139  self::assertFalse($message2->hasHeader('X-Foo'));
140  }
141 
142  #[Test]
143  public function ‪headerRemovalIsCaseInsensitive(): void
144  {
145  ‪$message = $this->message
146  ->‪withHeader('X-Foo', 'Foo')
147  ->withAddedHeader('x-foo', 'Bar')
148  ->withAddedHeader('X-FOO', 'Baz');
149  self::assertNotSame($this->message, ‪$message);
150  self::assertTrue(‪$message->‪hasHeader('x-foo'));
151  $message2 = ‪$message->‪withoutHeader('x-foo');
152  self::assertNotSame($this->message, $message2);
153  self::assertNotSame(‪$message, $message2);
154  self::assertFalse($message2->hasHeader('X-Foo'));
155  $headers = $message2->getHeaders();
156  self::assertCount(0, $headers);
157  }
158 
159  public static function ‪invalidGeneralHeaderValuesDataProvider(): array
160  {
161  return [
162  'null' => [null],
163  'true' => [true],
164  'false' => [false],
165  'int' => [1],
166  'float' => [1.1],
167  'array' => [['foo' => ['bar']]],
168  'object' => [(object)['foo' => 'bar']],
169  ];
170  }
171 
172  #[DataProvider('invalidGeneralHeaderValuesDataProvider')]
173  #[Test]
175  {
176  $this->expectException(\InvalidArgumentException::class);
177  $this->expectExceptionCode(1436717266);
178  $this->message->withHeader('X-Foo', [$value]);
179  }
180 
181  public static function ‪invalidHeaderValuesDataProvider(): array
182  {
183  return [
184  'null' => [null],
185  'true' => [true],
186  'false' => [false],
187  'int' => [1],
188  'float' => [1.1],
189  'object' => [(object)['foo' => 'bar']],
190  ];
191  }
192 
193  #[DataProvider('invalidHeaderValuesDataProvider')]
195  {
196  $this->expectException(\InvalidArgumentException::class);
197  $this->expectExceptionCode(1436717266);
198  $this->message->withHeader('X-Foo', $value);
199  }
200 
201  #[DataProvider('invalidHeaderValuesDataProvider')]
203  {
204  $this->expectException(\InvalidArgumentException::class);
205  $this->expectExceptionCode(1436717267);
206  $this->message->withAddedHeader('X-Foo', $value);
207  }
208 
209  #[Test]
211  {
212  self::assertFalse($this->message->hasHeader('X-Foo'));
213  ‪$message = $this->message->‪withoutHeader('X-Foo');
214  self::assertNotSame($this->message, ‪$message);
215  self::assertFalse(‪$message->‪hasHeader('X-Foo'));
216  }
217 
218  #[Test]
220  {
221  self::assertSame([], $this->message->getHeader('X-Foo-Bar'));
222  }
223 
224  #[Test]
226  {
227  self::assertSame('', $this->message->getHeaderLine('X-Foo-Bar'));
228  }
229 
230  public static function ‪headersWithInjectionVectorsDataProvider(): array
231  {
232  return [
233  'name-with-cr' => ["X-Foo\r-Bar", 'value'],
234  'name-with-lf' => ["X-Foo\n-Bar", 'value'],
235  'name-with-crlf' => ["X-Foo\r\n-Bar", 'value'],
236  'name-with-2crlf' => ["X-Foo\r\n\r\n-Bar", 'value'],
237  'value-with-cr' => ['X-Foo-Bar', "value\rinjection"],
238  'value-with-lf' => ['X-Foo-Bar', "value\ninjection"],
239  'value-with-crlf' => ['X-Foo-Bar', "value\r\ninjection"],
240  'value-with-2crlf' => ['X-Foo-Bar', "value\r\n\r\ninjection"],
241  'array-value-with-cr' => ['X-Foo-Bar', ["value\rinjection"]],
242  'array-value-with-lf' => ['X-Foo-Bar', ["value\ninjection"]],
243  'array-value-with-crlf' => ['X-Foo-Bar', ["value\r\ninjection"]],
244  'array-value-with-2crlf' => ['X-Foo-Bar', ["value\r\n\r\ninjection"]],
245  'multi-line-header-space' => ['X-Foo-Bar', "value\r\n injection"],
246  'multi-line-header-tab' => ['X-Foo-Bar', "value\r\n\tinjection"],
247  'value-with-EOT' => ['X-Foo-Bar', "value\x03injection"],
248  'value-with-vert-tab' => ['X-Foo-Bar', "value\x11injection"],
249  'value-with-form-feed' => ['X-Foo-Bar', "value\x12injection"],
250  'value-with-null-byte' => ['X-Foo-Bar', "value\x00injection"],
251  'value-with-del-byte' => ['X-Foo-Bar', "value\x7finjection"],
252  ];
253  }
254 
255  #[DataProvider('headersWithInjectionVectorsDataProvider')]
256  #[Test]
257  public function ‪doesNotAllowCRLFInjectionWhenCallingWithHeader($name, $value): void
258  {
259  $this->expectException(\InvalidArgumentException::class);
260  $this->message->withHeader($name, $value);
261  }
262 
263  #[DataProvider('headersWithInjectionVectorsDataProvider')]
264  #[Test]
265  public function ‪doesNotAllowCRLFInjectionWhenCallingWithAddedHeader($name, $value): void
266  {
267  $this->expectException(\InvalidArgumentException::class);
268  $this->message->withAddedHeader($name, $value);
269  }
270 }
‪TYPO3\CMS\Core\Http\Message\getBody
‪StreamInterface getBody()
Definition: Message.php:287
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\hasHeaderReturnsTrueIfHeaderIsPresent
‪hasHeaderReturnsTrueIfHeaderIsPresent()
Definition: MessageTest.php:113
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\addHeaderAppendsToExistingHeader
‪addHeaderAppendsToExistingHeader()
Definition: MessageTest.php:121
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\withAddedHeaderRaisesExceptionForNonStringNonArrayValue
‪withAddedHeaderRaisesExceptionForNonStringNonArrayValue($value)
Definition: MessageTest.php:202
‪TYPO3\CMS\Core\Http\Message\getHeaders
‪array getHeaders()
Definition: Message.php:114
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\bodyMutatorReturnsCloneWithChanges
‪bodyMutatorReturnsCloneWithChanges()
Definition: MessageTest.php:64
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\withHeaderRaisesExceptionForInvalidNestedHeaderValue
‪withHeaderRaisesExceptionForInvalidNestedHeaderValue($value)
Definition: MessageTest.php:174
‪TYPO3\CMS\Core\Tests\Unit\Http
Definition: ApplicationTypeTest.php:18
‪TYPO3\CMS\Core\Http\Message\getHeaderLine
‪string getHeaderLine(string $name)
Definition: Message.php:178
‪TYPO3\CMS\Core\Http\Message\withAddedHeader
‪static withAddedHeader(string $name, $value)
Definition: Message.php:238
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\canRemoveHeaders
‪canRemoveHeaders()
Definition: MessageTest.php:131
‪TYPO3\CMS\Core\Http\Message\withoutHeader
‪static withoutHeader(string $name)
Definition: Message.php:269
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\getHeaderReturnsAnEmptyArrayWhenHeaderDoesNotExist
‪getHeaderReturnsAnEmptyArrayWhenHeaderDoesNotExist()
Definition: MessageTest.php:219
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\headersWithInjectionVectorsDataProvider
‪static headersWithInjectionVectorsDataProvider()
Definition: MessageTest.php:230
‪TYPO3\CMS\Core\Http\Message
Definition: Message.php:32
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\headerRemovalIsCaseInsensitive
‪headerRemovalIsCaseInsensitive()
Definition: MessageTest.php:143
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\$stream
‪Stream $stream
Definition: MessageTest.php:33
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest
Definition: MessageTest.php:32
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\protocolMutatorReturnsCloneWithChanges
‪protocolMutatorReturnsCloneWithChanges()
Definition: MessageTest.php:50
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\usesStreamProvidedInConstructorAsBody
‪usesStreamProvidedInConstructorAsBody()
Definition: MessageTest.php:58
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\invalidHeaderValuesDataProvider
‪static invalidHeaderValuesDataProvider()
Definition: MessageTest.php:181
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\doesNotAllowCRLFInjectionWhenCallingWithHeader
‪doesNotAllowCRLFInjectionWhenCallingWithHeader($name, $value)
Definition: MessageTest.php:257
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\protocolHasAcceptableDefault
‪protocolHasAcceptableDefault()
Definition: MessageTest.php:44
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\withoutHeaderDoesNothingIfHeaderDoesNotExist
‪withoutHeaderDoesNothingIfHeaderDoesNotExist()
Definition: MessageTest.php:210
‪TYPO3\CMS\Core\Http\Stream
Definition: Stream.php:31
‪TYPO3\CMS\Core\Http\Message\getHeader
‪string[] getHeader(string $name)
Definition: Message.php:146
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\getHeaderLineReturnsEmptyStringWhenHeaderDoesNotExist
‪getHeaderLineReturnsEmptyStringWhenHeaderDoesNotExist()
Definition: MessageTest.php:225
‪TYPO3\CMS\Core\Http\Message\getProtocolVersion
‪string getProtocolVersion()
Definition: Message.php:62
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\setUp
‪setUp()
Definition: MessageTest.php:36
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\getHeadersReturnsCaseWithWhichHeaderFirstRegistered
‪getHeadersReturnsCaseWithWhichHeaderFirstRegistered()
Definition: MessageTest.php:97
‪TYPO3\CMS\Core\Http\Message\withHeader
‪static withHeader(string $name, $value)
Definition: Message.php:202
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\getHeadersKeepsHeaderCaseSensitivity
‪getHeadersKeepsHeaderCaseSensitivity()
Definition: MessageTest.php:89
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\invalidGeneralHeaderValuesDataProvider
‪static invalidGeneralHeaderValuesDataProvider()
Definition: MessageTest.php:159
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\doesNotAllowCRLFInjectionWhenCallingWithAddedHeader
‪doesNotAllowCRLFInjectionWhenCallingWithAddedHeader($name, $value)
Definition: MessageTest.php:265
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\withHeaderRaisesExceptionForInvalidValueType
‪withHeaderRaisesExceptionForInvalidValueType($value)
Definition: MessageTest.php:194
‪TYPO3\CMS\Core\Http\Message\withBody
‪static withBody(StreamInterface $body)
Definition: Message.php:307
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\getHeaderLineReturnsHeaderValueAsCommaConcatenatedString
‪getHeaderLineReturnsHeaderValueAsCommaConcatenatedString()
Definition: MessageTest.php:81
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\hasHeaderReturnsFalseIfHeaderIsNotPresent
‪hasHeaderReturnsFalseIfHeaderIsNotPresent()
Definition: MessageTest.php:107
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\getHeaderReturnsHeaderValueAsArray
‪getHeaderReturnsHeaderValueAsArray()
Definition: MessageTest.php:73
‪TYPO3\CMS\Core\Http\Message\hasHeader
‪bool hasHeader(string $name)
Definition: Message.php:127
‪TYPO3\CMS\Core\Http\Message\withProtocolVersion
‪static withProtocolVersion(string $version)
Definition: Message.php:80
‪TYPO3\CMS\Core\Tests\Unit\Http\MessageTest\$message
‪Message $message
Definition: MessageTest.php:34