-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathResponse.php
256 lines (232 loc) · 8.89 KB
/
Response.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\HTTP;
use CodeIgniter\Cookie\Cookie;
use CodeIgniter\Cookie\CookieStore;
use CodeIgniter\Cookie\Exceptions\CookieException;
use CodeIgniter\HTTP\Exceptions\HTTPException;
use Config\App;
use Config\ContentSecurityPolicy as CSPConfig;
/**
* Representation of an outgoing, getServer-side response.
*
* Per the HTTP specification, this interface includes properties for
* each of the following:
*
* - Protocol version
* - Status code and reason phrase
* - Headers
* - Message body
*/
class Response extends Message implements MessageInterface, ResponseInterface
{
use ResponseTrait;
/**
* HTTP status codes
*
* @var array
*/
protected static $statusCodes = [
// 1xx: Informational
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing', // http://www.iana.org/go/rfc2518
103 => 'Early Hints', // http://www.ietf.org/rfc/rfc8297.txt
// 2xx: Success
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information', // 1.1
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status', // http://www.iana.org/go/rfc4918
208 => 'Already Reported', // http://www.iana.org/go/rfc5842
226 => 'IM Used', // 1.1; http://www.ietf.org/rfc/rfc3229.txt
// 3xx: Redirection
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found', // Formerly 'Moved Temporarily'
303 => 'See Other', // 1.1
304 => 'Not Modified',
305 => 'Use Proxy', // 1.1
306 => 'Switch Proxy', // No longer used
307 => 'Temporary Redirect', // 1.1
308 => 'Permanent Redirect', // 1.1; Experimental; http://www.ietf.org/rfc/rfc7238.txt
// 4xx: Client error
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
418 => "I'm a teapot", // April's Fools joke; http://www.ietf.org/rfc/rfc2324.txt
// 419 (Authentication Timeout) is a non-standard status code with unknown origin
421 => 'Misdirected Request', // http://www.iana.org/go/rfc7540 Section 9.1.2
422 => 'Unprocessable Entity', // http://www.iana.org/go/rfc4918
423 => 'Locked', // http://www.iana.org/go/rfc4918
424 => 'Failed Dependency', // http://www.iana.org/go/rfc4918
425 => 'Too Early', // https://datatracker.ietf.org/doc/draft-ietf-httpbis-replay/
426 => 'Upgrade Required',
428 => 'Precondition Required', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
429 => 'Too Many Requests', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
431 => 'Request Header Fields Too Large', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
451 => 'Unavailable For Legal Reasons', // http://tools.ietf.org/html/rfc7725
499 => 'Client Closed Request', // http://lxr.nginx.org/source/src/http/ngx_http_request.h#0133
// 5xx: Server error
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates', // 1.1; http://www.ietf.org/rfc/rfc2295.txt
507 => 'Insufficient Storage', // http://www.iana.org/go/rfc4918
508 => 'Loop Detected', // http://www.iana.org/go/rfc5842
510 => 'Not Extended', // http://www.ietf.org/rfc/rfc2774.txt
511 => 'Network Authentication Required', // http://www.ietf.org/rfc/rfc6585.txt
599 => 'Network Connect Timeout Error', // https://httpstatuses.com/599
];
/**
* The current reason phrase for this response.
* If empty string, will use the default provided for the status code.
*
* @var string
*/
protected $reason = '';
/**
* The current status code for this response.
* The status code is a 3-digit integer result code of the server's attempt
* to understand and satisfy the request.
*
* @var int
*/
protected $statusCode = 200;
/**
* If true, will not write output. Useful during testing.
*
* @var bool
*
* @internal Used for framework testing, should not be relied on otherwise
*/
protected $pretend = false;
/**
* Constructor
*
* @param App $config
*
* @todo Recommend removing reliance on config injection
*/
public function __construct($config)
{
// Default to a non-caching page.
// Also ensures that a Cache-control header exists.
$this->noCache();
// We need CSP object even if not enabled to avoid calls to non existing methods
$this->CSP = new ContentSecurityPolicy(new CSPConfig());
$this->CSPEnabled = $config->CSPEnabled;
// DEPRECATED COOKIE MANAGEMENT
$this->cookiePrefix = $config->cookiePrefix;
$this->cookieDomain = $config->cookieDomain;
$this->cookiePath = $config->cookiePath;
$this->cookieSecure = $config->cookieSecure;
$this->cookieHTTPOnly = $config->cookieHTTPOnly;
$this->cookieSameSite = $config->cookieSameSite ?? Cookie::SAMESITE_LAX;
$config->cookieSameSite = $config->cookieSameSite ?? Cookie::SAMESITE_LAX;
if (! in_array(strtolower($config->cookieSameSite ?: Cookie::SAMESITE_LAX), Cookie::ALLOWED_SAMESITE_VALUES, true)) {
throw CookieException::forInvalidSameSite($config->cookieSameSite);
}
$this->cookieStore = new CookieStore([]);
Cookie::setDefaults(config('Cookie') ?? [
// @todo Remove this fallback when deprecated `App` members are removed
'prefix' => $config->cookiePrefix,
'path' => $config->cookiePath,
'domain' => $config->cookieDomain,
'secure' => $config->cookieSecure,
'httponly' => $config->cookieHTTPOnly,
'samesite' => $config->cookieSameSite ?? Cookie::SAMESITE_LAX,
]);
// Default to an HTML Content-Type. Devs can override if needed.
$this->setContentType('text/html');
}
/**
* Turns "pretend" mode on or off to aid in testing.
* Note that this is not a part of the interface so
* should not be relied on outside of internal testing.
*
* @return $this
*/
public function pretend(bool $pretend = true)
{
$this->pretend = $pretend;
return $this;
}
/**
* Gets the response status code.
*
* The status code is a 3-digit integer result code of the getServer's attempt
* to understand and satisfy the request.
*
* @return int Status code.
*/
public function getStatusCode(): int
{
if (empty($this->statusCode)) {
throw HTTPException::forMissingResponseStatus();
}
return $this->statusCode;
}
/**
* Gets the response response phrase associated with the status code.
*
* @see http://tools.ietf.org/html/rfc7231#section-6
* @see http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
* @deprecated Use getReasonPhrase()
*
* @codeCoverageIgnore
*/
public function getReason(): string
{
return $this->getReasonPhrase();
}
/**
* Gets the response reason phrase associated with the status code.
*
* Because a reason phrase is not a required element in a response
* status line, the reason phrase value MAY be null. Implementations MAY
* choose to return the default RFC 7231 recommended reason phrase (or those
* listed in the IANA HTTP Status Code Registry) for the response's
* status code.
*
* @see http://tools.ietf.org/html/rfc7231#section-6
* @see http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
*
* @return string Reason phrase; must return an empty string if none present.
*/
public function getReasonPhrase()
{
if ($this->reason === '') {
return ! empty($this->statusCode) ? static::$statusCodes[$this->statusCode] : '';
}
return $this->reason;
}
}