index/src/Http/HttpRequest.php

143 lines
4.7 KiB
PHP

<?php
// HttpRequest.php
// Created: 2022-02-08
// Updated: 2023-01-07
namespace Index\Http;
use InvalidArgumentException;
use Index\Version;
use Index\MediaType;
use Index\Http\Content\IHttpContent;
use Index\Http\Content\JsonContent;
use Index\Http\Content\StreamContent;
use Index\Http\Content\FormContent;
class HttpRequest extends HttpMessage {
private string $method;
private string $path;
private array $params;
private array $cookies;
public function __construct(
Version $version,
string $method,
string $path,
array $params,
array $cookies,
HttpHeaders $headers,
?IHttpContent $content
) {
$this->method = $method;
$this->path = $path;
$this->params = $params;
$this->cookies = $cookies;
parent::__construct($version, $headers, $content);
}
public function getMethod(): string {
return $this->method;
}
public function getPath(): string {
return $this->path;
}
public function getParamString(bool $spacesAsPlus = false): string {
return http_build_query($this->params, '', '&', $spacesAsPlus ? PHP_QUERY_RFC1738 : PHP_QUERY_RFC3986);
}
public function getParams(): array {
return $this->params;
}
public function getParam(string $name, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed {
if(!isset($this->params[$name]))
return null;
return filter_var($this->params[$name] ?? null, $filter, $options);
}
public function hasParam(string $name): bool {
return isset($this->params[$name]);
}
public function getCookies(): array {
return $this->cookies;
}
public function getCookie(string $name, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed {
if(!isset($this->cookies[$name]))
return null;
return filter_var($this->cookies[$name] ?? null, $filter, $options);
}
public static function fromRequest(): HttpRequest {
$build = new HttpRequestBuilder;
$build->setHttpVersion(new Version(...array_map('intval', explode('.', substr($_SERVER['SERVER_PROTOCOL'], 5)))));
$build->setMethod($_SERVER['REQUEST_METHOD']);
$build->setPath('/' . trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/'));
$build->setParams($_GET);
$build->setCookies($_COOKIE);
$contentType = null;
$contentLength = 0;
$headers = self::getRawRequestHeaders();
foreach($headers as $name => $value) {
$nameLower = strtolower($name);
if($nameLower === 'content-type')
try {
$contentType = MediaType::parse($value);
} catch(InvalidArgumentException $ex) {
$contentType = null;
}
elseif($nameLower === 'content-length')
$contentLength = (int)$value;
$build->setHeader($name, $value);
}
if($contentType !== null
&& ($contentType->equals('application/json') || $contentType->equals('application/x-json')))
$build->setContent(JsonContent::fromRequest());
elseif($contentType !== null
&& ($contentType->equals('application/x-www-form-urlencoded') || $contentType->equals('multipart/form-data')))
$build->setContent(FormContent::fromRequest());
elseif($contentLength > 0)
$build->setContent(StreamContent::fromRequest());
return $build->toRequest();
}
private static function getRawRequestHeaders(): array {
if(function_exists('getallheaders'))
return getallheaders();
$headers = [];
foreach($_SERVER as $key => $value) {
if(substr($key, 0, 5) === 'HTTP_') {
$key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5)))));
$headers[$key] = $value;
} elseif($key === 'CONTENT_TYPE') {
$headers['Content-Type'] = $value;
} elseif($key === 'CONTENT_LENGTH') {
$headers['Content-Length'] = $value;
}
}
if(!isset($headers['Authorization'])) {
if(isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
$headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
} elseif(isset($_SERVER['PHP_AUTH_USER'])) {
$headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . ($_SERVER['PHP_AUTH_PW'] ?? ''));
} elseif(isset($_SERVER['PHP_AUTH_DIGEST'])) {
$headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
}
}
return $headers;
}
}