1 | <?php |
||||||
2 | declare(strict_types=1); |
||||||
3 | defined('BASEPATH') OR exit('No direct script access allowed'); |
||||||
4 | |||||||
5 | require_once('RESTAuth.php'); |
||||||
6 | require_once('RESTResponse.php'); |
||||||
7 | require_once('RESTExceptions.php'); |
||||||
8 | |||||||
9 | class REST |
||||||
10 | { |
||||||
11 | /** |
||||||
12 | * [private description] |
||||||
13 | * @var [type] |
||||||
0 ignored issues
–
show
Documentation
Bug
introduced
by
Loading history...
|
|||||||
14 | */ |
||||||
15 | private $ci; |
||||||
16 | |||||||
17 | /** |
||||||
18 | * [private description] |
||||||
19 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
20 | */ |
||||||
21 | private $api_key_limit_column; |
||||||
22 | |||||||
23 | /** |
||||||
24 | * [private description] |
||||||
25 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
26 | */ |
||||||
27 | private $api_key_column; |
||||||
28 | |||||||
29 | /** |
||||||
30 | * [private description] |
||||||
31 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
32 | */ |
||||||
33 | private $per_hour; |
||||||
34 | |||||||
35 | /** |
||||||
36 | * [private description] |
||||||
37 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
38 | */ |
||||||
39 | private $ip_per_hour; |
||||||
40 | |||||||
41 | /** |
||||||
42 | * [private description] |
||||||
43 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
44 | */ |
||||||
45 | private $show_header; |
||||||
46 | |||||||
47 | /** |
||||||
48 | * [private description] |
||||||
49 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
50 | */ |
||||||
51 | private $whitelist; |
||||||
52 | |||||||
53 | /** |
||||||
54 | * [private description] |
||||||
55 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
56 | */ |
||||||
57 | private $checked_rate_limit = false; |
||||||
58 | |||||||
59 | /** |
||||||
60 | * [private description] |
||||||
61 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
62 | */ |
||||||
63 | private $header_prefix; |
||||||
64 | |||||||
65 | /** |
||||||
66 | * [private description] |
||||||
67 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
68 | */ |
||||||
69 | private $limit_api; |
||||||
70 | |||||||
71 | /** |
||||||
72 | * [public description] |
||||||
73 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
74 | */ |
||||||
75 | public $userId; |
||||||
76 | |||||||
77 | /** |
||||||
78 | * [public description] |
||||||
79 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
80 | */ |
||||||
81 | public $apiKeyHeader; |
||||||
82 | |||||||
83 | /** |
||||||
84 | * [public description] |
||||||
85 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
86 | */ |
||||||
87 | public $token; |
||||||
88 | |||||||
89 | /** |
||||||
90 | * [public description] |
||||||
91 | * @var [type] |
||||||
0 ignored issues
–
show
|
|||||||
92 | */ |
||||||
93 | public $allowedIps; |
||||||
94 | |||||||
95 | /** |
||||||
96 | * [PACKAGE description] |
||||||
97 | * @var string |
||||||
98 | */ |
||||||
99 | const PACKAGE = "francis94c/ci-rest"; |
||||||
100 | |||||||
101 | /** |
||||||
102 | * [RATE_LIMIT description] |
||||||
103 | * @var string |
||||||
104 | */ |
||||||
105 | const RATE_LIMIT = "RateLimit"; |
||||||
106 | |||||||
107 | /** |
||||||
108 | * [__construct This is the part of the code that takes care of all |
||||||
109 | * authentiations. allowing you to focus on building wonderful things at REST. |
||||||
110 | * pun intended ;-)] |
||||||
111 | * @param array|null $params Initialization parameters from the Slint system. |
||||||
112 | * There's no use for this arg yet. |
||||||
113 | */ |
||||||
114 | function __construct(?array $params=null) |
||||||
0 ignored issues
–
show
The parameter
$params is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.
Loading history...
|
|||||||
115 | { |
||||||
116 | $this->ci =& get_instance(); |
||||||
0 ignored issues
–
show
The function
get_instance was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
117 | |||||||
118 | if ($this->ci->input->is_cli_request()) return; |
||||||
119 | |||||||
120 | // Load Config If Exists. |
||||||
121 | $this->ci->config->load('rest', true, true); |
||||||
122 | |||||||
123 | // Load Database. |
||||||
124 | $this->ci->load->database(); |
||||||
125 | |||||||
126 | // load URL Helper |
||||||
127 | $this->ci->load->helper('url'); |
||||||
128 | |||||||
129 | // Load REST Helper. |
||||||
130 | $this->ci->load->splint(self::PACKAGE, '%rest'); |
||||||
131 | |||||||
132 | // Load Model. |
||||||
133 | $this->ci->load->splint(self::PACKAGE, '*RESTModel', 'rest_model'); |
||||||
134 | $this->rest_model =& $this->ci->rest_model; |
||||||
0 ignored issues
–
show
|
|||||||
135 | |||||||
136 | $config = [ |
||||||
137 | 'users_table' => $this->ci->config->item('rest')['basic_auth']['users_table'] ?? null, |
||||||
138 | 'users_id_column' => $this->ci->config->item('rest')['basic_auth']['id_column'] ?? null, |
||||||
139 | 'users_username_column' => $this->ci->config->item('rest')['basic_auth']['username_column'] ?? null, |
||||||
140 | 'users_email_column' => $this->ci->config->item('rest')['basic_auth']['email_column'] ?? null, |
||||||
141 | 'users_password_column' => $this->ci->config->item('rest')['basic_auth']['password_column'] ?? null, |
||||||
142 | 'api_key_table' => $this->ci->config->item('rest')['api_key_auth']['api_key_table'] ?? null, |
||||||
143 | 'api_key_column' => $this->ci->config->item('rest')['api_key_auth']['api_key_column'] ?? null, |
||||||
144 | 'api_key_limit_column' => $this->ci->config->item('rest')['api_key_auth']['api_key_limit_column'] ?? null |
||||||
145 | ]; |
||||||
146 | |||||||
147 | $this->rest_model->init($config); |
||||||
148 | |||||||
149 | // Load Variable(s) from Config. |
||||||
150 | $this->allowedIps = $this->ci->config->item('rest')['allowed_ips'] ?? ['127.0.0.1', '[::1]']; |
||||||
151 | $this->apiKeyHeader = $this->ci->config->item('rest')['api_key_header'] ?? 'X-API-KEY'; |
||||||
152 | $this->api_key_limit_column = $this->ci->config->item('rest')['api_key_auth']['api_key_limit_column'] ?? null; |
||||||
153 | $this->api_key_column = $this->ci->config->item('rest')['api_key_auth']['api_key_column'] ?? null; |
||||||
154 | $this->limit_api = $this->ci->config->item('rest')['api_limiter']['api_limiter'] ?? false; |
||||||
155 | $this->per_hour = $this->ci->config->item('rest')['api_limiter']['per_hour'] ?? 100; |
||||||
156 | $this->ip_per_hour = $this->ci->config->item('rest')['api_limiter']['ip_per_hour'] ?? 50; |
||||||
157 | $this->show_header = $this->ci->config->item('rest')['api_limiter']['show_header'] ?? null; |
||||||
158 | $this->whitelist = $this->ci->config->item('rest')['api_limiter']['whitelist'] ?? null; |
||||||
159 | $this->header_prefix = $this->ci->config->item('rest')['api_limiter']['header_prefix'] ?? 'X-RateLimit-'; |
||||||
160 | |||||||
161 | // Limit Only? |
||||||
162 | //if ($this->ci->config->item('rest')['api_limiter']['api_limit_only'] ?? false) { |
||||||
163 | //return; |
||||||
164 | //} |
||||||
165 | |||||||
166 | // Authenticate |
||||||
167 | $this->authenticate(); |
||||||
168 | |||||||
169 | // Generic Rate Limiter. |
||||||
170 | if ($this->limit_api && !$this->checked_rate_limit && |
||||||
171 | ($this->ci->config->item('rest')['api_limiter']['limit_by_ip'] ?? false)) { |
||||||
172 | $this->api_rest_limit_by_ip_address(); |
||||||
173 | } |
||||||
174 | |||||||
175 | log_message('debug', 'REST Request Authenticated and REST Library Initialized.'); |
||||||
0 ignored issues
–
show
The function
log_message was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
176 | } |
||||||
177 | |||||||
178 | /** |
||||||
179 | * [authenticate description] |
||||||
180 | * @date 2020-01-30 |
||||||
181 | */ |
||||||
182 | private function authenticate():void |
||||||
183 | { |
||||||
184 | $auths = null; |
||||||
185 | |||||||
186 | $globalAuths = $this->ci->config->item('rest')['global_auth'] ?? null; |
||||||
187 | |||||||
188 | if ($globalAuths != null) { |
||||||
189 | if (is_array($globalAuths)) { |
||||||
190 | $auths = $globalAuths; |
||||||
191 | } else { |
||||||
192 | $auths = [$globalAuths]; |
||||||
193 | } |
||||||
194 | } |
||||||
195 | |||||||
196 | $uri_auths = $this->ci->config->item('rest')['uri_auth'] ?? null; |
||||||
197 | |||||||
198 | // Match Auth Routes. |
||||||
199 | // The below algorithm is similar to the one Code Igniter uses in its |
||||||
200 | // Routing Class. |
||||||
201 | if ($uri_auths != null || is_array($uri_auths)) { |
||||||
202 | foreach ($uri_auths as $uri => $auth_array) { |
||||||
203 | // Convert wildcards to RegEx. |
||||||
204 | $uri = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $uri); |
||||||
205 | if (preg_match('#^'.$uri.'$#', uri_string())) { |
||||||
0 ignored issues
–
show
The function
uri_string was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
206 | // Assign Authentication Steps. |
||||||
207 | if (is_array($auth_array)) { |
||||||
208 | foreach ($auth_array as $auth) { |
||||||
209 | $auths[] = $auth; |
||||||
210 | } |
||||||
211 | } else { |
||||||
212 | $auths[] = $auth_array; |
||||||
213 | } |
||||||
214 | } |
||||||
215 | break; |
||||||
216 | } |
||||||
217 | } |
||||||
218 | |||||||
219 | //$auths = $this->ci->config->item('rest')['uri_auth'][uri_string()] ?? null; |
||||||
220 | if ($auths == null) return; // No authentication(s) to carry out. |
||||||
221 | |||||||
222 | // $this->process_auth() terminates the script if authentication fails |
||||||
223 | // It will call the callable in the rest.php config file under |
||||||
224 | // response_callbacks which matches the necesarry RESTResponse constant |
||||||
225 | // before exiting. Which callable is called in any situation is documented |
||||||
226 | // in README.md |
||||||
227 | //if (is_scalar($auths)) { |
||||||
228 | //$this->process_auth($auths); |
||||||
229 | //return; |
||||||
230 | //} |
||||||
231 | |||||||
232 | foreach ($auths as $auth) $this->process_auth($auth); |
||||||
233 | } |
||||||
234 | /** |
||||||
235 | * [process_auth description] |
||||||
236 | * @param string $auth [description] |
||||||
237 | * @return bool [description] |
||||||
238 | */ |
||||||
239 | private function process_auth(string &$auth):void { |
||||||
240 | switch ($auth) { |
||||||
241 | case RESTAuth::IP: $this->ip_auth(); break; |
||||||
242 | case RESTAuth::BASIC: $this->basic_auth(); break; |
||||||
243 | case RESTAuth::API_KEY: $this->api_key_auth(); break; |
||||||
244 | case RESTAuth::OAUTH2: $this->bearer_auth(RESTAuth::OAUTH2); break; |
||||||
245 | case RESTAuth::BEARER: $this->bearer_auth(); break; |
||||||
246 | default: $this->custom_auth($auth); |
||||||
247 | } |
||||||
248 | } |
||||||
249 | /** |
||||||
250 | * [ip_auth description] |
||||||
251 | */ |
||||||
252 | private function ip_auth():void { |
||||||
253 | if (!in_array($this->ci->input->ip_address(), $this->allowedIps)) { |
||||||
254 | $this->handle_response(RESTResponse::UN_AUTHORIZED, RESTAuth::IP); // Exits. |
||||||
255 | } |
||||||
256 | } |
||||||
257 | /** |
||||||
258 | * [bearer_auth description] |
||||||
259 | */ |
||||||
260 | private function bearer_auth($auth=RESTAuth::BEARER):void { |
||||||
261 | $authorization = $this->get_authorization_header(); |
||||||
262 | if ($authorization == null || substr_count($authorization, " ") != 1) { |
||||||
0 ignored issues
–
show
|
|||||||
263 | $this->handle_response(RESTResponse::BAD_REQUEST, $auth); // Exits. |
||||||
264 | } |
||||||
265 | $token = explode(" ", $authorization); |
||||||
266 | if ($token[0] != "Bearer") { |
||||||
267 | $this->handle_response(RESTResponse::BAD_REQUEST, $auth); // Exits. |
||||||
268 | } |
||||||
269 | $this->token = $token[1]; |
||||||
270 | // Call Up Custom Implemented Bearer/Token Authorization. |
||||||
271 | // Callback Check. |
||||||
272 | if (!isset($this->ci->config->item('rest')['auth_callbacks'][$auth])) { |
||||||
273 | $this->handle_response(RESTResponse::NOT_IMPLEMENTED, $auth); // Exits. |
||||||
274 | } |
||||||
275 | // Authorization. |
||||||
276 | if (!$this->ci->config->item('rest')['auth_callbacks'][$auth]($this, $this->token)) { |
||||||
277 | $this->handle_response(RESTResponse::UN_AUTHORIZED, $auth); // Exits. |
||||||
278 | } |
||||||
279 | } |
||||||
280 | /** |
||||||
281 | * [basic_auth description] |
||||||
282 | */ |
||||||
283 | private function basic_auth():void { |
||||||
284 | $username = $_SERVER['PHP_AUTH_USER'] ?? null; |
||||||
285 | $password = $_SERVER['PHP_AUTH_PW'] ?? null; |
||||||
286 | if (!$username || !$password) $this->handle_response(RESTResponse::BAD_REQUEST, RESTAuth::BASIC); // Exits. |
||||||
287 | if (!$this->rest_model->basicAuth($this, $username, $password)) $this->handle_response(RESTResponse::UN_AUTHORIZED, RESTAuth::BASIC); // Exits. |
||||||
288 | } |
||||||
289 | /** |
||||||
290 | * [api_key_auth description] |
||||||
291 | */ |
||||||
292 | private function api_key_auth():void |
||||||
293 | { |
||||||
294 | if (uri_string() == '') return; |
||||||
0 ignored issues
–
show
The function
uri_string was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
295 | |||||||
296 | if (!$this->ci->input->get_request_header($this->apiKeyHeader, true)) { |
||||||
297 | // if (!isset($_SERVER['HTTP_' . str_replace("-", "_", $this->apiKeyHeader)])) { |
||||||
298 | $this->handle_response(RESTResponse::BAD_REQUEST, RESTAuth::API_KEY); // Exits. |
||||||
299 | } |
||||||
300 | |||||||
301 | $apiKey = $this->rest_model->getAPIKeyData( |
||||||
302 | $this->ci->input->get_request_header($this->apiKeyHeader, true) |
||||||
303 | ); |
||||||
304 | |||||||
305 | if ($apiKey == null) { |
||||||
306 | $this->handle_response(RESTResponse::UN_AUTHORIZED, RESTAuth::API_KEY); // Exits. |
||||||
307 | } |
||||||
308 | |||||||
309 | // API KEY Auth Passed Above. |
||||||
310 | if ($this->limit_api && $this->api_key_limit_column != null && $apiKey[$this->api_key_limit_column] == 1) { |
||||||
311 | // Trunctate Rate Limit Data. |
||||||
312 | $this->rest_model->truncateRatelimitData(); |
||||||
313 | // Check Whitelist. |
||||||
314 | if (in_array($this->ci->input->ip_address(), $this->whitelist)) { |
||||||
315 | $this->checked_rate_limit = true; // Ignore Limit By IP. |
||||||
316 | return; |
||||||
317 | } |
||||||
318 | // Should we acyually Limit? |
||||||
319 | if ($this->per_hour > 0) { |
||||||
320 | $client = hash('md5', $this->ci->input->ip_address() . "%" . $apiKey[$this->api_key_column]); |
||||||
321 | $limitData = $this->rest_model->getLimitData($client, '_api_keyed_user'); |
||||||
322 | if ($limitData == null) { |
||||||
323 | $limitData = []; |
||||||
324 | $limitData['count'] = 0; |
||||||
325 | $limitData['reset_epoch'] = gmdate('d M Y H:i:s', time() + (60 * 60)); |
||||||
326 | $limitData['start'] = date('d M Y H:i:s'); |
||||||
327 | } |
||||||
328 | if ($this->per_hour - $limitData['count'] > 0) { |
||||||
329 | if (!$this->rest_model->insertLimitData($client, '_api_keyed_user')) { |
||||||
330 | $this->handle_response(RESTResponse::INTERNAL_SERVER_ERROR, self::RATE_LIMIT); // Exits. |
||||||
331 | } |
||||||
332 | ++$limitData['count']; |
||||||
333 | if ($this->show_header) { |
||||||
334 | header($this->header_prefix.'Limit: '.$this->per_hour); |
||||||
335 | header($this->header_prefix.'Remaining: '.($this->per_hour - $limitData['count'])); |
||||||
336 | header($this->header_prefix.'Reset: '.strtotime($limitData['reset_epoch'])); |
||||||
337 | } |
||||||
338 | } else { |
||||||
339 | header('Retry-After: '.(strtotime($limitData['reset_epoch']) - strtotime(gmdate('d M Y H:i:s')))); |
||||||
340 | $this->handle_response(RESTResponse::TOO_MANY_REQUESTS, self::RATE_LIMIT); // Exits. |
||||||
341 | } |
||||||
342 | } |
||||||
343 | } |
||||||
344 | $this->checked_rate_limit = true; // Ignore Limit By IP. |
||||||
345 | } |
||||||
346 | /** |
||||||
347 | * [api_rest_limit_by_ip_address description] |
||||||
348 | * TODO: Implement. |
||||||
349 | */ |
||||||
350 | private function api_rest_limit_by_ip_address():void { |
||||||
351 | // Trunctate Rate Limit Data. |
||||||
352 | $this->rest_model->truncateRatelimitData(); |
||||||
353 | // Check Whitelist. |
||||||
354 | if (in_array($this->ci->input->ip_address(), $this->whitelist)) return; |
||||||
355 | // Should we acyually Limit? |
||||||
356 | if ($this->ip_per_hour > 0) { |
||||||
357 | $client = hash('md5', $this->ci->input->ip_address()); |
||||||
358 | $limitData = $this->rest_model->getLimitData($client, '_ip_address'); |
||||||
359 | if ($limitData == null) { |
||||||
360 | $limitData = []; |
||||||
361 | $limitData['count'] = 0; |
||||||
362 | $limitData['reset_epoch'] = gmdate('d M Y H:i:s', time() + (60 * 60)); |
||||||
363 | $limitData['start'] = date('d M Y H:i:s'); |
||||||
364 | } |
||||||
365 | if ($this->ip_per_hour - $limitData['count'] > 0) { |
||||||
366 | if (!$this->rest_model->insertLimitData($client, '_ip_address')) { |
||||||
367 | $this->handle_response(RESTResponse::INTERNAL_SERVER_ERROR, self::RATE_LIMIT); // Exits. |
||||||
368 | } |
||||||
369 | ++$limitData['count']; |
||||||
370 | if ($this->show_header) { |
||||||
371 | header($this->header_prefix.'Limit: '.$this->ip_per_hour); |
||||||
372 | header($this->header_prefix.'Remaining: '.($this->ip_per_hour - $limitData['count'])); |
||||||
373 | header($this->header_prefix.'Reset: '.strtotime($limitData['reset_epoch'])); |
||||||
374 | } |
||||||
375 | } else { |
||||||
376 | header('Retry-After: '.(strtotime($limitData['reset_epoch']) - strtotime(gmdate('d M Y H:i:s')))); |
||||||
377 | $this->handle_response(RESTResponse::TOO_MANY_REQUESTS, self::RATE_LIMIT); // Exits. |
||||||
378 | } |
||||||
379 | } |
||||||
380 | } |
||||||
381 | /** |
||||||
382 | * [custom_auth description] |
||||||
383 | * @param string $auth [description] |
||||||
384 | */ |
||||||
385 | private function custom_auth(string &$auth):void |
||||||
386 | { |
||||||
387 | // Header Check. |
||||||
388 | if (!isset($_SERVER[$auth])) { |
||||||
389 | $this->handle_response(RESTResponse::BAD_REQUEST, $auth); |
||||||
390 | } |
||||||
391 | // Callback Check. |
||||||
392 | if (!isset($this->ci->config->item('rest')['auth_callbacks'][$auth])) { |
||||||
393 | $this->handle_response(RESTResponse::NOT_IMPLEMENTED, $auth); // Exits. |
||||||
394 | } |
||||||
395 | // Authentication. |
||||||
396 | if (!$this->ci->config->item('rest')['auth_callbacks'][$auth]($this, $this->ci->security->xss_clean($_SERVER[$auth]))) { |
||||||
397 | $this->handle_response(RESTResponse::UN_AUTHORIZED, $auth); // Exits. |
||||||
398 | } |
||||||
399 | } |
||||||
400 | /** |
||||||
401 | * [get_authorization_header description] |
||||||
402 | * @return [type] [description] |
||||||
0 ignored issues
–
show
|
|||||||
403 | */ |
||||||
404 | private function get_authorization_header():?string |
||||||
405 | { |
||||||
406 | if (isset($_SERVER['Authorization'])) { |
||||||
407 | return trim($_SERVER["Authorization"]); |
||||||
408 | } else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI |
||||||
409 | return trim($_SERVER["HTTP_AUTHORIZATION"]); |
||||||
410 | } elseif (function_exists('apache_request_headers')) { |
||||||
411 | $requestHeaders = apache_request_headers(); |
||||||
412 | |||||||
413 | // Avoid Surprises. |
||||||
414 | $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); |
||||||
0 ignored issues
–
show
It seems like
$requestHeaders can also be of type false ; however, parameter $input of array_keys() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
It seems like
$requestHeaders can also be of type false ; however, parameter $input of array_values() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
415 | |||||||
416 | if (isset($requestHeaders['Authorization'])) { |
||||||
417 | return trim($requestHeaders['Authorization']); |
||||||
418 | } |
||||||
419 | } |
||||||
420 | return null; |
||||||
421 | } |
||||||
422 | |||||||
423 | /** |
||||||
424 | * [handle_response description] |
||||||
425 | * @param int $code [description] |
||||||
426 | */ |
||||||
427 | private function handle_response(int $code, $auth=null):void |
||||||
428 | { |
||||||
429 | http_response_code($code); |
||||||
430 | header("Content-Type: application/json"); |
||||||
431 | if (isset($this->ci->config->item('rest')['response_callbacks'][$code])) { |
||||||
432 | $this->ci->config->item('rest')['response_callbacks'][$code]($auth); |
||||||
433 | } |
||||||
434 | if (ENVIRONMENT != 'testing') exit($code); |
||||||
0 ignored issues
–
show
|
|||||||
435 | throw new Exception("Error $code in $auth", $code); |
||||||
436 | } |
||||||
437 | } |
||||||
438 | ?> |
||||||
0 ignored issues
–
show
It is not recommended to use PHP's closing tag
?> in files other than templates.
Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore. A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.
Loading history...
|
|||||||
439 |