$query @param array $body @param array $headers */ public function __construct( public readonly string $method, public readonly string $path, public readonly array $query, public readonly array $body, public readonly array $headers, public readonly string $ip, ) { } public static function fromGlobals(Config $config): self { $uri = (string) ($_SERVER['REQUEST_URI'] ?? '/'); $path = rawurldecode((string) parse_url($uri, PHP_URL_PATH)); $path = '/' . trim($path, '/'); if ($path !== '/') { $path = rtrim($path, '/'); } $headers = []; foreach ($_SERVER as $key => $value) { if (str_starts_with($key, 'HTTP_')) { $headers[strtolower(str_replace('_', '-', substr($key, 5)))] = (string) $value; } } $ip = (string) ($_SERVER['REMOTE_ADDR'] ?? ''); if ($config->trustProxy && in_array($ip, $config->network['trustedProxyIps'], true) && isset($headers['x-forwarded-for'])) { $candidate = trim(explode(',', $headers['x-forwarded-for'])[0]); if (filter_var($candidate, FILTER_VALIDATE_IP)) { $ip = $candidate; } } return new self( strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')), $path, $_GET, $_POST, $headers, $ip, ); } }