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
|
<?php
namespace Trails;
/**
* This class represents a response returned by a controller that was asked to
* perform for a given request. A Response contains the body, status and
* additional headers which can be renderer back to the client.
*
* @package trails
*
* @author mlunzena
* @copyright (c) Authors
* @version $Id: trails.php 7001 2008-04-04 11:20:27Z mlunzena $
*/
class Response
{
public $body = '';
public $status;
public $reason;
public $headers = [];
/**
* Constructor.
*
* @param string $body the body of the response defaulting to ''
* @param array $headers an array of additional headers defaulting to an
* empty array
* @param int|null $status the status code of the response defaulting to a
* regular 200
* @param string|null $reason the descriptional reason for a status code defaulting to
* the standard reason phrases defined in RFC 2616
*/
public function __construct(
string $body = '',
array $headers = [],
?int $status = null,
?string $reason = null
) {
$this->set_body($body);
$this->headers = $headers;
if (isset($status)) {
$this->set_status($status, $reason);
}
}
/**
* Sets the body of the response.
*
* @param string $body the body
* @return static this response object. Useful for cascading method calls.
*/
public function set_body($body)
{
$this->body = $body;
return $this;
}
/**
* Sets the status code and an optional custom reason. If none is given, the
* standard reason phrase as of RFC 2616 is used.
*
* @param integer $status the status code
* @param string $reason the custom reason, defaulting to the one given in RFC 2616
* @return static this response object. Useful for cascading method calls.
*/
public function set_status($status, $reason = null)
{
$this->status = $status;
$this->reason = $reason ?? self::get_reason($status);
return $this;
}
/**
* Returns the reason phrase of this response according to RFC2616.
*
* @param int $status the response's status
* @return string the reason phrase for this response's status
*/
public static function get_reason($status)
{
return match ($status) {
100 => 'Continue',
101 => 'Switching Protocols',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => '(Unused)',
307 => 'Temporary Redirect',
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',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
default => '',
};
}
/**
* Adds an additional header to the response.
*
* @param string $key the left hand key part
* @param string $value the right hand value part
* @return static this response object. Useful for cascading method calls.
*/
public function add_header($key, $value)
{
$this->headers[$key] = $value;
return $this;
}
/**
* Outputs this response to the client using "echo" and "header".
* @return void
*/
public function output()
{
if (isset($this->status)) {
$this->send_header(
"HTTP/1.1 {$this->status} {$this->reason}",
true,
$this->status
);
}
foreach ($this->headers as $k => $v) {
$this->send_header("{$k}: {$v}");
}
echo $this->body;
}
/**
* Internally used function to actually send headers
*
* @param string $header the HTTP header
* @param bool $replace optional; TRUE if previously sent header should be
* replaced - FALSE otherwise (default)
* @param integer $status optional; the HTTP response code
* @return void
*/
public function send_header($header, $replace = false, $status = null)
{
if (isset($status)) {
header($header, $replace, $status);
} else {
header($header, $replace);
}
}
}
|