Passed
Push — master ( c3277e...6db6a3 )
by Anatoly
04:11 queued 16s
created
src/Uri/Component/Scheme.php 1 patch
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -22,40 +22,40 @@
 block discarded – undo
22 22
  */
23 23
 final class Scheme implements ComponentInterface
24 24
 {
25
-    private const VALIDATION_REGEX = '/^(?:[A-Za-z][0-9A-Za-z\x2b\x2d\x2e]*)?$/';
26
-
27
-    private string $value = '';
28
-
29
-    /**
30
-     * @param mixed $value
31
-     *
32
-     * @throws InvalidArgumentException
33
-     */
34
-    public function __construct($value)
35
-    {
36
-        if ($value === '') {
37
-            return;
38
-        }
39
-
40
-        if (!is_string($value)) {
41
-            throw new InvalidArgumentException('URI component "scheme" must be a string');
42
-        }
43
-
44
-        if (!preg_match(self::VALIDATION_REGEX, $value)) {
45
-            throw new InvalidArgumentException('Invalid URI component "scheme"');
46
-        }
47
-
48
-        // the component is case-insensitive...
49
-        $this->value = strtolower($value);
50
-    }
51
-
52
-    /**
53
-     * {@inheritdoc}
54
-     *
55
-     * @return string
56
-     */
57
-    public function getValue(): string
58
-    {
59
-        return $this->value;
60
-    }
25
+	private const VALIDATION_REGEX = '/^(?:[A-Za-z][0-9A-Za-z\x2b\x2d\x2e]*)?$/';
26
+
27
+	private string $value = '';
28
+
29
+	/**
30
+	 * @param mixed $value
31
+	 *
32
+	 * @throws InvalidArgumentException
33
+	 */
34
+	public function __construct($value)
35
+	{
36
+		if ($value === '') {
37
+			return;
38
+		}
39
+
40
+		if (!is_string($value)) {
41
+			throw new InvalidArgumentException('URI component "scheme" must be a string');
42
+		}
43
+
44
+		if (!preg_match(self::VALIDATION_REGEX, $value)) {
45
+			throw new InvalidArgumentException('Invalid URI component "scheme"');
46
+		}
47
+
48
+		// the component is case-insensitive...
49
+		$this->value = strtolower($value);
50
+	}
51
+
52
+	/**
53
+	 * {@inheritdoc}
54
+	 *
55
+	 * @return string
56
+	 */
57
+	public function getValue(): string
58
+	{
59
+		return $this->value;
60
+	}
61 61
 }
Please login to merge, or discard this patch.
src/HeaderInterface.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -18,17 +18,17 @@
 block discarded – undo
18 18
  */
19 19
 interface HeaderInterface extends IteratorAggregate
20 20
 {
21
-    public const RFC822_DATE_FORMAT = 'D, d M y H:i:s O';
21
+	public const RFC822_DATE_FORMAT = 'D, d M y H:i:s O';
22 22
 
23
-    public const RFC7230_TOKEN_REGEX = '/^[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]+$/';
23
+	public const RFC7230_TOKEN_REGEX = '/^[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]+$/';
24 24
 
25
-    public const RFC7230_FIELD_VALUE_REGEX = '/^[\x09\x20-\x7E\x80-\xFF]*$/';
25
+	public const RFC7230_FIELD_VALUE_REGEX = '/^[\x09\x20-\x7E\x80-\xFF]*$/';
26 26
 
27
-    public const RFC7230_QUOTED_STRING_REGEX = '/^(?:[\x5C][\x22]|[\x09\x20\x21\x23-\x5B\x5D-\x7E\x80-\xFF])*$/';
27
+	public const RFC7230_QUOTED_STRING_REGEX = '/^(?:[\x5C][\x22]|[\x09\x20\x21\x23-\x5B\x5D-\x7E\x80-\xFF])*$/';
28 28
 
29
-    public function getFieldName(): string;
29
+	public function getFieldName(): string;
30 30
 
31
-    public function getFieldValue(): string;
31
+	public function getFieldValue(): string;
32 32
 
33
-    public function __toString(): string;
33
+	public function __toString(): string;
34 34
 }
Please login to merge, or discard this patch.
src/Response.php 1 patch
Indentation   +194 added lines, -194 removed lines patch added patch discarded remove patch
@@ -22,198 +22,198 @@
 block discarded – undo
22 22
 
23 23
 class Response extends Message implements ResponseInterface, StatusCodeInterface
24 24
 {
25
-    /**
26
-     * List of Reason Phrases
27
-     *
28
-     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
29
-     *
30
-     * @var array<int<100, 599>, non-empty-string>
31
-     */
32
-    public const REASON_PHRASES = [
33
-        // 1xx
34
-        100 => 'Continue',
35
-        101 => 'Switching Protocols',
36
-        102 => 'Processing',
37
-        103 => 'Early Hints',
38
-        // 2xx
39
-        200 => 'OK',
40
-        201 => 'Created',
41
-        202 => 'Accepted',
42
-        203 => 'Non-Authoritative Information',
43
-        204 => 'No Content',
44
-        205 => 'Reset Content',
45
-        206 => 'Partial Content',
46
-        207 => 'Multi-Status',
47
-        208 => 'Already Reported',
48
-        226 => 'IM Used',
49
-        // 3xx
50
-        300 => 'Multiple Choices',
51
-        301 => 'Moved Permanently',
52
-        302 => 'Found',
53
-        303 => 'See Other',
54
-        304 => 'Not Modified',
55
-        305 => 'Use Proxy',
56
-        307 => 'Temporary Redirect',
57
-        308 => 'Permanent Redirect',
58
-        // 4xx
59
-        400 => 'Bad Request',
60
-        401 => 'Unauthorized',
61
-        402 => 'Payment Required',
62
-        403 => 'Forbidden',
63
-        404 => 'Not Found',
64
-        405 => 'Method Not Allowed',
65
-        406 => 'Not Acceptable',
66
-        407 => 'Proxy Authentication Required',
67
-        408 => 'Request Timeout',
68
-        409 => 'Conflict',
69
-        410 => 'Gone',
70
-        411 => 'Length Required',
71
-        412 => 'Precondition Failed',
72
-        413 => 'Payload Too Large',
73
-        414 => 'URI Too Long',
74
-        415 => 'Unsupported Media Type',
75
-        416 => 'Range Not Satisfiable',
76
-        417 => 'Expectation Failed',
77
-        421 => 'Misdirected Request',
78
-        422 => 'Unprocessable Entity',
79
-        423 => 'Locked',
80
-        424 => 'Failed Dependency',
81
-        425 => 'Too Early',
82
-        426 => 'Upgrade Required',
83
-        428 => 'Precondition Required',
84
-        429 => 'Too Many Requests',
85
-        431 => 'Request Header Fields Too Large',
86
-        451 => 'Unavailable For Legal Reasons',
87
-        // 5xx
88
-        500 => 'Internal Server Error',
89
-        501 => 'Not Implemented',
90
-        502 => 'Bad Gateway',
91
-        503 => 'Service Unavailable',
92
-        504 => 'Gateway Timeout',
93
-        505 => 'HTTP Version Not Supported',
94
-        506 => 'Variant Also Negotiates',
95
-        507 => 'Insufficient Storage',
96
-        508 => 'Loop Detected',
97
-        510 => 'Not Extended',
98
-        511 => 'Network Authentication Required',
99
-    ];
100
-
101
-    private int $statusCode = self::STATUS_OK;
102
-    private string $reasonPhrase = self::REASON_PHRASES[self::STATUS_OK];
103
-
104
-    /**
105
-     * @param array<string, string|string[]>|null $headers
106
-     *
107
-     * @throws InvalidArgumentException
108
-     */
109
-    public function __construct(
110
-        ?int $statusCode = null,
111
-        ?string $reasonPhrase = null,
112
-        ?array $headers = null,
113
-        ?StreamInterface $body = null
114
-    ) {
115
-        if ($statusCode !== null) {
116
-            $this->setStatus($statusCode, $reasonPhrase ?? '');
117
-        }
118
-
119
-        if ($headers !== null) {
120
-            $this->setHeaders($headers);
121
-        }
122
-
123
-        if ($body !== null) {
124
-            $this->setBody($body);
125
-        }
126
-    }
127
-
128
-    /**
129
-     * @inheritDoc
130
-     */
131
-    public function getStatusCode(): int
132
-    {
133
-        return $this->statusCode;
134
-    }
135
-
136
-    /**
137
-     * @inheritDoc
138
-     */
139
-    public function getReasonPhrase(): string
140
-    {
141
-        return $this->reasonPhrase;
142
-    }
143
-
144
-    /**
145
-     * @inheritDoc
146
-     */
147
-    public function withStatus($code, $reasonPhrase = ''): ResponseInterface
148
-    {
149
-        $clone = clone $this;
150
-        $clone->setStatus($code, $reasonPhrase);
151
-
152
-        return $clone;
153
-    }
154
-
155
-    /**
156
-     * Sets the given status code to the response
157
-     *
158
-     * @param int $statusCode
159
-     * @param string $reasonPhrase
160
-     *
161
-     * @throws InvalidArgumentException
162
-     */
163
-    final protected function setStatus($statusCode, $reasonPhrase): void
164
-    {
165
-        $this->validateStatusCode($statusCode);
166
-        $this->validateReasonPhrase($reasonPhrase);
167
-
168
-        if ($reasonPhrase === '') {
169
-            $reasonPhrase = self::REASON_PHRASES[$statusCode] ?? 'Unknown Status Code';
170
-        }
171
-
172
-        $this->statusCode = $statusCode;
173
-        $this->reasonPhrase = $reasonPhrase;
174
-    }
175
-
176
-    /**
177
-     * Validates the given status code
178
-     *
179
-     * @link https://tools.ietf.org/html/rfc7230#section-3.1.2
180
-     *
181
-     * @param mixed $statusCode
182
-     *
183
-     * @throws InvalidArgumentException
184
-     */
185
-    private function validateStatusCode($statusCode): void
186
-    {
187
-        if (!is_int($statusCode)) {
188
-            throw new InvalidArgumentException('HTTP status code must be an integer');
189
-        }
190
-
191
-        if (!($statusCode >= 100 && $statusCode <= 599)) {
192
-            throw new InvalidArgumentException('Invalid HTTP status code');
193
-        }
194
-    }
195
-
196
-    /**
197
-     * Validates the given reason phrase
198
-     *
199
-     * @link https://tools.ietf.org/html/rfc7230#section-3.1.2
200
-     *
201
-     * @param mixed $reasonPhrase
202
-     *
203
-     * @throws InvalidArgumentException
204
-     */
205
-    private function validateReasonPhrase($reasonPhrase): void
206
-    {
207
-        if ($reasonPhrase === '') {
208
-            return;
209
-        }
210
-
211
-        if (!is_string($reasonPhrase)) {
212
-            throw new InvalidArgumentException('HTTP reason phrase must be a string');
213
-        }
214
-
215
-        if (!preg_match(HeaderInterface::RFC7230_FIELD_VALUE_REGEX, $reasonPhrase)) {
216
-            throw new InvalidArgumentException('Invalid HTTP reason phrase');
217
-        }
218
-    }
25
+	/**
26
+	 * List of Reason Phrases
27
+	 *
28
+	 * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
29
+	 *
30
+	 * @var array<int<100, 599>, non-empty-string>
31
+	 */
32
+	public const REASON_PHRASES = [
33
+		// 1xx
34
+		100 => 'Continue',
35
+		101 => 'Switching Protocols',
36
+		102 => 'Processing',
37
+		103 => 'Early Hints',
38
+		// 2xx
39
+		200 => 'OK',
40
+		201 => 'Created',
41
+		202 => 'Accepted',
42
+		203 => 'Non-Authoritative Information',
43
+		204 => 'No Content',
44
+		205 => 'Reset Content',
45
+		206 => 'Partial Content',
46
+		207 => 'Multi-Status',
47
+		208 => 'Already Reported',
48
+		226 => 'IM Used',
49
+		// 3xx
50
+		300 => 'Multiple Choices',
51
+		301 => 'Moved Permanently',
52
+		302 => 'Found',
53
+		303 => 'See Other',
54
+		304 => 'Not Modified',
55
+		305 => 'Use Proxy',
56
+		307 => 'Temporary Redirect',
57
+		308 => 'Permanent Redirect',
58
+		// 4xx
59
+		400 => 'Bad Request',
60
+		401 => 'Unauthorized',
61
+		402 => 'Payment Required',
62
+		403 => 'Forbidden',
63
+		404 => 'Not Found',
64
+		405 => 'Method Not Allowed',
65
+		406 => 'Not Acceptable',
66
+		407 => 'Proxy Authentication Required',
67
+		408 => 'Request Timeout',
68
+		409 => 'Conflict',
69
+		410 => 'Gone',
70
+		411 => 'Length Required',
71
+		412 => 'Precondition Failed',
72
+		413 => 'Payload Too Large',
73
+		414 => 'URI Too Long',
74
+		415 => 'Unsupported Media Type',
75
+		416 => 'Range Not Satisfiable',
76
+		417 => 'Expectation Failed',
77
+		421 => 'Misdirected Request',
78
+		422 => 'Unprocessable Entity',
79
+		423 => 'Locked',
80
+		424 => 'Failed Dependency',
81
+		425 => 'Too Early',
82
+		426 => 'Upgrade Required',
83
+		428 => 'Precondition Required',
84
+		429 => 'Too Many Requests',
85
+		431 => 'Request Header Fields Too Large',
86
+		451 => 'Unavailable For Legal Reasons',
87
+		// 5xx
88
+		500 => 'Internal Server Error',
89
+		501 => 'Not Implemented',
90
+		502 => 'Bad Gateway',
91
+		503 => 'Service Unavailable',
92
+		504 => 'Gateway Timeout',
93
+		505 => 'HTTP Version Not Supported',
94
+		506 => 'Variant Also Negotiates',
95
+		507 => 'Insufficient Storage',
96
+		508 => 'Loop Detected',
97
+		510 => 'Not Extended',
98
+		511 => 'Network Authentication Required',
99
+	];
100
+
101
+	private int $statusCode = self::STATUS_OK;
102
+	private string $reasonPhrase = self::REASON_PHRASES[self::STATUS_OK];
103
+
104
+	/**
105
+	 * @param array<string, string|string[]>|null $headers
106
+	 *
107
+	 * @throws InvalidArgumentException
108
+	 */
109
+	public function __construct(
110
+		?int $statusCode = null,
111
+		?string $reasonPhrase = null,
112
+		?array $headers = null,
113
+		?StreamInterface $body = null
114
+	) {
115
+		if ($statusCode !== null) {
116
+			$this->setStatus($statusCode, $reasonPhrase ?? '');
117
+		}
118
+
119
+		if ($headers !== null) {
120
+			$this->setHeaders($headers);
121
+		}
122
+
123
+		if ($body !== null) {
124
+			$this->setBody($body);
125
+		}
126
+	}
127
+
128
+	/**
129
+	 * @inheritDoc
130
+	 */
131
+	public function getStatusCode(): int
132
+	{
133
+		return $this->statusCode;
134
+	}
135
+
136
+	/**
137
+	 * @inheritDoc
138
+	 */
139
+	public function getReasonPhrase(): string
140
+	{
141
+		return $this->reasonPhrase;
142
+	}
143
+
144
+	/**
145
+	 * @inheritDoc
146
+	 */
147
+	public function withStatus($code, $reasonPhrase = ''): ResponseInterface
148
+	{
149
+		$clone = clone $this;
150
+		$clone->setStatus($code, $reasonPhrase);
151
+
152
+		return $clone;
153
+	}
154
+
155
+	/**
156
+	 * Sets the given status code to the response
157
+	 *
158
+	 * @param int $statusCode
159
+	 * @param string $reasonPhrase
160
+	 *
161
+	 * @throws InvalidArgumentException
162
+	 */
163
+	final protected function setStatus($statusCode, $reasonPhrase): void
164
+	{
165
+		$this->validateStatusCode($statusCode);
166
+		$this->validateReasonPhrase($reasonPhrase);
167
+
168
+		if ($reasonPhrase === '') {
169
+			$reasonPhrase = self::REASON_PHRASES[$statusCode] ?? 'Unknown Status Code';
170
+		}
171
+
172
+		$this->statusCode = $statusCode;
173
+		$this->reasonPhrase = $reasonPhrase;
174
+	}
175
+
176
+	/**
177
+	 * Validates the given status code
178
+	 *
179
+	 * @link https://tools.ietf.org/html/rfc7230#section-3.1.2
180
+	 *
181
+	 * @param mixed $statusCode
182
+	 *
183
+	 * @throws InvalidArgumentException
184
+	 */
185
+	private function validateStatusCode($statusCode): void
186
+	{
187
+		if (!is_int($statusCode)) {
188
+			throw new InvalidArgumentException('HTTP status code must be an integer');
189
+		}
190
+
191
+		if (!($statusCode >= 100 && $statusCode <= 599)) {
192
+			throw new InvalidArgumentException('Invalid HTTP status code');
193
+		}
194
+	}
195
+
196
+	/**
197
+	 * Validates the given reason phrase
198
+	 *
199
+	 * @link https://tools.ietf.org/html/rfc7230#section-3.1.2
200
+	 *
201
+	 * @param mixed $reasonPhrase
202
+	 *
203
+	 * @throws InvalidArgumentException
204
+	 */
205
+	private function validateReasonPhrase($reasonPhrase): void
206
+	{
207
+		if ($reasonPhrase === '') {
208
+			return;
209
+		}
210
+
211
+		if (!is_string($reasonPhrase)) {
212
+			throw new InvalidArgumentException('HTTP reason phrase must be a string');
213
+		}
214
+
215
+		if (!preg_match(HeaderInterface::RFC7230_FIELD_VALUE_REGEX, $reasonPhrase)) {
216
+			throw new InvalidArgumentException('Invalid HTTP reason phrase');
217
+		}
218
+	}
219 219
 }
Please login to merge, or discard this patch.
src/Response/HtmlResponse.php 1 patch
Indentation   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -22,42 +22,42 @@
 block discarded – undo
22 22
 
23 23
 final class HtmlResponse extends Response
24 24
 {
25
-    /**
26
-     * @param mixed $html
27
-     *
28
-     * @throws InvalidArgumentException
29
-     */
30
-    public function __construct(int $statusCode, $html)
31
-    {
32
-        parent::__construct($statusCode);
33
-
34
-        $this->setBody(self::createBody($html));
35
-        $this->setHeader('Content-Type', 'text/html; charset=utf-8');
36
-    }
37
-
38
-    /**
39
-     * @param mixed $html
40
-     *
41
-     * @throws InvalidArgumentException
42
-     */
43
-    private static function createBody($html): StreamInterface
44
-    {
45
-        if ($html instanceof StreamInterface) {
46
-            return $html;
47
-        }
48
-
49
-        if (is_object($html) && method_exists($html, '__toString')) {
50
-            $html = (string) $html;
51
-        }
52
-
53
-        if (!is_string($html)) {
54
-            throw new InvalidArgumentException('Unable to create the HTML response due to a unexpected HTML type');
55
-        }
56
-
57
-        $stream = new PhpTempStream('r+b');
58
-        $stream->write($html);
59
-        $stream->rewind();
60
-
61
-        return $stream;
62
-    }
25
+	/**
26
+	 * @param mixed $html
27
+	 *
28
+	 * @throws InvalidArgumentException
29
+	 */
30
+	public function __construct(int $statusCode, $html)
31
+	{
32
+		parent::__construct($statusCode);
33
+
34
+		$this->setBody(self::createBody($html));
35
+		$this->setHeader('Content-Type', 'text/html; charset=utf-8');
36
+	}
37
+
38
+	/**
39
+	 * @param mixed $html
40
+	 *
41
+	 * @throws InvalidArgumentException
42
+	 */
43
+	private static function createBody($html): StreamInterface
44
+	{
45
+		if ($html instanceof StreamInterface) {
46
+			return $html;
47
+		}
48
+
49
+		if (is_object($html) && method_exists($html, '__toString')) {
50
+			$html = (string) $html;
51
+		}
52
+
53
+		if (!is_string($html)) {
54
+			throw new InvalidArgumentException('Unable to create the HTML response due to a unexpected HTML type');
55
+		}
56
+
57
+		$stream = new PhpTempStream('r+b');
58
+		$stream->write($html);
59
+		$stream->rewind();
60
+
61
+		return $stream;
62
+	}
63 63
 }
Please login to merge, or discard this patch.
src/Message.php 1 patch
Indentation   +292 added lines, -292 removed lines patch added patch discarded remove patch
@@ -24,296 +24,296 @@
 block discarded – undo
24 24
 
25 25
 abstract class Message implements MessageInterface
26 26
 {
27
-    /**
28
-     * @deprecated 3.2.0
29
-     */
30
-    public const ALLOWED_HTTP_VERSIONS = ['1.0', '1.1', '2.0', '2'];
31
-
32
-    public const HTTP_VERSION_REGEX = '/^[0-9](?:[.][0-9])?$/';
33
-    public const DEFAULT_HTTP_VERSION = '1.1';
34
-
35
-    private string $protocolVersion = self::DEFAULT_HTTP_VERSION;
36
-
37
-    /**
38
-     * @var array<string, list<string>>
39
-     */
40
-    private array $headers = [];
41
-
42
-    /**
43
-     * @var array<string, string>
44
-     */
45
-    private array $headerNames = [];
46
-
47
-    private ?StreamInterface $body = null;
48
-
49
-    /**
50
-     * @inheritDoc
51
-     */
52
-    public function getProtocolVersion(): string
53
-    {
54
-        return $this->protocolVersion;
55
-    }
56
-
57
-    /**
58
-     * @inheritDoc
59
-     *
60
-     * @throws InvalidArgumentException
61
-     */
62
-    public function withProtocolVersion($version): MessageInterface
63
-    {
64
-        $clone = clone $this;
65
-        $clone->setProtocolVersion($version);
66
-
67
-        return $clone;
68
-    }
69
-
70
-    /**
71
-     * @inheritDoc
72
-     */
73
-    public function getHeaders(): array
74
-    {
75
-        return $this->headers;
76
-    }
77
-
78
-    /**
79
-     * @inheritDoc
80
-     */
81
-    public function hasHeader($name): bool
82
-    {
83
-        $key = strtolower($name);
84
-
85
-        return isset($this->headerNames[$key]);
86
-    }
87
-
88
-    /**
89
-     * @inheritDoc
90
-     */
91
-    public function getHeader($name): array
92
-    {
93
-        $key = strtolower($name);
94
-
95
-        if (!isset($this->headerNames[$key])) {
96
-            return [];
97
-        }
98
-
99
-        return $this->headers[$this->headerNames[$key]];
100
-    }
101
-
102
-    /**
103
-     * @inheritDoc
104
-     */
105
-    public function getHeaderLine($name): string
106
-    {
107
-        $key = strtolower($name);
108
-
109
-        if (!isset($this->headerNames[$key])) {
110
-            return '';
111
-        }
112
-
113
-        return implode(',', $this->headers[$this->headerNames[$key]]);
114
-    }
115
-
116
-    /**
117
-     * @inheritDoc
118
-     */
119
-    public function withHeader($name, $value): MessageInterface
120
-    {
121
-        $clone = clone $this;
122
-        $clone->setHeader($name, $value, true);
123
-
124
-        return $clone;
125
-    }
126
-
127
-    /**
128
-     * @inheritDoc
129
-     */
130
-    public function withAddedHeader($name, $value): MessageInterface
131
-    {
132
-        $clone = clone $this;
133
-        $clone->setHeader($name, $value, false);
134
-
135
-        return $clone;
136
-    }
137
-
138
-    /**
139
-     * @inheritDoc
140
-     */
141
-    public function withoutHeader($name): MessageInterface
142
-    {
143
-        $clone = clone $this;
144
-        $clone->deleteHeader($name);
145
-
146
-        return $clone;
147
-    }
148
-
149
-    /**
150
-     * @inheritDoc
151
-     */
152
-    public function getBody(): StreamInterface
153
-    {
154
-        return $this->body ??= new PhpTempStream();
155
-    }
156
-
157
-    /**
158
-     * @inheritDoc
159
-     */
160
-    public function withBody(StreamInterface $body): MessageInterface
161
-    {
162
-        $clone = clone $this;
163
-        $clone->setBody($body);
164
-
165
-        return $clone;
166
-    }
167
-
168
-    /**
169
-     * Sets the given HTTP version to the message
170
-     *
171
-     * @param string $protocolVersion
172
-     *
173
-     * @throws InvalidArgumentException
174
-     */
175
-    final protected function setProtocolVersion($protocolVersion): void
176
-    {
177
-        $this->validateProtocolVersion($protocolVersion);
178
-
179
-        $this->protocolVersion = $protocolVersion;
180
-    }
181
-
182
-    /**
183
-     * Sets a new header to the message with the given name and value(s)
184
-     *
185
-     * @param string $name
186
-     * @param string|string[] $value
187
-     *
188
-     * @throws InvalidArgumentException
189
-     */
190
-    final protected function setHeader($name, $value, bool $replace = true): void
191
-    {
192
-        if (!is_array($value)) {
193
-            $value = [$value];
194
-        }
195
-
196
-        $this->validateHeaderName($name);
197
-        $this->validateHeaderValue($name, $value);
198
-
199
-        $replace and $this->deleteHeader($name);
200
-
201
-        $key = strtolower($name);
202
-
203
-        $this->headerNames[$key] ??= $name;
204
-        $this->headers[$this->headerNames[$key]] ??= [];
205
-
206
-        foreach ($value as $item) {
207
-            $this->headers[$this->headerNames[$key]][] = $item;
208
-        }
209
-    }
210
-
211
-    /**
212
-     * Sets the given headers to the message
213
-     *
214
-     * @param array<string, string|string[]> $headers
215
-     *
216
-     * @throws InvalidArgumentException
217
-     */
218
-    final protected function setHeaders(array $headers): void
219
-    {
220
-        foreach ($headers as $name => $value) {
221
-            $this->setHeader($name, $value, false);
222
-        }
223
-    }
224
-
225
-    /**
226
-     * Deletes a header from the message by the given name
227
-     *
228
-     * @param string $name
229
-     */
230
-    final protected function deleteHeader($name): void
231
-    {
232
-        $key = strtolower($name);
233
-
234
-        if (isset($this->headerNames[$key])) {
235
-            unset($this->headers[$this->headerNames[$key]]);
236
-            unset($this->headerNames[$key]);
237
-        }
238
-    }
239
-
240
-    /**
241
-     * Sets the given body to the message
242
-     */
243
-    final protected function setBody(StreamInterface $body): void
244
-    {
245
-        $this->body = $body;
246
-    }
247
-
248
-    /**
249
-     * Validates the given HTTP version
250
-     *
251
-     * @param mixed $protocolVersion
252
-     *
253
-     * @throws InvalidArgumentException
254
-     */
255
-    private function validateProtocolVersion($protocolVersion): void
256
-    {
257
-        if ($protocolVersion === '') {
258
-            throw new InvalidArgumentException('HTTP version cannot be an empty');
259
-        }
260
-
261
-        if (!is_string($protocolVersion)) {
262
-            throw new InvalidArgumentException('HTTP version must be a string');
263
-        }
264
-
265
-        if (!preg_match(self::HTTP_VERSION_REGEX, $protocolVersion)) {
266
-            throw new InvalidArgumentException('HTTP version is invalid');
267
-        }
268
-    }
269
-
270
-    /**
271
-     * Validates the given header name
272
-     *
273
-     * @param mixed $name
274
-     *
275
-     * @throws InvalidArgumentException
276
-     */
277
-    private function validateHeaderName($name): void
278
-    {
279
-        if ($name === '') {
280
-            throw new InvalidArgumentException('HTTP header name cannot be an empty');
281
-        }
282
-
283
-        if (!is_string($name)) {
284
-            throw new InvalidArgumentException('HTTP header name must be a string');
285
-        }
286
-
287
-        if (!preg_match(HeaderInterface::RFC7230_TOKEN_REGEX, $name)) {
288
-            throw new InvalidArgumentException('HTTP header name is invalid');
289
-        }
290
-    }
291
-
292
-    /**
293
-     * Validates the given header value
294
-     *
295
-     * @param array<array-key, mixed> $value
296
-     *
297
-     * @throws InvalidArgumentException
298
-     */
299
-    private function validateHeaderValue(string $name, array $value): void
300
-    {
301
-        if ($value === []) {
302
-            throw new InvalidArgumentException("The value of the HTTP header $name cannot be an empty array");
303
-        }
304
-
305
-        foreach ($value as $key => $item) {
306
-            if ($item === '') {
307
-                continue;
308
-            }
309
-
310
-            if (!is_string($item)) {
311
-                throw new InvalidArgumentException("The value of the HTTP header $name:$key must be a string");
312
-            }
313
-
314
-            if (!preg_match(HeaderInterface::RFC7230_FIELD_VALUE_REGEX, $item)) {
315
-                throw new InvalidArgumentException("The value of the HTTP header $name:$key is invalid");
316
-            }
317
-        }
318
-    }
27
+	/**
28
+	 * @deprecated 3.2.0
29
+	 */
30
+	public const ALLOWED_HTTP_VERSIONS = ['1.0', '1.1', '2.0', '2'];
31
+
32
+	public const HTTP_VERSION_REGEX = '/^[0-9](?:[.][0-9])?$/';
33
+	public const DEFAULT_HTTP_VERSION = '1.1';
34
+
35
+	private string $protocolVersion = self::DEFAULT_HTTP_VERSION;
36
+
37
+	/**
38
+	 * @var array<string, list<string>>
39
+	 */
40
+	private array $headers = [];
41
+
42
+	/**
43
+	 * @var array<string, string>
44
+	 */
45
+	private array $headerNames = [];
46
+
47
+	private ?StreamInterface $body = null;
48
+
49
+	/**
50
+	 * @inheritDoc
51
+	 */
52
+	public function getProtocolVersion(): string
53
+	{
54
+		return $this->protocolVersion;
55
+	}
56
+
57
+	/**
58
+	 * @inheritDoc
59
+	 *
60
+	 * @throws InvalidArgumentException
61
+	 */
62
+	public function withProtocolVersion($version): MessageInterface
63
+	{
64
+		$clone = clone $this;
65
+		$clone->setProtocolVersion($version);
66
+
67
+		return $clone;
68
+	}
69
+
70
+	/**
71
+	 * @inheritDoc
72
+	 */
73
+	public function getHeaders(): array
74
+	{
75
+		return $this->headers;
76
+	}
77
+
78
+	/**
79
+	 * @inheritDoc
80
+	 */
81
+	public function hasHeader($name): bool
82
+	{
83
+		$key = strtolower($name);
84
+
85
+		return isset($this->headerNames[$key]);
86
+	}
87
+
88
+	/**
89
+	 * @inheritDoc
90
+	 */
91
+	public function getHeader($name): array
92
+	{
93
+		$key = strtolower($name);
94
+
95
+		if (!isset($this->headerNames[$key])) {
96
+			return [];
97
+		}
98
+
99
+		return $this->headers[$this->headerNames[$key]];
100
+	}
101
+
102
+	/**
103
+	 * @inheritDoc
104
+	 */
105
+	public function getHeaderLine($name): string
106
+	{
107
+		$key = strtolower($name);
108
+
109
+		if (!isset($this->headerNames[$key])) {
110
+			return '';
111
+		}
112
+
113
+		return implode(',', $this->headers[$this->headerNames[$key]]);
114
+	}
115
+
116
+	/**
117
+	 * @inheritDoc
118
+	 */
119
+	public function withHeader($name, $value): MessageInterface
120
+	{
121
+		$clone = clone $this;
122
+		$clone->setHeader($name, $value, true);
123
+
124
+		return $clone;
125
+	}
126
+
127
+	/**
128
+	 * @inheritDoc
129
+	 */
130
+	public function withAddedHeader($name, $value): MessageInterface
131
+	{
132
+		$clone = clone $this;
133
+		$clone->setHeader($name, $value, false);
134
+
135
+		return $clone;
136
+	}
137
+
138
+	/**
139
+	 * @inheritDoc
140
+	 */
141
+	public function withoutHeader($name): MessageInterface
142
+	{
143
+		$clone = clone $this;
144
+		$clone->deleteHeader($name);
145
+
146
+		return $clone;
147
+	}
148
+
149
+	/**
150
+	 * @inheritDoc
151
+	 */
152
+	public function getBody(): StreamInterface
153
+	{
154
+		return $this->body ??= new PhpTempStream();
155
+	}
156
+
157
+	/**
158
+	 * @inheritDoc
159
+	 */
160
+	public function withBody(StreamInterface $body): MessageInterface
161
+	{
162
+		$clone = clone $this;
163
+		$clone->setBody($body);
164
+
165
+		return $clone;
166
+	}
167
+
168
+	/**
169
+	 * Sets the given HTTP version to the message
170
+	 *
171
+	 * @param string $protocolVersion
172
+	 *
173
+	 * @throws InvalidArgumentException
174
+	 */
175
+	final protected function setProtocolVersion($protocolVersion): void
176
+	{
177
+		$this->validateProtocolVersion($protocolVersion);
178
+
179
+		$this->protocolVersion = $protocolVersion;
180
+	}
181
+
182
+	/**
183
+	 * Sets a new header to the message with the given name and value(s)
184
+	 *
185
+	 * @param string $name
186
+	 * @param string|string[] $value
187
+	 *
188
+	 * @throws InvalidArgumentException
189
+	 */
190
+	final protected function setHeader($name, $value, bool $replace = true): void
191
+	{
192
+		if (!is_array($value)) {
193
+			$value = [$value];
194
+		}
195
+
196
+		$this->validateHeaderName($name);
197
+		$this->validateHeaderValue($name, $value);
198
+
199
+		$replace and $this->deleteHeader($name);
200
+
201
+		$key = strtolower($name);
202
+
203
+		$this->headerNames[$key] ??= $name;
204
+		$this->headers[$this->headerNames[$key]] ??= [];
205
+
206
+		foreach ($value as $item) {
207
+			$this->headers[$this->headerNames[$key]][] = $item;
208
+		}
209
+	}
210
+
211
+	/**
212
+	 * Sets the given headers to the message
213
+	 *
214
+	 * @param array<string, string|string[]> $headers
215
+	 *
216
+	 * @throws InvalidArgumentException
217
+	 */
218
+	final protected function setHeaders(array $headers): void
219
+	{
220
+		foreach ($headers as $name => $value) {
221
+			$this->setHeader($name, $value, false);
222
+		}
223
+	}
224
+
225
+	/**
226
+	 * Deletes a header from the message by the given name
227
+	 *
228
+	 * @param string $name
229
+	 */
230
+	final protected function deleteHeader($name): void
231
+	{
232
+		$key = strtolower($name);
233
+
234
+		if (isset($this->headerNames[$key])) {
235
+			unset($this->headers[$this->headerNames[$key]]);
236
+			unset($this->headerNames[$key]);
237
+		}
238
+	}
239
+
240
+	/**
241
+	 * Sets the given body to the message
242
+	 */
243
+	final protected function setBody(StreamInterface $body): void
244
+	{
245
+		$this->body = $body;
246
+	}
247
+
248
+	/**
249
+	 * Validates the given HTTP version
250
+	 *
251
+	 * @param mixed $protocolVersion
252
+	 *
253
+	 * @throws InvalidArgumentException
254
+	 */
255
+	private function validateProtocolVersion($protocolVersion): void
256
+	{
257
+		if ($protocolVersion === '') {
258
+			throw new InvalidArgumentException('HTTP version cannot be an empty');
259
+		}
260
+
261
+		if (!is_string($protocolVersion)) {
262
+			throw new InvalidArgumentException('HTTP version must be a string');
263
+		}
264
+
265
+		if (!preg_match(self::HTTP_VERSION_REGEX, $protocolVersion)) {
266
+			throw new InvalidArgumentException('HTTP version is invalid');
267
+		}
268
+	}
269
+
270
+	/**
271
+	 * Validates the given header name
272
+	 *
273
+	 * @param mixed $name
274
+	 *
275
+	 * @throws InvalidArgumentException
276
+	 */
277
+	private function validateHeaderName($name): void
278
+	{
279
+		if ($name === '') {
280
+			throw new InvalidArgumentException('HTTP header name cannot be an empty');
281
+		}
282
+
283
+		if (!is_string($name)) {
284
+			throw new InvalidArgumentException('HTTP header name must be a string');
285
+		}
286
+
287
+		if (!preg_match(HeaderInterface::RFC7230_TOKEN_REGEX, $name)) {
288
+			throw new InvalidArgumentException('HTTP header name is invalid');
289
+		}
290
+	}
291
+
292
+	/**
293
+	 * Validates the given header value
294
+	 *
295
+	 * @param array<array-key, mixed> $value
296
+	 *
297
+	 * @throws InvalidArgumentException
298
+	 */
299
+	private function validateHeaderValue(string $name, array $value): void
300
+	{
301
+		if ($value === []) {
302
+			throw new InvalidArgumentException("The value of the HTTP header $name cannot be an empty array");
303
+		}
304
+
305
+		foreach ($value as $key => $item) {
306
+			if ($item === '') {
307
+				continue;
308
+			}
309
+
310
+			if (!is_string($item)) {
311
+				throw new InvalidArgumentException("The value of the HTTP header $name:$key must be a string");
312
+			}
313
+
314
+			if (!preg_match(HeaderInterface::RFC7230_FIELD_VALUE_REGEX, $item)) {
315
+				throw new InvalidArgumentException("The value of the HTTP header $name:$key is invalid");
316
+			}
317
+		}
318
+	}
319 319
 }
Please login to merge, or discard this patch.
resources/definitions/psr17.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -18,10 +18,10 @@
 block discarded – undo
18 18
 use function DI\create;
19 19
 
20 20
 return [
21
-    RequestFactoryInterface::class => create(RequestFactory::class),
22
-    ResponseFactoryInterface::class => create(ResponseFactory::class),
23
-    ServerRequestFactoryInterface::class => create(ServerRequestFactory::class),
24
-    StreamFactoryInterface::class => create(StreamFactory::class),
25
-    UploadedFileFactoryInterface::class => create(UploadedFileFactory::class),
26
-    UriFactoryInterface::class => create(UriFactory::class),
21
+	RequestFactoryInterface::class => create(RequestFactory::class),
22
+	ResponseFactoryInterface::class => create(ResponseFactory::class),
23
+	ServerRequestFactoryInterface::class => create(ServerRequestFactory::class),
24
+	StreamFactoryInterface::class => create(StreamFactory::class),
25
+	UploadedFileFactoryInterface::class => create(UploadedFileFactory::class),
26
+	UriFactoryInterface::class => create(UriFactory::class),
27 27
 ];
Please login to merge, or discard this patch.
src/Response/JsonResponse.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -24,48 +24,48 @@
 block discarded – undo
24 24
 
25 25
 final class JsonResponse extends Response
26 26
 {
27
-    /**
28
-     * @param mixed $data
29
-     * @param int<1, max> $depth
30
-     * @psalm-param int<1, 2147483647> $depth
31
-     *
32
-     * @throws InvalidArgumentException
33
-     */
34
-    public function __construct(int $statusCode, $data, int $flags = 0, int $depth = 512)
35
-    {
36
-        parent::__construct($statusCode);
27
+	/**
28
+	 * @param mixed $data
29
+	 * @param int<1, max> $depth
30
+	 * @psalm-param int<1, 2147483647> $depth
31
+	 *
32
+	 * @throws InvalidArgumentException
33
+	 */
34
+	public function __construct(int $statusCode, $data, int $flags = 0, int $depth = 512)
35
+	{
36
+		parent::__construct($statusCode);
37 37
 
38
-        $this->setBody(self::createBody($data, $flags, $depth));
39
-        $this->setHeader('Content-Type', 'application/json; charset=utf-8');
40
-    }
38
+		$this->setBody(self::createBody($data, $flags, $depth));
39
+		$this->setHeader('Content-Type', 'application/json; charset=utf-8');
40
+	}
41 41
 
42
-    /**
43
-     * @param mixed $data
44
-     * @param int<1, max> $depth
45
-     * @psalm-param int<1, 2147483647> $depth
46
-     *
47
-     * @throws InvalidArgumentException
48
-     */
49
-    private static function createBody($data, int $flags, int $depth): StreamInterface
50
-    {
51
-        if ($data instanceof StreamInterface) {
52
-            return $data;
53
-        }
42
+	/**
43
+	 * @param mixed $data
44
+	 * @param int<1, max> $depth
45
+	 * @psalm-param int<1, 2147483647> $depth
46
+	 *
47
+	 * @throws InvalidArgumentException
48
+	 */
49
+	private static function createBody($data, int $flags, int $depth): StreamInterface
50
+	{
51
+		if ($data instanceof StreamInterface) {
52
+			return $data;
53
+		}
54 54
 
55
-        try {
56
-            /** @var non-empty-string $json */
57
-            $json = json_encode($data, $flags | JSON_THROW_ON_ERROR, $depth);
58
-        } catch (JsonException $e) {
59
-            throw new InvalidArgumentException(sprintf(
60
-                'Unable to create the JSON response due to an invalid data: %s',
61
-                $e->getMessage()
62
-            ), 0, $e);
63
-        }
55
+		try {
56
+			/** @var non-empty-string $json */
57
+			$json = json_encode($data, $flags | JSON_THROW_ON_ERROR, $depth);
58
+		} catch (JsonException $e) {
59
+			throw new InvalidArgumentException(sprintf(
60
+				'Unable to create the JSON response due to an invalid data: %s',
61
+				$e->getMessage()
62
+			), 0, $e);
63
+		}
64 64
 
65
-        $stream = new PhpTempStream('r+b');
66
-        $stream->write($json);
67
-        $stream->rewind();
65
+		$stream = new PhpTempStream('r+b');
66
+		$stream->write($json);
67
+		$stream->rewind();
68 68
 
69
-        return $stream;
70
-    }
69
+		return $stream;
70
+	}
71 71
 }
Please login to merge, or discard this patch.
src/Request/JsonRequest.php 1 patch
Indentation   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -27,49 +27,49 @@
 block discarded – undo
27 27
  */
28 28
 final class JsonRequest extends Request
29 29
 {
30
-    /**
31
-     * @param mixed $uri
32
-     * @param mixed $data
33
-     * @param int<1, max> $depth
34
-     * @psalm-param int<1, 2147483647> $depth
35
-     *
36
-     * @throws InvalidArgumentException
37
-     */
38
-    public function __construct(string $method, $uri, $data, int $flags = 0, int $depth = 512)
39
-    {
40
-        parent::__construct($method, $uri);
30
+	/**
31
+	 * @param mixed $uri
32
+	 * @param mixed $data
33
+	 * @param int<1, max> $depth
34
+	 * @psalm-param int<1, 2147483647> $depth
35
+	 *
36
+	 * @throws InvalidArgumentException
37
+	 */
38
+	public function __construct(string $method, $uri, $data, int $flags = 0, int $depth = 512)
39
+	{
40
+		parent::__construct($method, $uri);
41 41
 
42
-        $this->setBody(self::createBody($data, $flags, $depth));
43
-        $this->setHeader('Content-Type', 'application/json; charset=utf-8');
44
-    }
42
+		$this->setBody(self::createBody($data, $flags, $depth));
43
+		$this->setHeader('Content-Type', 'application/json; charset=utf-8');
44
+	}
45 45
 
46
-    /**
47
-     * @param mixed $data
48
-     * @param int<1, max> $depth
49
-     * @psalm-param int<1, 2147483647> $depth
50
-     *
51
-     * @throws InvalidArgumentException
52
-     */
53
-    private static function createBody($data, int $flags, int $depth): StreamInterface
54
-    {
55
-        if ($data instanceof StreamInterface) {
56
-            return $data;
57
-        }
46
+	/**
47
+	 * @param mixed $data
48
+	 * @param int<1, max> $depth
49
+	 * @psalm-param int<1, 2147483647> $depth
50
+	 *
51
+	 * @throws InvalidArgumentException
52
+	 */
53
+	private static function createBody($data, int $flags, int $depth): StreamInterface
54
+	{
55
+		if ($data instanceof StreamInterface) {
56
+			return $data;
57
+		}
58 58
 
59
-        try {
60
-            /** @var non-empty-string $json */
61
-            $json = json_encode($data, $flags | JSON_THROW_ON_ERROR, $depth);
62
-        } catch (JsonException $e) {
63
-            throw new InvalidArgumentException(sprintf(
64
-                'Unable to create the JSON request due to an invalid data: %s',
65
-                $e->getMessage(),
66
-            ), 0, $e);
67
-        }
59
+		try {
60
+			/** @var non-empty-string $json */
61
+			$json = json_encode($data, $flags | JSON_THROW_ON_ERROR, $depth);
62
+		} catch (JsonException $e) {
63
+			throw new InvalidArgumentException(sprintf(
64
+				'Unable to create the JSON request due to an invalid data: %s',
65
+				$e->getMessage(),
66
+			), 0, $e);
67
+		}
68 68
 
69
-        $stream = new PhpTempStream('r+b');
70
-        $stream->write($json);
71
-        $stream->rewind();
69
+		$stream = new PhpTempStream('r+b');
70
+		$stream->write($json);
71
+		$stream->rewind();
72 72
 
73
-        return $stream;
74
-    }
73
+		return $stream;
74
+	}
75 75
 }
Please login to merge, or discard this patch.
src/Request.php 1 patch
Indentation   +214 added lines, -214 removed lines patch added patch discarded remove patch
@@ -23,218 +23,218 @@
 block discarded – undo
23 23
 
24 24
 class Request extends Message implements RequestInterface, RequestMethodInterface
25 25
 {
26
-    private const RFC7230_REQUEST_TARGET_REGEX = '/^[\x21-\x7E\x80-\xFF]+$/';
27
-
28
-    private string $method = self::METHOD_GET;
29
-    private UriInterface $uri;
30
-    private ?string $requestTarget = null;
31
-
32
-    /**
33
-     * @param mixed $uri
34
-     * @param array<string, string|string[]>|null $headers
35
-     *
36
-     * @throws InvalidArgumentException
37
-     */
38
-    public function __construct(
39
-        ?string $method = null,
40
-        $uri = null,
41
-        ?array $headers = null,
42
-        ?StreamInterface $body = null
43
-    ) {
44
-        if ($method !== null) {
45
-            $this->setMethod($method);
46
-        }
47
-
48
-        $this->setUri($uri ?? '/');
49
-
50
-        if ($headers !== null) {
51
-            $this->setHeaders($headers);
52
-        }
53
-
54
-        if ($body !== null) {
55
-            $this->setBody($body);
56
-        }
57
-    }
58
-
59
-    /**
60
-     * @inheritDoc
61
-     */
62
-    public function getMethod(): string
63
-    {
64
-        return $this->method;
65
-    }
66
-
67
-    /**
68
-     * @inheritDoc
69
-     */
70
-    public function withMethod($method): RequestInterface
71
-    {
72
-        $clone = clone $this;
73
-        $clone->setMethod($method);
74
-
75
-        return $clone;
76
-    }
77
-
78
-    /**
79
-     * @inheritDoc
80
-     */
81
-    public function getUri(): UriInterface
82
-    {
83
-        return $this->uri;
84
-    }
85
-
86
-    /**
87
-     * @inheritDoc
88
-     */
89
-    public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface
90
-    {
91
-        $clone = clone $this;
92
-        $clone->setUri($uri, $preserveHost);
93
-
94
-        return $clone;
95
-    }
96
-
97
-    /**
98
-     * @inheritDoc
99
-     */
100
-    public function getRequestTarget(): string
101
-    {
102
-        if ($this->requestTarget !== null) {
103
-            return $this->requestTarget;
104
-        }
105
-
106
-        $requestTarget = $this->uri->getPath();
107
-
108
-        // https://tools.ietf.org/html/rfc7230#section-5.3.1
109
-        // https://tools.ietf.org/html/rfc7230#section-2.7
110
-        //
111
-        // origin-form = absolute-path [ "?" query ]
112
-        // absolute-path = 1*( "/" segment )
113
-        if (strncmp($requestTarget, '/', 1) !== 0) {
114
-            return '/';
115
-        }
116
-
117
-        $queryString = $this->uri->getQuery();
118
-        if ($queryString !== '') {
119
-            $requestTarget .= '?' . $queryString;
120
-        }
121
-
122
-        return $requestTarget;
123
-    }
124
-
125
-    /**
126
-     * @inheritDoc
127
-     */
128
-    public function withRequestTarget($requestTarget): RequestInterface
129
-    {
130
-        $clone = clone $this;
131
-        $clone->setRequestTarget($requestTarget);
132
-
133
-        return $clone;
134
-    }
135
-
136
-    /**
137
-     * Sets the given method to the request
138
-     *
139
-     * @param string $method
140
-     *
141
-     * @throws InvalidArgumentException
142
-     */
143
-    final protected function setMethod($method): void
144
-    {
145
-        $this->validateMethod($method);
146
-
147
-        $this->method = $method;
148
-    }
149
-
150
-    /**
151
-     * Sets the given URI to the request
152
-     *
153
-     * @param mixed $uri
154
-     * @param bool $preserveHost
155
-     *
156
-     * @throws InvalidArgumentException
157
-     */
158
-    final protected function setUri($uri, $preserveHost = false): void
159
-    {
160
-        $this->uri = Uri::create($uri);
161
-
162
-        if ($preserveHost && $this->hasHeader('Host')) {
163
-            return;
164
-        }
165
-
166
-        $host = $this->uri->getHost();
167
-        if ($host === '') {
168
-            return;
169
-        }
170
-
171
-        $port = $this->uri->getPort();
172
-        if ($port !== null) {
173
-            $host .= ':' . (string) $port;
174
-        }
175
-
176
-        $this->setHeader('Host', $host, true);
177
-    }
178
-
179
-    /**
180
-     * Sets the given request target to the request
181
-     *
182
-     * @param mixed $requestTarget
183
-     *
184
-     * @throws InvalidArgumentException
185
-     */
186
-    final protected function setRequestTarget($requestTarget): void
187
-    {
188
-        $this->validateRequestTarget($requestTarget);
189
-
190
-        /** @var string $requestTarget */
191
-
192
-        $this->requestTarget = $requestTarget;
193
-    }
194
-
195
-    /**
196
-     * Validates the given method
197
-     *
198
-     * @link https://tools.ietf.org/html/rfc7230#section-3.1.1
199
-     *
200
-     * @param mixed $method
201
-     *
202
-     * @throws InvalidArgumentException
203
-     */
204
-    private function validateMethod($method): void
205
-    {
206
-        if ($method === '') {
207
-            throw new InvalidArgumentException('HTTP method cannot be an empty');
208
-        }
209
-
210
-        if (!is_string($method)) {
211
-            throw new InvalidArgumentException('HTTP method must be a string');
212
-        }
213
-
214
-        if (!preg_match(HeaderInterface::RFC7230_TOKEN_REGEX, $method)) {
215
-            throw new InvalidArgumentException('Invalid HTTP method');
216
-        }
217
-    }
218
-
219
-    /**
220
-     * Validates the given request target
221
-     *
222
-     * @param mixed $requestTarget
223
-     *
224
-     * @throws InvalidArgumentException
225
-     */
226
-    private function validateRequestTarget($requestTarget): void
227
-    {
228
-        if ($requestTarget === '') {
229
-            throw new InvalidArgumentException('HTTP request target cannot be an empty');
230
-        }
231
-
232
-        if (!is_string($requestTarget)) {
233
-            throw new InvalidArgumentException('HTTP request target must be a string');
234
-        }
235
-
236
-        if (!preg_match(self::RFC7230_REQUEST_TARGET_REGEX, $requestTarget)) {
237
-            throw new InvalidArgumentException('Invalid HTTP request target');
238
-        }
239
-    }
26
+	private const RFC7230_REQUEST_TARGET_REGEX = '/^[\x21-\x7E\x80-\xFF]+$/';
27
+
28
+	private string $method = self::METHOD_GET;
29
+	private UriInterface $uri;
30
+	private ?string $requestTarget = null;
31
+
32
+	/**
33
+	 * @param mixed $uri
34
+	 * @param array<string, string|string[]>|null $headers
35
+	 *
36
+	 * @throws InvalidArgumentException
37
+	 */
38
+	public function __construct(
39
+		?string $method = null,
40
+		$uri = null,
41
+		?array $headers = null,
42
+		?StreamInterface $body = null
43
+	) {
44
+		if ($method !== null) {
45
+			$this->setMethod($method);
46
+		}
47
+
48
+		$this->setUri($uri ?? '/');
49
+
50
+		if ($headers !== null) {
51
+			$this->setHeaders($headers);
52
+		}
53
+
54
+		if ($body !== null) {
55
+			$this->setBody($body);
56
+		}
57
+	}
58
+
59
+	/**
60
+	 * @inheritDoc
61
+	 */
62
+	public function getMethod(): string
63
+	{
64
+		return $this->method;
65
+	}
66
+
67
+	/**
68
+	 * @inheritDoc
69
+	 */
70
+	public function withMethod($method): RequestInterface
71
+	{
72
+		$clone = clone $this;
73
+		$clone->setMethod($method);
74
+
75
+		return $clone;
76
+	}
77
+
78
+	/**
79
+	 * @inheritDoc
80
+	 */
81
+	public function getUri(): UriInterface
82
+	{
83
+		return $this->uri;
84
+	}
85
+
86
+	/**
87
+	 * @inheritDoc
88
+	 */
89
+	public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface
90
+	{
91
+		$clone = clone $this;
92
+		$clone->setUri($uri, $preserveHost);
93
+
94
+		return $clone;
95
+	}
96
+
97
+	/**
98
+	 * @inheritDoc
99
+	 */
100
+	public function getRequestTarget(): string
101
+	{
102
+		if ($this->requestTarget !== null) {
103
+			return $this->requestTarget;
104
+		}
105
+
106
+		$requestTarget = $this->uri->getPath();
107
+
108
+		// https://tools.ietf.org/html/rfc7230#section-5.3.1
109
+		// https://tools.ietf.org/html/rfc7230#section-2.7
110
+		//
111
+		// origin-form = absolute-path [ "?" query ]
112
+		// absolute-path = 1*( "/" segment )
113
+		if (strncmp($requestTarget, '/', 1) !== 0) {
114
+			return '/';
115
+		}
116
+
117
+		$queryString = $this->uri->getQuery();
118
+		if ($queryString !== '') {
119
+			$requestTarget .= '?' . $queryString;
120
+		}
121
+
122
+		return $requestTarget;
123
+	}
124
+
125
+	/**
126
+	 * @inheritDoc
127
+	 */
128
+	public function withRequestTarget($requestTarget): RequestInterface
129
+	{
130
+		$clone = clone $this;
131
+		$clone->setRequestTarget($requestTarget);
132
+
133
+		return $clone;
134
+	}
135
+
136
+	/**
137
+	 * Sets the given method to the request
138
+	 *
139
+	 * @param string $method
140
+	 *
141
+	 * @throws InvalidArgumentException
142
+	 */
143
+	final protected function setMethod($method): void
144
+	{
145
+		$this->validateMethod($method);
146
+
147
+		$this->method = $method;
148
+	}
149
+
150
+	/**
151
+	 * Sets the given URI to the request
152
+	 *
153
+	 * @param mixed $uri
154
+	 * @param bool $preserveHost
155
+	 *
156
+	 * @throws InvalidArgumentException
157
+	 */
158
+	final protected function setUri($uri, $preserveHost = false): void
159
+	{
160
+		$this->uri = Uri::create($uri);
161
+
162
+		if ($preserveHost && $this->hasHeader('Host')) {
163
+			return;
164
+		}
165
+
166
+		$host = $this->uri->getHost();
167
+		if ($host === '') {
168
+			return;
169
+		}
170
+
171
+		$port = $this->uri->getPort();
172
+		if ($port !== null) {
173
+			$host .= ':' . (string) $port;
174
+		}
175
+
176
+		$this->setHeader('Host', $host, true);
177
+	}
178
+
179
+	/**
180
+	 * Sets the given request target to the request
181
+	 *
182
+	 * @param mixed $requestTarget
183
+	 *
184
+	 * @throws InvalidArgumentException
185
+	 */
186
+	final protected function setRequestTarget($requestTarget): void
187
+	{
188
+		$this->validateRequestTarget($requestTarget);
189
+
190
+		/** @var string $requestTarget */
191
+
192
+		$this->requestTarget = $requestTarget;
193
+	}
194
+
195
+	/**
196
+	 * Validates the given method
197
+	 *
198
+	 * @link https://tools.ietf.org/html/rfc7230#section-3.1.1
199
+	 *
200
+	 * @param mixed $method
201
+	 *
202
+	 * @throws InvalidArgumentException
203
+	 */
204
+	private function validateMethod($method): void
205
+	{
206
+		if ($method === '') {
207
+			throw new InvalidArgumentException('HTTP method cannot be an empty');
208
+		}
209
+
210
+		if (!is_string($method)) {
211
+			throw new InvalidArgumentException('HTTP method must be a string');
212
+		}
213
+
214
+		if (!preg_match(HeaderInterface::RFC7230_TOKEN_REGEX, $method)) {
215
+			throw new InvalidArgumentException('Invalid HTTP method');
216
+		}
217
+	}
218
+
219
+	/**
220
+	 * Validates the given request target
221
+	 *
222
+	 * @param mixed $requestTarget
223
+	 *
224
+	 * @throws InvalidArgumentException
225
+	 */
226
+	private function validateRequestTarget($requestTarget): void
227
+	{
228
+		if ($requestTarget === '') {
229
+			throw new InvalidArgumentException('HTTP request target cannot be an empty');
230
+		}
231
+
232
+		if (!is_string($requestTarget)) {
233
+			throw new InvalidArgumentException('HTTP request target must be a string');
234
+		}
235
+
236
+		if (!preg_match(self::RFC7230_REQUEST_TARGET_REGEX, $requestTarget)) {
237
+			throw new InvalidArgumentException('Invalid HTTP request target');
238
+		}
239
+	}
240 240
 }
Please login to merge, or discard this patch.