Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
99.12% |
113 / 114 |
|
97.92% |
47 / 48 |
CRAP | |
0.00% |
0 / 1 |
Request | |
99.12% |
113 / 114 |
|
97.92% |
47 / 48 |
99 | |
0.00% |
0 / 1 |
__construct | |
95.45% |
21 / 22 |
|
0.00% |
0 / 1 |
11 | |||
create | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createWithBasePath | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setAuth | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getAuth | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasAuth | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isGet | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isHead | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isPost | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isPut | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isDelete | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isTrace | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isOptions | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isConnect | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isPatch | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isSecure | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
3 | |||
getDocumentRoot | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getMethod | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPort | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getScheme | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
getHost | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
getFullHost | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
5 | |||
getIp | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
6 | |||
getCookie | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getServer | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getEnv | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getBasePath | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getUriString | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getFullUriString | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getSegment | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getSegments | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setBasePath | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
hasFiles | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getQuery | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPost | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getFiles | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPut | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPatch | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getDelete | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getQueryData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasQueryData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getParsedData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasParsedData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getRawData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasRawData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__get | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
14 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (https://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@noladev.com> |
7 | * @copyright Copyright (c) 2009-2025 NOLA Interactive, LLC. |
8 | * @license https://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Http\Server; |
15 | |
16 | use Pop\Http\Auth; |
17 | use Pop\Http\Uri; |
18 | use Pop\Http\AbstractRequest; |
19 | use Pop\Mime\Part\Body; |
20 | |
21 | /** |
22 | * HTTP server request class |
23 | * |
24 | * @category Pop |
25 | * @package Pop\Http |
26 | * @author Nick Sagona, III <dev@noladev.com> |
27 | * @copyright Copyright (c) 2009-2025 NOLA Interactive, LLC. |
28 | * @license https://www.popphp.org/license New BSD License |
29 | * @version 5.3.2 |
30 | */ |
31 | class Request extends AbstractRequest |
32 | { |
33 | |
34 | /** |
35 | * Server request data object |
36 | * @var ?Data |
37 | */ |
38 | protected ?Data $data = null; |
39 | |
40 | /** |
41 | * COOKIE array |
42 | * @var array |
43 | */ |
44 | protected array $cookie = []; |
45 | |
46 | /** |
47 | * SERVER array |
48 | * @var array |
49 | */ |
50 | protected array $server = []; |
51 | |
52 | /** |
53 | * ENV array |
54 | * @var array |
55 | */ |
56 | protected array $env = []; |
57 | |
58 | /** |
59 | * HTTP auth object |
60 | * @var ?Auth |
61 | */ |
62 | protected ?Auth $auth = null; |
63 | |
64 | /** |
65 | * Constructor |
66 | * |
67 | * Instantiate the request object |
68 | * |
69 | * @param Uri|string|null $uri |
70 | * @param mixed $filters |
71 | * @param mixed $streamToFile |
72 | * @throws Exception|\Pop\Http\Exception |
73 | */ |
74 | public function __construct(Uri|string|null $uri = null, mixed $filters = null, mixed $streamToFile = null) |
75 | { |
76 | parent::__construct($uri); |
77 | |
78 | $this->cookie = (isset($_COOKIE)) ? $_COOKIE : []; |
79 | $this->server = (isset($_SERVER)) ? $_SERVER : []; |
80 | $this->env = (isset($_ENV)) ? $_ENV : []; |
81 | |
82 | // Get any possible request headers |
83 | if (function_exists('getallheaders')) { |
84 | $this->addHeaders(getallheaders()); |
85 | } else { |
86 | foreach ($_SERVER as $key => $value) { |
87 | if (str_starts_with($key, 'HTTP_')) { |
88 | $key = ucfirst(strtolower(str_replace('HTTP_', '', $key))); |
89 | if (str_contains($key, '_')) { |
90 | $ary = explode('_', $key); |
91 | foreach ($ary as $k => $v){ |
92 | $ary[$k] = ucfirst(strtolower($v)); |
93 | } |
94 | $key = implode('-', $ary); |
95 | } |
96 | $this->addHeader($key, $value); |
97 | } |
98 | } |
99 | } |
100 | |
101 | if ($this->hasHeader('Authorization')) { |
102 | $this->setAuth(Auth::parse($this->getHeader('Authorization'))); |
103 | } |
104 | |
105 | $this->data = new Data( |
106 | $this->getHeaderValue('Content-Type'), $this->getHeaderValue('Content-Encoding'), $filters, $streamToFile |
107 | ); |
108 | |
109 | if ($this->data->hasRawData()) { |
110 | $this->body = new Body($this->data->getRawData()); |
111 | } |
112 | } |
113 | |
114 | /** |
115 | * Factory to create a new request object |
116 | * |
117 | * @param ?Uri $uri |
118 | * @param mixed $filters |
119 | * @param mixed $streamToFile |
120 | * @throws Exception|\Pop\Http\Exception |
121 | * @return Request |
122 | */ |
123 | public static function create(?Uri $uri = null, mixed $filters = null, mixed $streamToFile = null): Request |
124 | { |
125 | return new self($uri, $filters, $streamToFile); |
126 | } |
127 | |
128 | /** |
129 | * Factory to create a new request object with a base path reference for the request URI |
130 | * |
131 | * @param string $basePath |
132 | * @param mixed $filters |
133 | * @param mixed $streamToFile |
134 | * @return Request |
135 | */ |
136 | public static function createWithBasePath(string $basePath, mixed $filters = null, mixed $streamToFile = null): Request |
137 | { |
138 | return new self(new Uri(null, $basePath), $filters, $streamToFile); |
139 | } |
140 | |
141 | /** |
142 | * Set the auth object |
143 | * |
144 | * @param Auth $auth |
145 | * @return Request |
146 | */ |
147 | public function setAuth(Auth $auth): Request |
148 | { |
149 | $this->auth = $auth; |
150 | return $this; |
151 | } |
152 | |
153 | /** |
154 | * Get the auth object |
155 | * |
156 | * @return Auth |
157 | */ |
158 | public function getAuth(): Auth |
159 | { |
160 | return $this->auth; |
161 | } |
162 | |
163 | /** |
164 | * Has auth object |
165 | * |
166 | * @return bool |
167 | */ |
168 | public function hasAuth(): bool |
169 | { |
170 | return ($this->auth !== null); |
171 | } |
172 | |
173 | /** |
174 | * Return whether or not the method is GET |
175 | * |
176 | * @return bool |
177 | */ |
178 | public function isGet(): bool |
179 | { |
180 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'GET')); |
181 | } |
182 | |
183 | /** |
184 | * Return whether or not the method is HEAD |
185 | * |
186 | * @return bool |
187 | */ |
188 | public function isHead(): bool |
189 | { |
190 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'HEAD')); |
191 | } |
192 | |
193 | /** |
194 | * Return whether or not the method is POST |
195 | * |
196 | * @return bool |
197 | */ |
198 | public function isPost(): bool |
199 | { |
200 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'POST')); |
201 | } |
202 | |
203 | /** |
204 | * Return whether or not the method is PUT |
205 | * |
206 | * @return bool |
207 | */ |
208 | public function isPut(): bool |
209 | { |
210 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'PUT')); |
211 | } |
212 | |
213 | /** |
214 | * Return whether or not the method is DELETE |
215 | * |
216 | * @return bool |
217 | */ |
218 | public function isDelete(): bool |
219 | { |
220 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'DELETE')); |
221 | } |
222 | |
223 | /** |
224 | * Return whether or not the method is TRACE |
225 | * |
226 | * @return bool |
227 | */ |
228 | public function isTrace(): bool |
229 | { |
230 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'TRACE')); |
231 | } |
232 | |
233 | /** |
234 | * Return whether or not the method is OPTIONS |
235 | * |
236 | * @return bool |
237 | */ |
238 | public function isOptions(): bool |
239 | { |
240 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'OPTIONS')); |
241 | } |
242 | |
243 | /** |
244 | * Return whether or not the method is CONNECT |
245 | * |
246 | * @return bool |
247 | */ |
248 | public function isConnect(): bool |
249 | { |
250 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'CONNECT')); |
251 | } |
252 | |
253 | /** |
254 | * Return whether or not the method is PATCH |
255 | * |
256 | * @return bool |
257 | */ |
258 | public function isPatch(): bool |
259 | { |
260 | return (isset($this->server['REQUEST_METHOD']) && ($this->server['REQUEST_METHOD'] == 'PATCH')); |
261 | } |
262 | |
263 | /** |
264 | * Return whether or not the request is secure |
265 | * |
266 | * @return bool |
267 | */ |
268 | public function isSecure(): bool |
269 | { |
270 | return (isset($this->server['HTTPS']) || (isset($_SERVER['SERVER_PORT']) && ($_SERVER['SERVER_PORT'] == '443'))); |
271 | } |
272 | |
273 | /** |
274 | * Get the document root |
275 | * |
276 | * @return string|null |
277 | */ |
278 | public function getDocumentRoot(): string|null |
279 | { |
280 | return $this->server['DOCUMENT_ROOT'] ?? null; |
281 | } |
282 | |
283 | /** |
284 | * Get the method |
285 | * |
286 | * @return string|null |
287 | */ |
288 | public function getMethod(): string|null |
289 | { |
290 | return $this->server['REQUEST_METHOD'] ?? null; |
291 | } |
292 | |
293 | /** |
294 | * Get the server port |
295 | * |
296 | * @return string|null |
297 | */ |
298 | public function getPort(): string|null |
299 | { |
300 | return $this->server['SERVER_PORT'] ?? null; |
301 | } |
302 | |
303 | /** |
304 | * Get scheme |
305 | * |
306 | * @return string |
307 | */ |
308 | public function getScheme(): string |
309 | { |
310 | return ($this->isSecure()) ? 'https' : 'http'; |
311 | } |
312 | |
313 | /** |
314 | * Get host (without port) |
315 | * |
316 | * @return string |
317 | */ |
318 | public function getHost(): string |
319 | { |
320 | $hostname = null; |
321 | |
322 | if (!empty($this->server['HTTP_HOST'])) { |
323 | $hostname = $this->server['HTTP_HOST']; |
324 | } else if (!empty($this->server['SERVER_NAME'])) { |
325 | $hostname = $this->server['SERVER_NAME']; |
326 | } |
327 | |
328 | if (str_contains($hostname, ':')) { |
329 | $hostname = substr($hostname, 0, strpos($hostname, ':')); |
330 | } |
331 | |
332 | return $hostname; |
333 | } |
334 | |
335 | /** |
336 | * Get host with port |
337 | * |
338 | * @return string |
339 | */ |
340 | public function getFullHost(): string |
341 | { |
342 | $port = $this->getPort(); |
343 | $hostname = null; |
344 | |
345 | if (!empty($this->server['HTTP_HOST'])) { |
346 | $hostname = $this->server['HTTP_HOST']; |
347 | } else if (!empty($this->server['SERVER_NAME'])) { |
348 | $hostname = $this->server['SERVER_NAME']; |
349 | } |
350 | |
351 | if ((!str_contains($hostname, ':')) && ($port !== null)) { |
352 | $hostname .= ':' . $port; |
353 | } |
354 | |
355 | return $hostname; |
356 | } |
357 | |
358 | /** |
359 | * Get client's IP |
360 | * |
361 | * @param bool $proxy |
362 | * @return string |
363 | */ |
364 | public function getIp(bool $proxy = true): string |
365 | { |
366 | $ip = null; |
367 | |
368 | if ($proxy && isset($this->server['HTTP_CLIENT_IP'])) { |
369 | $ip = $this->server['HTTP_CLIENT_IP']; |
370 | } else if ($proxy && isset($this->server['HTTP_X_FORWARDED_FOR'])) { |
371 | $ip = $this->server['HTTP_X_FORWARDED_FOR']; |
372 | } else if (isset($this->server['REMOTE_ADDR'])) { |
373 | $ip = $this->server['REMOTE_ADDR']; |
374 | } |
375 | |
376 | return $ip; |
377 | } |
378 | |
379 | /** |
380 | * Get a value from $_COOKIE, or the whole array |
381 | * |
382 | * @param ?string $key |
383 | * @return string|array|null |
384 | */ |
385 | public function getCookie(?string $key = null): string|array|null |
386 | { |
387 | if ($key === null) { |
388 | return $this->cookie; |
389 | } else { |
390 | return $this->cookie[$key] ?? null; |
391 | } |
392 | } |
393 | |
394 | /** |
395 | * Get a value from $_SERVER, or the whole array |
396 | * |
397 | * @param ?string $key |
398 | * @return string|array|null |
399 | */ |
400 | public function getServer(?string $key = null): string|array|null |
401 | { |
402 | if ($key === null) { |
403 | return $this->server; |
404 | } else { |
405 | return $this->server[$key] ?? null; |
406 | } |
407 | } |
408 | |
409 | /** |
410 | * Get a value from $_ENV, or the whole array |
411 | * |
412 | * @param ?string $key |
413 | * @return string|array|null |
414 | */ |
415 | public function getEnv(?string $key = null): string|array|null |
416 | { |
417 | if ($key === null) { |
418 | return $this->env; |
419 | } else { |
420 | return $this->env[$key] ?? null; |
421 | } |
422 | } |
423 | |
424 | /** |
425 | * Get the base path |
426 | * |
427 | * @return string |
428 | */ |
429 | public function getBasePath(): string |
430 | { |
431 | return $this->uri->getBasePath(); |
432 | } |
433 | |
434 | /** |
435 | * Get the request URI |
436 | * |
437 | * @return string |
438 | */ |
439 | public function getUriString(): string |
440 | { |
441 | return $this->uri->getUri(); |
442 | } |
443 | |
444 | /** |
445 | * Get the full request URI, including base path |
446 | * |
447 | * @return string |
448 | */ |
449 | public function getFullUriString(): string |
450 | { |
451 | return $this->uri->getFullUri(); |
452 | } |
453 | |
454 | /** |
455 | * Get a path segment, divided by the forward slash, |
456 | * where $i refers to the array key index, i.e., |
457 | * 0 1 2 |
458 | * /hello/world/page |
459 | * |
460 | * @param int $i |
461 | * @return string|null |
462 | */ |
463 | public function getSegment(int $i): string|null |
464 | { |
465 | return $this->uri->getSegment($i); |
466 | } |
467 | |
468 | /** |
469 | * Get all path segments |
470 | * |
471 | * @return array |
472 | */ |
473 | public function getSegments(): array |
474 | { |
475 | return $this->uri->getSegments(); |
476 | } |
477 | |
478 | /** |
479 | * Set the base path |
480 | * |
481 | * @param ?string $path |
482 | * @return Request |
483 | */ |
484 | public function setBasePath(?string $path = null): Request |
485 | { |
486 | if ($this->uri !== null) { |
487 | $this->uri->setBasePath($path); |
488 | } |
489 | return $this; |
490 | } |
491 | |
492 | /** |
493 | * Return whether or not the request has FILES |
494 | * |
495 | * @return bool |
496 | */ |
497 | public function hasFiles(): bool |
498 | { |
499 | return $this->data->hasFiles(); |
500 | } |
501 | |
502 | /** |
503 | * Get a value from $_GET, or the whole array |
504 | * |
505 | * @param ?string $key |
506 | * @return string|array|null |
507 | */ |
508 | public function getQuery(?string $key = null): string|array|null |
509 | { |
510 | return $this->data->getQuery($key); |
511 | } |
512 | |
513 | /** |
514 | * Get a value from $_POST, or the whole array |
515 | * |
516 | * @param ?string $key |
517 | * @return string|array|null |
518 | */ |
519 | public function getPost(?string $key = null): string|array|null |
520 | { |
521 | return $this->data->getPost($key); |
522 | } |
523 | |
524 | /** |
525 | * Get a value from $_FILES, or the whole array |
526 | * |
527 | * @param ?string $key |
528 | * @return string|array|null |
529 | */ |
530 | public function getFiles(?string $key = null): string|array|null |
531 | { |
532 | return $this->data->getFiles($key); |
533 | } |
534 | |
535 | /** |
536 | * Get a value from PUT query data, or the whole array |
537 | * |
538 | * @param ?string $key |
539 | * @return string|array|null |
540 | */ |
541 | public function getPut(?string $key = null): string|array|null |
542 | { |
543 | return $this->data->getPut($key); |
544 | } |
545 | |
546 | /** |
547 | * Get a value from PATCH query data, or the whole array |
548 | * |
549 | * @param ?string $key |
550 | * @return string|array|null |
551 | */ |
552 | public function getPatch(?string $key = null): string|array|null |
553 | { |
554 | return $this->data->getPatch($key); |
555 | } |
556 | |
557 | /** |
558 | * Get a value from DELETE query data, or the whole array |
559 | * |
560 | * @param ?string $key |
561 | * @return string|array|null |
562 | */ |
563 | public function getDelete(?string $key = null): string|array|null |
564 | { |
565 | return $this->data->getDelete($key); |
566 | } |
567 | |
568 | |
569 | /** |
570 | * Get a value from query data, or the whole array |
571 | * |
572 | * @param ?string $key |
573 | * @return string|array|null |
574 | */ |
575 | public function getQueryData(?string $key = null): string|array|null |
576 | { |
577 | return $this->data->getQueryData($key); |
578 | } |
579 | |
580 | /** |
581 | * Has query data |
582 | * |
583 | * @return bool |
584 | */ |
585 | public function hasQueryData(): bool |
586 | { |
587 | return $this->data->hasQueryData(); |
588 | } |
589 | |
590 | /** |
591 | * Get a value from parsed data, or the whole array |
592 | * |
593 | * @param ?string $key |
594 | * @return string|array|null |
595 | */ |
596 | public function getParsedData(?string $key = null): string|array|null |
597 | { |
598 | return $this->data->getParsedData($key); |
599 | } |
600 | |
601 | /** |
602 | * Has parsed data |
603 | * |
604 | * @return bool |
605 | */ |
606 | public function hasParsedData(): bool |
607 | { |
608 | return $this->data->hasParsedData(); |
609 | } |
610 | |
611 | /** |
612 | * Get the raw data |
613 | * |
614 | * @return string|null |
615 | */ |
616 | public function getRawData(): string|null |
617 | { |
618 | return $this->data->getRawData(); |
619 | } |
620 | |
621 | /** |
622 | * Has raw data |
623 | * |
624 | * @return bool |
625 | */ |
626 | public function hasRawData(): bool |
627 | { |
628 | return $this->data->hasRawData(); |
629 | } |
630 | |
631 | /** |
632 | * Get data |
633 | * |
634 | * @return Uri |
635 | */ |
636 | public function getData(): Data |
637 | { |
638 | return $this->data; |
639 | } |
640 | |
641 | /** |
642 | * Has data |
643 | * |
644 | * @return bool |
645 | */ |
646 | public function hasData(): bool |
647 | { |
648 | return ($this->data !== null); |
649 | } |
650 | |
651 | /** |
652 | * Magic method to get a value from one of the server/environment variables |
653 | * |
654 | * @param string $name |
655 | * @return mixed |
656 | */ |
657 | public function __get(string $name): mixed |
658 | { |
659 | return match ($name) { |
660 | 'get' => $this->data->get, |
661 | 'post' => $this->data->post, |
662 | 'files' => $this->data->files, |
663 | 'put' => $this->data->put, |
664 | 'patch' => $this->data->patch, |
665 | 'delete' => $this->data->delete, |
666 | 'parsed' => $this->data->parsed, |
667 | 'raw' => $this->data->raw, |
668 | 'cookie' => $this->cookie, |
669 | 'server' => $this->server, |
670 | 'env' => $this->env, |
671 | 'headers' => $this->headers, |
672 | default => null, |
673 | }; |
674 | } |
675 | |
676 | } |