Removed crusty HTTP header parsers.

If they're ever needed again they'll be written as needed as opposed to being speedran 4 years ago.
This commit is contained in:
flash 2024-08-01 22:08:15 +00:00
parent 57b939103e
commit 7e341e32ff
39 changed files with 0 additions and 1548 deletions

View file

@ -1,71 +0,0 @@
<?php
// AcceptEncodingHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use stdClass;
use InvalidArgumentException;
class AcceptEncodingHeader {
private array $encodings;
private array $rejects;
public function __construct(array $encodings, array $rejects) {
$this->encodings = $encodings;
$this->rejects = $rejects;
}
public function getEncodings(): array {
return $this->encodings;
}
public function getRejects(): array {
return $this->rejects;
}
public function accepts(string $algoName): int {
$algoName = strtolower($algoName);
foreach($this->encodings as $algo)
if($algo->quality !== 0 && ($algo->name === $algoName || $algo->name === '*'))
return $algo->quality;
return 0;
}
public function rejects(string $locale): bool {
return in_array(strtolower($locale), $this->rejects)
|| in_array('*', $this->rejects);
}
public static function parse(array $lines): AcceptEncodingHeader {
$parts = explode(',', (string)$lines[0]);
$algos = [];
$rejects = [];
foreach($parts as $part)
try {
$part = explode(';', $part);
$algo = new stdClass;
$algo->name = strtolower(trim(array_shift($part)));
$algo->quality = 1;
foreach($part as $param) {
if(substr($param, 0, 2) === 'q=') {
$algo->quality = min(0, max(1, (float)substr($param, 2)));
break;
}
}
$algos[] = $algo;
if($algo->quality === 0)
$rejects[] = $algo->name;
} catch(InvalidArgumentException $ex) {}
if(empty($algos))
throw new InvalidArgumentException('Failed to parse Accept-Encoding header.');
return new AcceptEncodingHeader($algos, $rejects);
}
}

View file

@ -1,63 +0,0 @@
<?php
// AcceptHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use InvalidArgumentException;
use Index\MediaType;
use Index\Http\HttpHeader;
class AcceptHeader {
private array $types;
private array $rejects;
public function __construct(array $types, array $rejects) {
$this->types = $types;
$this->rejects = $rejects;
}
public function getTypes(): array {
return $this->types;
}
public function getRejects(): array {
return $this->rejects;
}
public function accepts(MediaType|string $mediaType): ?MediaType {
foreach($this->types as $type)
if($type->getQuality() < 0.1 && $type->equals($mediaType))
return $type;
return null;
}
public function rejects(MediaType|string $mediaType): bool {
foreach($this->rejects as $reject)
if($reject->equals($mediaType))
return true;
return false;
}
public static function parse(HttpHeader $header): AcceptHeader {
$parts = explode(',', $header->getFirstLine());
$types = [];
$rejects = [];
foreach($parts as $part)
try {
$types[] = $type = MediaType::parse(trim($part));
if($type->getQuality() < 0.1)
$rejects[] = $type;
} catch(InvalidArgumentException $ex) {}
if(empty($types))
throw new InvalidArgumentException('Failed to parse Accept header.');
return new AcceptHeader($types, $rejects);
}
}

View file

@ -1,72 +0,0 @@
<?php
// AcceptLanguageHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use stdClass;
use InvalidArgumentException;
use Index\Http\HttpHeader;
class AcceptLanguageHeader {
private array $langs;
private array $rejects;
public function __construct(array $langs, array $rejects) {
$this->langs = $langs;
$this->rejects = $rejects;
}
public function getLanguages(): array {
return $this->langs;
}
public function getRejects(): array {
return $this->rejects;
}
public function accepts(string $locale): int {
$locale = strtolower($locale);
foreach($this->langs as $lang)
if($lang->quality !== 0 && ($lang->name === $locale || $lang->name === '*'))
return $lang->quality;
return 0;
}
public function rejects(string $locale): bool {
return in_array(strtolower($locale), $this->rejects)
|| in_array('*', $this->rejects);
}
public static function parse(HttpHeader $header): AcceptLanguageHeader {
$parts = explode(',', $header->getFirstLine());
$langs = [];
$rejects = [];
foreach($parts as $part)
try {
$part = explode(';', $part);
$lang = new stdClass;
$lang->name = strtolower(trim(array_shift($part)));
$lang->quality = 1;
foreach($part as $param) {
if(substr($param, 0, 2) === 'q=') {
$lang->quality = min(0, max(1, (float)substr($param, 2)));
break;
}
}
$langs[] = $lang;
if($lang->quality === 0)
$rejects[] = $lang->name;
} catch(InvalidArgumentException $ex) {}
if(empty($langs))
throw new InvalidArgumentException('Failed to parse Accept-Language header.');
return new AcceptLanguageHeader($langs, $rejects);
}
}

View file

@ -1,71 +0,0 @@
<?php
// AcceptTransferEncodingHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use stdClass;
use InvalidArgumentException;
class AcceptTransferEncodingHeader {
private array $encodings;
private array $rejects;
public function __construct(array $encodings, array $rejects) {
$this->encodings = $encodings;
$this->rejects = $rejects;
}
public function getEncodings(): array {
return $this->encodings;
}
public function getRejects(): array {
return $this->rejects;
}
public function accepts(string $algoName): int {
$algoName = strtolower($algoName);
foreach($this->encodings as $algo)
if($algo->quality !== 0 && ($algo->name === $algoName || $algo->name === '*'))
return $algo->quality;
return 0;
}
public function rejects(string $locale): bool {
return in_array(strtolower($locale), $this->rejects)
|| in_array('*', $this->rejects);
}
public static function parse(array $lines): AcceptTransferEncodingHeader {
$parts = explode(',', (string)$lines[0]);
$algos = [];
$rejects = [];
foreach($parts as $part)
try {
$part = explode(';', $part);
$algo = new stdClass;
$algo->name = strtolower(trim(array_shift($part)));
$algo->quality = 1;
foreach($part as $param) {
if(substr($param, 0, 2) === 'q=') {
$algo->quality = min(0, max(1, (float)substr($param, 2)));
break;
}
}
$algos[] = $algo;
if($algo->quality === 0)
$rejects[] = $algo->name;
} catch(InvalidArgumentException $ex) {}
if(empty($algos))
throw new InvalidArgumentException('Failed to parse TE header.');
return new AcceptTransferEncodingHeader($algos, $rejects);
}
}

View file

@ -1,34 +0,0 @@
<?php
// AccessControlRequestHeadersHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class AccessControlRequestHeadersHeader {
private array $headers;
public function __construct(array $headers) {
$this->headers = $headers;
}
public function getHeaders(): array {
return $this->headers;
}
public function isAllowed(string $header): bool {
return in_array(strtolower($header), $this->headers);
}
public static function parse(HttpHeader $header): AccessControlRequestHeadersHeader {
$raw = explode(',', $header->getFirstLine());
$headers = [];
foreach($raw as $header)
$headers[] = strtolower(trim($header));
return new AccessControlRequestHeadersHeader(array_unique($headers));
}
}

View file

@ -1,28 +0,0 @@
<?php
// AccessControlRequestMethodHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class AccessControlRequestMethodHeader {
private string $method;
public function __construct(string $method) {
$this->method = $method;
}
public function getMethod(): string {
return $this->method;
}
public function isMethod(string $method): bool {
return $this->method === strtolower($method);
}
public static function parse(HttpHeader $header): AccessControlRequestMethodHeader {
return new AccessControlRequestMethodHeader(strtolower(trim($header->getFirstLine())));
}
}

View file

@ -1,35 +0,0 @@
<?php
// AuthorizationHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class AuthorizationHeader {
private string $method;
private string $params;
public function __construct(string $method, string $params) {
$this->method = $method;
$this->params = $params;
}
public function getMethod(): string {
return $this->method;
}
public function isMethod(string $method): bool {
return $this->method === strtolower($method);
}
public function getParams(): string {
return $this->params;
}
public static function parse(HttpHeader $header): AuthorizationHeader {
$parts = explode(' ', trim($header->getFirstLine()), 2);
return new AuthorizationHeader($parts[0], $parts[1] ?? '');
}
}

View file

@ -1,47 +0,0 @@
<?php
// CacheControlHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class CacheControlHeader {
private array $params;
public function __construct(array $params) {
$this->params = $params;
}
public function getParams(): array {
return $this->params;
}
public function hasParam(string $name): bool {
return isset($this->params[strtolower($name)]);
}
public function getParam(string $name, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed {
$name = strtolower($name);
if(!isset($this->params[$name]))
return null;
return filter_var($this->params[$name] ?? null, $filter, $options);
}
public static function parse(HttpHeader $header): CacheControlHeader {
$raw = explode(',', strtolower($header->getFirstLine()));
$params = [];
foreach($raw as $param) {
$parts = explode('=', $param, 2);
$name = trim($parts[0]);
$value = trim($parts[1] ?? '');
if($value === '')
$value = true;
$params[$name] = $value;
}
return new CacheControlHeader($params);
}
}

View file

@ -1,35 +0,0 @@
<?php
// ConnectionHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class ConnectionHeader {
private array $params;
public function __construct(array $params) {
$this->params = $params;
}
public function getParams(): array {
return $this->params;
}
public function hasParam(string $directive): bool {
return in_array($directive, $this->params);
}
public static function parse(HttpHeader $header): ConnectionHeader {
return new ConnectionHeader(
array_unique(
array_map(
fn($directive) => trim($directive),
explode(',', strtolower($header->getFirstLine()))
)
)
);
}
}

View file

@ -1,29 +0,0 @@
<?php
// ContentEncodingHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class ContentEncodingHeader {
private array $encodings;
public function __construct(array $encodings) {
$this->encodings = $encodings;
}
public function getEncodings(): array {
return $this->encodings;
}
public static function parse(HttpHeader $header): ContentEncodingHeader {
return new ContentEncodingHeader(
array_map(
fn($directive) => trim($directive),
explode(',', strtolower($header->getFirstLine()))
)
);
}
}

View file

@ -1,35 +0,0 @@
<?php
// ContentLanguageHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class ContentLanguageHeader {
private array $langs;
public function __construct(array $langs) {
$this->langs = $langs;
}
public function getLanguages(): array {
return $this->langs;
}
public function hasLanguage(string $lang): bool {
return in_array(strtolower($lang), $this->langs);
}
public static function parse(HttpHeader $header): ContentLanguageHeader {
return new ContentLanguageHeader(
array_unique(
array_map(
fn($directive) => trim($directive),
explode(',', strtolower($header->getFirstLine()))
)
)
);
}
}

View file

@ -1,24 +0,0 @@
<?php
// ContentLengthHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class ContentLengthHeader {
private int $length;
public function __construct(int $length) {
$this->length = $length;
}
public function getLength(): int {
return $this->length;
}
public static function parse(HttpHeader $header): ContentLengthHeader {
return new ContentLengthHeader((int)$header->getFirstLine());
}
}

View file

@ -1,24 +0,0 @@
<?php
// ContentLocationHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class ContentLocationHeader {
private string $location;
public function __construct(string $location) {
$this->location = $location;
}
public function getLocation(): string {
return $this->location;
}
public static function parse(HttpHeader $header): ContentLocationHeader {
return new ContentLocationHeader(trim($header->getFirstLine()));
}
}

View file

@ -1,74 +0,0 @@
<?php
// ContentRangeHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class ContentRangeHeader {
private string $unit;
private int $rangeStart = -1;
private int $rangeEnd = -1;
private int $size = -1;
public function __construct(string $unit, int $rangeStart, int $rangeEnd, int $size) {
$this->unit = $unit;
$this->rangeStart = $rangeStart;
$this->rangeEnd = $rangeEnd;
$this->size = $size;
}
public function getUnit(): string {
return $this->unit;
}
public function isBytes(): bool {
return $this->unit === 'bytes';
}
public function getSize(): int {
return $this->size;
}
public function isUnknownSize(): bool {
return $this->size < 0;
}
public function isUnspecifiedRange(): bool {
return $this->rangeStart < 0 || $this->rangeEnd < 0;
}
public function getRangeStart(): int {
return $this->rangeStart;
}
public function getRangeEnd(): int {
return $this->rangeEnd;
}
public static function parse(HttpHeader $header): ContentRangeHeader {
$parts = explode(' ', trim($header->getFirstLine()), 2);
$unit = array_shift($parts);
$parts = explode('/', $parts[1] ?? '', 2);
$size = trim($parts[1] ?? '*');
if($size !== '*')
$size = max(0, (int)$size);
else
$size = -1;
$range = trim($parts[0]);
if($range !== '*') {
$parts = explode('-', $range, 2);
$rangeStart = (int)trim($parts[0]);
$rangeEnd = (int)trim($parts[1] ?? '0');
} else
$rangeStart = $rangeEnd = -1;
return new ContentRangeHeader($unit, $rangeStart, $rangeEnd, $size);
}
}

View file

@ -1,25 +0,0 @@
<?php
// ContentTypeHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\MediaType;
use Index\Http\HttpHeader;
class ContentTypeHeader {
private MediaType $mediaType;
public function __construct(MediaType $mediaType) {
$this->mediaType = $mediaType;
}
public function getMediaType(): MediaType {
return $this->mediaType;
}
public static function parse(HttpHeader $header): ContentTypeHeader {
return new ContentTypeHeader(MediaType::parse($header->getFirstLine()));
}
}

View file

@ -1,47 +0,0 @@
<?php
// CookieHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\UrlEncoding;
use Index\Http\HttpHeader;
class CookieHeader {
private array $cookies;
public function __construct(array $cookies) {
$this->cookies = $cookies;
}
public function getCookies(): array {
return $this->cookies;
}
public function hasCookie(string $name): bool {
return isset($this->cookies[$name]);
}
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 parse(HttpHeader $header): CookieHeader {
$cookies = [];
$lines = $header->getLines();
foreach($lines as $line) {
$parts = explode(';', $line);
foreach($parts as $part) {
$kvp = explode('=', $part, 2);
$cookies[rawurldecode($kvp[0])] = rawurldecode($kvp[1] ?? '');
}
}
return new CookieHeader($cookies);
}
}

View file

@ -1,33 +0,0 @@
<?php
// DNTHeader.php
// Created: 2022-02-14
// Updated: 2022-02-14
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class DNTHeader {
private ?bool $state;
public function __construct(?bool $state) {
$this->state = $state;
}
public function getState(): ?bool {
return $this->state;
}
public function hasNoPreference(): bool {
return $this->state === null;
}
public function allowsTracking(): bool {
return $this->state !== false;
}
public static function parse(HttpHeader $header): DNTHeader {
$value = $header->getFirstLine();
return new DNTHeader($value === 'null' ? null : ($value === '1'));
}
}

View file

@ -1,31 +0,0 @@
<?php
// DateHeader.php
// Created: 2022-02-14
// Updated: 2024-07-31
namespace Index\Http\Headers;
use DateTimeImmutable;
use DateTimeInterface;
use RuntimeException;
use Index\Http\HttpHeader;
class DateHeader {
private DateTimeImmutable $dateTime;
public function __construct(DateTimeImmutable $dateTime) {
$this->dateTime = $dateTime;
}
public function getDateTime(): DateTimeImmutable {
return $this->dateTime;
}
public static function parse(HttpHeader $header): DateHeader {
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $header->getFirstLine());
if($parsed === false)
throw new RuntimeException('Failed to parse Date header.');
return new DateHeader($parsed);
}
}

View file

@ -1,31 +0,0 @@
<?php
// ExpectHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class ExpectHeader {
private int $statusCode;
private string $statusText;
public function __construct(int $statusCode, string $statusText) {
$this->statusCode = $statusCode;
$this->statusText = $statusText;
}
public function getStatusCode(): int {
return $this->statusCode;
}
public function getStatusText(): string {
return $this->statusText;
}
public static function parse(HttpHeader $header): ExpectHeader {
$value = explode('-', $header->getFirstLine(), 2);
return new ExpectHeader((int)$value[0], $value[1] ?? '');
}
}

View file

@ -1,24 +0,0 @@
<?php
// FromHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class FromHeader {
private string $email;
public function __construct(string $email) {
$this->email = $email;
}
public function getEMailAddress(): string {
return $this->email;
}
public static function parse(HttpHeader $header): FromHeader {
return new FromHeader($header->getFirstLine());
}
}

View file

@ -1,35 +0,0 @@
<?php
// HostHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class HostHeader {
private string $host;
private int $port;
public function __construct(string $host, int $port) {
$this->host = $host;
$this->port = $port;
}
public function getHost(): string {
return $this->host;
}
public function hasPort(): bool {
return $this->port > 0;
}
public function getPort(): int {
return $this->port;
}
public static function parse(HttpHeader $header): HostHeader {
$parts = explode(':', $header->getFirstLine(), 2);
return new HostHeader($parts[0], (int)($parts[1] ?? '-1'));
}
}

View file

@ -1,46 +0,0 @@
<?php
// IfMatchHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class IfMatchHeader {
private array $tags;
private int $count;
public function __construct(array $tags) {
$this->tags = $tags;
$this->count = count($tags);
}
public function getTags(): array {
return $this->tags;
}
public function hasTag(string $tag): bool {
if($this->count === 1 && $this->tags[0] === '*')
return true;
return in_array((string)$tag, $this->tags);
}
public static function parse(HttpHeader $header): IfMatchHeader {
$tags = [];
$rawTags = array_unique(
array_map(
fn($directive) => trim($directive),
explode(',', strtolower($header->getFirstLine()))
)
);
foreach($rawTags as $raw) {
if(substr($raw, 0, 3) === 'W/"')
continue;
$tags[] = trim($raw, '"');
}
return new IfMatchHeader($tags);
}
}

View file

@ -1,36 +0,0 @@
<?php
// IfModifiedSinceHeader.php
// Created: 2022-02-14
// Updated: 2024-07-31
namespace Index\Http\Headers;
use DateTimeImmutable;
use DateTimeInterface;
use RuntimeException;
use Index\XDateTime;
use Index\Http\HttpHeader;
class IfModifiedSinceHeader {
private DateTimeImmutable $dateTime;
public function __construct(DateTimeImmutable $dateTime) {
$this->dateTime = $dateTime;
}
public function getDateTime(): DateTimeImmutable {
return $this->dateTime;
}
public function isLessThanOrEqual(DateTimeInterface $other): bool {
return XDateTime::compare($this->dateTime, $other) <= 0;
}
public static function parse(HttpHeader $header): IfModifiedSinceHeader {
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $header->getFirstLine());
if($parsed === false)
throw new RuntimeException('Failed to parse If-Modified-Since header.');
return new IfModifiedSinceHeader($parsed);
}
}

View file

@ -1,46 +0,0 @@
<?php
// IfNoneMatchHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class IfNoneMatchHeader {
private array $tags;
private int $count;
public function __construct(array $tags) {
$this->tags = $tags;
$this->count = count($tags);
}
public function getTags(): array {
return $this->tags;
}
public function hasTag(string $tag): bool {
if($this->count === 1 && $this->tags[0] === '*')
return true;
return in_array($tag, $this->tags);
}
public static function parse(HttpHeader $header): IfNoneMatchHeader {
$tags = [];
$rawTags = array_unique(
array_map(
fn($directive) => trim($directive),
explode(',', strtolower($header->getFirstLine()))
)
);
foreach($rawTags as $raw) {
if(str_starts_with($raw, 'W/"'))
$raw = substr($raw, 2);
$tags[] = trim($raw, '"');
}
return new IfNoneMatchHeader($tags);
}
}

View file

@ -1,65 +0,0 @@
<?php
// IfRangeHeader.php
// Created: 2022-02-14
// Updated: 2024-07-31
namespace Index\Http\Headers;
use DateTimeImmutable;
use DateTimeInterface;
use RuntimeException;
use Index\XDateTime;
use Index\Http\HttpHeader;
class IfRangeHeader {
private ?string $tag;
private ?DateTimeImmutable $dateTime;
public function __construct(?string $tag, ?DateTimeImmutable $dateTime) {
$this->tag = $tag;
$this->dateTime = $dateTime;
}
public function hasTag(): bool {
return $this->tag !== null;
}
public function getTag(): string {
return $this->tag;
}
public function hasDateTime(): bool {
return $this->dateTime !== null;
}
public function getDateTime(): DateTimeImmutable {
return $this->dateTime;
}
public function matches(string|DateTimeInterface $other): bool {
if($this->hasTag() && is_string($other)) {
if(str_starts_with($other, 'W/"'))
return false;
return $this->tag === $other;
}
if($this->hasDateTime() && $other instanceof DateTimeInterface)
return XDateTime::compare($this->dateTime, $other) <= 0;
return false;
}
public static function parse(HttpHeader $header): IfRangeHeader {
$line = $header->getFirstLine();
if($line[0] !== '"' && !str_starts_with($line, 'W/"')) {
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $line);
if($parsed === false)
throw new RuntimeException('Failed to parse If-Range header.');
return new IfRangeHeader(null, $parsed);
}
return new IfRangeHeader($line, null);
}
}

View file

@ -1,36 +0,0 @@
<?php
// IfUnmodifiedSinceHeader.php
// Created: 2022-02-14
// Updated: 2024-07-31
namespace Index\Http\Headers;
use DateTimeImmutable;
use DateTimeInterface;
use RuntimeException;
use Index\XDateTime;
use Index\Http\HttpHeader;
class IfUnmodifiedSinceHeader {
private DateTimeImmutable $dateTime;
public function __construct(DateTimeImmutable $dateTime) {
$this->dateTime = $dateTime;
}
public function getDateTime(): DateTimeImmutable {
return $this->dateTime;
}
public function isMoreThan(DateTimeInterface $other): bool {
return XDateTime::compare($this->dateTime, $other) > 0;
}
public static function parse(HttpHeader $header): IfUnmodifiedSinceHeader {
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $header->getFirstLine());
if($parsed === false)
throw new RuntimeException('Failed to parse If-Unmodified-Since header.');
return new IfUnmodifiedSinceHeader($parsed);
}
}

View file

@ -1,43 +0,0 @@
<?php
// KeepAliveHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class KeepAliveHeader {
private int $timeOut;
private int $max;
public function __construct(int $timeOut, int $max) {
$this->timeOut = $timeOut;
$this->max = $max;
}
public function getTimeOut(): int {
return $this->timeOut;
}
public function getMax(): int {
return $this->max;
}
public static function parse(HttpHeader $header): KeepAliveHeader {
$params = explode(',', $header->getFirstLine());
$timeOut = -1;
$max = -1;
foreach($params as $param) {
if(str_starts_with($param, 'timeout='))
$timeOut = (int)substr($param, 8);
elseif(str_starts_with($param, 'max='))
$max = (int)substr($param, 4);
if($timeOut >= 0 && $max >= 0)
break;
}
return new KeepAliveHeader($timeOut, $max);
}
}

View file

@ -1,31 +0,0 @@
<?php
// LastModifiedHeader.php
// Created: 2022-02-14
// Updated: 2024-07-31
namespace Index\Http\Headers;
use DateTimeImmutable;
use DateTimeInterface;
use RuntimeException;
use Index\Http\HttpHeader;
class LastModifiedHeader {
private DateTimeImmutable $dateTime;
public function __construct(DateTimeImmutable $dateTime) {
$this->dateTime = $dateTime;
}
public function getDateTime(): DateTimeImmutable {
return $this->dateTime;
}
public static function parse(HttpHeader $header): LastModifiedHeader {
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $header->getFirstLine());
if($parsed === false)
throw new RuntimeException('Failed to parse Last-Modified header.');
return new LastModifiedHeader($parsed);
}
}

View file

@ -1,60 +0,0 @@
<?php
// OriginHeader.php
// Created: 2022-02-14
// Updated: 2024-07-31
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class OriginHeader {
private bool $isNull;
private string $scheme;
private string $host;
private int $port;
public function __construct(bool $isNull, string $scheme, string $host, int $port) {
$this->isNull = $isNull;
$this->scheme = $scheme;
$this->host = $host;
$this->port = $port;
}
public function isNull(): bool {
return $this->isNull;
}
public function isValid(): bool {
return $this->isNull || ($this->scheme !== '' && $this->host !== '');
}
public function getScheme(): string {
return $this->scheme;
}
public function getHost(): string {
return $this->host;
}
public function hasPort(): bool {
return $this->port > 0;
}
public function getPort(): int {
return $this->port;
}
public static function parse(HttpHeader $header): OriginHeader {
$line = $header->getFirstLine();
if($line === 'null')
return new OriginHeader(true, '', '', -1);
return new OriginHeader(
false,
parse_url($line, PHP_URL_SCHEME) ?? '',
parse_url($line, PHP_URL_HOST) ?? '',
parse_url($line, PHP_URL_PORT) ?? -1
);
}
}

View file

@ -1,24 +0,0 @@
<?php
// PragmaHeader.php
// Created: 2022-02-14
// Updated: 2022-02-14
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class PragmaHeader {
private bool $noCache;
public function __construct(bool $noCache) {
$this->noCache = $noCache;
}
public function shouldByPassCache(): bool {
return $this->noCache;
}
public static function parse(HttpHeader $header): PragmaHeader {
return new PragmaHeader($header->getFirstLine() === 'no-cache');
}
}

View file

@ -1,35 +0,0 @@
<?php
// ProxyAuthorizationHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class ProxyAuthorizationHeader {
private string $method;
private string $params;
public function __construct(string $method, string $params) {
$this->method = $method;
$this->params = $params;
}
public function getMethod(): string {
return $this->method;
}
public function isMethod(string $method): bool {
return $this->method === strtolower($method);
}
public function getParams(): string {
return $this->params;
}
public static function parse(HttpHeader $header): ProxyAuthorizationHeader {
$parts = explode(' ', trim($header->getFirstLine()), 2);
return new ProxyAuthorizationHeader($parts[0], $parts[1] ?? '');
}
}

View file

@ -1,61 +0,0 @@
<?php
// RangeHeader.php
// Created: 2022-02-14
// Updated: 2023-01-01
namespace Index\Http\Headers;
use stdClass;
use Index\Http\HttpHeader;
class RangeHeader {
private string $unit;
private array $ranges;
public function __construct(string $unit, array $ranges) {
$this->unit = $unit;
$this->ranges = $ranges;
}
public function getUnit(): string {
return $this->unit;
}
public function isBytes(): bool {
return $this->unit === 'bytes';
}
public function getRanges(): array {
return $this->ranges;
}
public static function parse(HttpHeader $header): RangeHeader {
$parts = explode('=', trim($header->getFirstLine()), 2);
$unit = trim($parts[0]);
$ranges = [];
$rawRanges = explode(',', $parts[1] ?? '', 2);
foreach($rawRanges as $raw) {
$raw = explode('-', trim($raw), 2);
$start = trim($raw[0]);
$end = trim($raw[1] ?? '');
$ranges[] = $range = new stdClass;
if($start === '' && is_numeric($end)) {
$range->type = 'suffix-length';
$range->length = (int)$end;
} elseif(is_numeric($start) && $end === '') {
$range->type = 'start';
$range->start = (int)$start;
} else {
$range->type = 'range';
$range->start = (int)$start;
$range->end = (int)$end;
}
}
return new RangeHeader($unit, $ranges);
}
}

View file

@ -1,24 +0,0 @@
<?php
// RefererHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class RefererHeader {
private string $url;
public function __construct(string $url) {
$this->url = $url;
}
public function getSource(): string {
return $this->url;
}
public static function parse(HttpHeader $header): RefererHeader {
return new RefererHeader(trim($header->getFirstLine()));
}
}

View file

@ -1,24 +0,0 @@
<?php
// SaveDataHeader.php
// Created: 2022-02-14
// Updated: 2022-02-14
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class SaveDataHeader {
private bool $saveData;
public function __construct(bool $saveData) {
$this->saveData = $saveData;
}
public function shouldReduceData(): bool {
return $this->saveData;
}
public static function parse(HttpHeader $header): SaveDataHeader {
return new SaveDataHeader($header->getFirstLine() === 'yes');
}
}

View file

@ -1,34 +0,0 @@
<?php
// TrailerHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class TrailerHeader {
private array $headers;
public function __construct(array $headers) {
$this->headers = $headers;
}
public function getHeaders(): array {
return $this->headers;
}
public function isTrailer(string $header): bool {
return in_array(strtolower($header), $this->headers);
}
public static function parse(HttpHeader $header): TrailerHeader {
$raw = explode(',', $header->getFirstLine());
$headers = [];
foreach($raw as $header)
$headers[] = strtolower(trim($header));
return new TrailerHeader(array_unique($headers));
}
}

View file

@ -1,29 +0,0 @@
<?php
// TransferEncodingHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class TransferEncodingHeader {
private array $encodings;
public function __construct(array $encodings) {
$this->encodings = $encodings;
}
public function getEncodings(): array {
return $this->encodings;
}
public static function parse(HttpHeader $header): TransferEncodingHeader {
return new TransferEncodingHeader(
array_map(
fn($directive) => trim($directive),
explode(',', strtolower($header->getFirstLine()))
)
);
}
}

View file

@ -1,33 +0,0 @@
<?php
// UpgradeHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class UpgradeHeader {
private array $protocols;
public function __construct(array $protocols) {
$this->protocols = $protocols;
}
public function getProtocols(): array {
return $this->protocols;
}
public function isAccepted(string $protocol): bool {
return in_array(strtolower($protocol), $this->protocols);
}
public static function parse(HttpHeader $header): UpgradeHeader {
return new UpgradeHeader(
array_map(
fn($directive) => trim($directive),
explode(',', strtolower($header->getFirstLine()))
)
);
}
}

View file

@ -1,24 +0,0 @@
<?php
// UpgradeInsecureRequestsHeader.php
// Created: 2022-02-14
// Updated: 2022-02-14
namespace Index\Http\Headers;
use Index\Http\HttpHeader;
class UpgradeInsecureRequestsHeader {
private bool $upgrade;
public function __construct(bool $upgrade) {
$this->upgrade = $upgrade;
}
public function shouldUpgrade(): bool {
return $this->upgrade;
}
public static function parse(HttpHeader $header): UpgradeInsecureRequestsHeader {
return new UpgradeInsecureRequestsHeader($header->getFirstLine() === '1');
}
}

View file

@ -1,29 +0,0 @@
<?php
// UserAgentHeader.php
// Created: 2022-02-14
// Updated: 2022-02-27
namespace Index\Http\Headers;
use Stringable;
use Index\Http\HttpHeader;
class UserAgentHeader implements Stringable {
private string $userAgent;
public function __construct(string $userAgent) {
$this->userAgent = $userAgent;
}
public function getUserAgent(): string {
return $this->userAgent;
}
public function __toString(): string {
return $this->userAgent;
}
public static function parse(HttpHeader $header): UserAgentHeader {
return new UserAgentHeader(trim($header->getFirstLine()));
}
}