Reorganised Http namespacing structure.

This commit is contained in:
Pachira 2024-10-02 19:32:38 +00:00
parent a5aa0152a0
commit a84f36f731
17 changed files with 110 additions and 121 deletions

View file

@ -1 +1 @@
0.2410.21617
0.2410.21928

View file

@ -1,17 +1,17 @@
<?php
// BencodedContent.php
// BencodeHttpContent.php
// Created: 2022-02-10
// Updated: 2024-10-02
namespace Index\Http\Content;
namespace Index\Bencode;
use RuntimeException;
use Index\Bencode\{Bencode,BencodeSerializable};
use Index\Http\HttpContent;
/**
* Represents Bencoded body content for a HTTP message.
*/
class BencodedContent implements BencodeSerializable, HttpContent {
class BencodeHttpContent implements BencodeSerializable, HttpContent {
/**
* @param mixed $content Content to be bencoded.
*/
@ -49,19 +49,19 @@ class BencodedContent implements BencodeSerializable, HttpContent {
* Creates an instance from encoded content.
*
* @param mixed $encoded Bencoded content.
* @return BencodedContent Instance representing the provided content.
* @return BencodeHttpContent Instance representing the provided content.
*/
public static function fromEncoded(mixed $encoded): BencodedContent {
return new BencodedContent(Bencode::decode($encoded));
public static function fromEncoded(mixed $encoded): BencodeHttpContent {
return new BencodeHttpContent(Bencode::decode($encoded));
}
/**
* Creates an instance from an encoded file.
*
* @param string $path Path to the bencoded file.
* @return BencodedContent Instance representing the provided path.
* @return BencodeHttpContent Instance representing the provided path.
*/
public static function fromFile(string $path): BencodedContent {
public static function fromFile(string $path): BencodeHttpContent {
$handle = fopen($path, 'rb');
if(!is_resource($handle))
throw new RuntimeException('$path could not be opened');
@ -76,9 +76,9 @@ class BencodedContent implements BencodeSerializable, HttpContent {
/**
* Creates an instance from the raw request body.
*
* @return BencodedContent Instance representing the request body.
* @return BencodeHttpContent Instance representing the request body.
*/
public static function fromRequest(): BencodedContent {
public static function fromRequest(): BencodeHttpContent {
return self::fromFile('php://input');
}
}

View file

@ -1,18 +1,16 @@
<?php
// BencodeContentHandler.php
// BencodeHttpContentHandler.php
// Created: 2024-03-28
// Updated: 2024-10-02
namespace Index\Http\ContentHandling;
namespace Index\Bencode;
use Index\Bencode\BencodeSerializable;
use Index\Http\HttpResponseBuilder;
use Index\Http\Content\BencodedContent;
use Index\Http\{HttpContentHandler,HttpResponseBuilder};
/**
* Represents a Bencode content handler for building HTTP response messages.
*/
class BencodeContentHandler implements ContentHandler {
class BencodeHttpContentHandler implements HttpContentHandler {
public function match(mixed $content): bool {
return $content instanceof BencodeSerializable;
}
@ -21,6 +19,6 @@ class BencodeContentHandler implements ContentHandler {
if(!$response->hasContentType())
$response->setTypePlain();
$response->setContent(new BencodedContent($content));
$response->setContent(new BencodeHttpContent($content));
}
}

View file

@ -1,17 +1,16 @@
<?php
// FormContent.php
// FormHttpContent.php
// Created: 2022-02-10
// Updated: 2024-10-02
namespace Index\Http\Content;
namespace Index\Http;
use RuntimeException;
use Index\Http\HttpUploadedFile;
/**
* Represents form body content for a HTTP message.
*/
class FormContent implements HttpContent {
class FormHttpContent implements HttpContent {
/**
* @param array<string, mixed> $postFields Form fields.
* @param array<string, HttpUploadedFile|array<string, mixed>> $uploadedFiles Uploaded files.
@ -95,10 +94,10 @@ class FormContent implements HttpContent {
*
* @param array<string, mixed> $post Form fields.
* @param array<string, mixed> $files Uploaded files.
* @return FormContent Instance representing the request body.
* @return FormHttpContent Instance representing the request body.
*/
public static function fromRaw(array $post, array $files): FormContent {
return new FormContent(
public static function fromRaw(array $post, array $files): FormHttpContent {
return new FormHttpContent(
$post,
HttpUploadedFile::createFromPhpFiles($files)
);
@ -107,9 +106,9 @@ class FormContent implements HttpContent {
/**
* Creates an instance from the $_POST and $_FILES superglobals.
*
* @return FormContent Instance representing the request body.
* @return FormHttpContent Instance representing the request body.
*/
public static function fromRequest(): FormContent {
public static function fromRequest(): FormHttpContent {
/** @var array<string, mixed> $postVars */
$postVars = $_POST;

View file

@ -1,16 +1,14 @@
<?php
// HtmlErrorHandler.php
// HtmlHttpErrorHandler.php
// Created: 2024-03-28
// Updated: 2024-10-02
namespace Index\Http\ErrorHandling;
use Index\Http\{HttpResponseBuilder,HttpRequest};
namespace Index\Http;
/**
* Represents a basic HTML error message handler for building HTTP response messages.
*/
class HtmlErrorHandler implements ErrorHandler {
class HtmlHttpErrorHandler implements HttpErrorHandler {
private const TEMPLATE = <<<HTML
<!doctype html>
<html>

View file

@ -3,7 +3,7 @@
// Created: 2022-02-08
// Updated: 2024-10-02
namespace Index\Http\Content;
namespace Index\Http;
use Stringable;

View file

@ -1,16 +1,14 @@
<?php
// ContentHandler.php
// HttpContentHandler.php
// Created: 2024-03-28
// Updated: 2024-10-02
namespace Index\Http\ContentHandling;
use Index\Http\HttpResponseBuilder;
namespace Index\Http;
/**
* Represents a content handler for building HTTP response messages.
*/
interface ContentHandler {
interface HttpContentHandler {
/**
* Determines whether this handler is suitable for the body content.
*

View file

@ -1,16 +1,14 @@
<?php
// ErrorHandler.php
// HttpErrorHandler.php
// Created: 2024-03-28
// Updated: 2024-10-02
namespace Index\Http\ErrorHandling;
use Index\Http\{HttpResponseBuilder,HttpRequest};
namespace Index\Http;
/**
* Represents an error message handler for building HTTP response messages.
*/
interface ErrorHandler {
interface HttpErrorHandler {
/**
* Applies an error message template to the provided HTTP response builder.
*

View file

@ -6,7 +6,8 @@
namespace Index\Http;
use RuntimeException;
use Index\Http\Content\{BencodedContent,FormContent,HttpContent,JsonContent,StringContent};
use Index\Bencode\BencodeHttpContent;
use Index\Json\JsonHttpContent;
/**
* Represents a base HTTP message.
@ -111,38 +112,38 @@ abstract class HttpMessage {
}
/**
* Checks if the body content is JsonContent.
* Checks if the body content is JsonHttpContent.
*
* @return bool true if it is JsonContent.
* @return bool true if it is JsonHttpContent.
*/
public function isJsonContent(): bool {
return $this->content instanceof JsonContent;
return $this->content instanceof JsonHttpContent;
}
/**
* Checks if the body content is FormContent.
* Checks if the body content is FormHttpContent.
*
* @return bool true if it is FormContent.
* @return bool true if it is FormHttpContent.
*/
public function isFormContent(): bool {
return $this->content instanceof FormContent;
return $this->content instanceof FormHttpContent;
}
/**
* Checks if the body content is StringContent.
* Checks if the body content is StringHttpContent.
*
* @return bool true if it is StringContent.
* @return bool true if it is StringHttpContent.
*/
public function isStringContent(): bool {
return $this->content instanceof StringContent;
return $this->content instanceof StringHttpContent;
}
/**
* Checks if the body content is BencodedContent.
* Checks if the body content is BencodeHttpContent.
*
* @return bool true if it is BencodedContent.
* @return bool true if it is BencodeHttpContent.
*/
public function isBencodedContent(): bool {
return $this->content instanceof BencodedContent;
public function isBencodeContent(): bool {
return $this->content instanceof BencodeHttpContent;
}
}

View file

@ -8,7 +8,6 @@ namespace Index\Http;
use InvalidArgumentException;
use RuntimeException;
use Stringable;
use Index\Http\Content\{HttpContent,StringContent};
/**
* Represents a base HTTP message builder.
@ -130,7 +129,7 @@ class HttpMessageBuilder {
}
if(is_scalar($content) || $content instanceof Stringable) {
$this->content = new StringContent((string)$content);
$this->content = new StringHttpContent((string)$content);
return;
}
@ -139,7 +138,7 @@ class HttpMessageBuilder {
if($content === false)
throw new RuntimeException('was unable to read the stream resource in $content');
$this->content = new StringContent($content);
$this->content = new StringHttpContent($content);
return;
}

View file

@ -8,7 +8,7 @@ namespace Index\Http;
use InvalidArgumentException;
use RuntimeException;
use Index\MediaType;
use Index\Http\Content\{HttpContent,FormContent,JsonContent,StringContent};
use Index\Json\JsonHttpContent;
/**
* Represents a HTTP request message.
@ -182,12 +182,12 @@ class HttpRequest extends HttpMessage {
if($contentType !== null
&& ($contentType->equals('application/json') || $contentType->equals('application/x-json')))
$build->setContent(JsonContent::fromRequest());
$build->setContent(JsonHttpContent::fromRequest());
elseif($contentType !== null
&& ($contentType->equals('application/x-www-form-urlencoded') || $contentType->equals('multipart/form-data')))
$build->setContent(FormContent::fromRequest());
$build->setContent(FormHttpContent::fromRequest());
elseif($contentLength > 0)
$build->setContent(StringContent::fromRequest());
$build->setContent(StringHttpContent::fromRequest());
return $build->toRequest();
}

View file

@ -5,8 +5,6 @@
namespace Index\Http;
use Index\Http\Content\HttpContent;
/**
* Represents a HTTP response message.
*/

View file

@ -1,16 +1,14 @@
<?php
// PlainErrorHandler.php
// PlainHttpErrorHandler.php
// Created: 2024-03-28
// Updated: 2024-10-02
namespace Index\Http\ErrorHandling;
use Index\Http\{HttpResponseBuilder,HttpRequest};
namespace Index\Http;
/**
* Represents a plain text error message handler for building HTTP response messages.
*/
class PlainErrorHandler implements ErrorHandler {
class PlainHttpErrorHandler implements HttpErrorHandler {
public function handle(HttpResponseBuilder $response, HttpRequest $request, int $code, string $message): void {
$response->setTypePlain();
$response->setContent(sprintf('HTTP %03d %s', $code, $message));

View file

@ -7,10 +7,12 @@ namespace Index\Http\Routing;
use stdClass;
use InvalidArgumentException;
use Index\Http\{HttpResponse,HttpResponseBuilder,HttpRequest};
use Index\Http\Content\StringContent;
use Index\Http\ContentHandling\{BencodeContentHandler,ContentHandler,JsonContentHandler};
use Index\Http\ErrorHandling\{HtmlErrorHandler,ErrorHandler,PlainErrorHandler};
use Index\Bencode\BencodeHttpContentHandler;
use Index\Http\{
HtmlHttpErrorHandler,HttpContentHandler,HttpErrorHandler,HttpResponse,
HttpResponseBuilder,HttpRequest,PlainHttpErrorHandler,StringHttpContent
};
use Index\Json\JsonHttpContentHandler;
class HttpRouter implements Router {
use RouterTrait;
@ -24,19 +26,19 @@ class HttpRouter implements Router {
/** @var array<string, array<string, callable>> */
private array $dynamicRoutes = [];
/** @var ContentHandler[] */
/** @var HttpContentHandler[] */
private array $contentHandlers = [];
private ErrorHandler $errorHandler;
private HttpErrorHandler $errorHandler;
/**
* @param string $charSet Default character set to specify when none is present.
* @param ErrorHandler|string $errorHandler Error handling to use for error responses with an empty body. 'html' for the default HTML implementation, 'plain' for the plaintext implementation.
* @param HttpErrorHandler|string $errorHandler Error handling to use for error responses with an empty body. 'html' for the default HTML implementation, 'plain' for the plaintext implementation.
* @param bool $registerDefaultContentHandlers true to register default content handlers for JSON, Bencode, etc.
*/
public function __construct(
private string $charSet = '',
ErrorHandler|string $errorHandler = 'html',
HttpErrorHandler|string $errorHandler = 'html',
bool $registerDefaultContentHandlers = true,
) {
$this->setErrorHandler($errorHandler);
@ -65,19 +67,19 @@ class HttpRouter implements Router {
/**
* Retrieves the error handler instance.
*
* @return ErrorHandler The error handler.
* @return HttpErrorHandler The error handler.
*/
public function getErrorHandler(): ErrorHandler {
public function getErrorHandler(): HttpErrorHandler {
return $this->errorHandler;
}
/**
* Changes the active error handler.
*
* @param ErrorHandler|string $handler Error handling to use for error responses with an empty body. 'html' for the default HTML implementation, 'plain' for the plaintext implementation.
* @param HttpErrorHandler|string $handler Error handling to use for error responses with an empty body. 'html' for the default HTML implementation, 'plain' for the plaintext implementation.
*/
public function setErrorHandler(ErrorHandler|string $handler): void {
if($handler instanceof ErrorHandler)
public function setErrorHandler(HttpErrorHandler|string $handler): void {
if($handler instanceof HttpErrorHandler)
$this->errorHandler = $handler;
elseif($handler === 'html')
$this->setHTMLErrorHandler();
@ -88,23 +90,23 @@ class HttpRouter implements Router {
/**
* Set the error handler to the basic HTML one.
*/
public function setHTMLErrorHandler(): void {
$this->errorHandler = new HtmlErrorHandler;
public function setHtmlErrorHandler(): void {
$this->errorHandler = new HtmlHttpErrorHandler;
}
/**
* Set the error handler to the plain text one.
*/
public function setPlainErrorHandler(): void {
$this->errorHandler = new PlainErrorHandler;
$this->errorHandler = new PlainHttpErrorHandler;
}
/**
* Register a message body content handler.
*
* @param ContentHandler $contentHandler Content handler to register.
* @param HttpContentHandler $contentHandler Content handler to register.
*/
public function registerContentHandler(ContentHandler $contentHandler): void {
public function registerContentHandler(HttpContentHandler $contentHandler): void {
if(!in_array($contentHandler, $this->contentHandlers))
$this->contentHandlers[] = $contentHandler;
}
@ -113,8 +115,8 @@ class HttpRouter implements Router {
* Register the default content handlers.
*/
public function registerDefaultContentHandlers(): void {
$this->registerContentHandler(new JsonContentHandler);
$this->registerContentHandler(new BencodeContentHandler);
$this->registerContentHandler(new JsonHttpContentHandler);
$this->registerContentHandler(new BencodeHttpContentHandler);
}
/**
@ -280,7 +282,7 @@ class HttpRouter implements Router {
if(!$response->hasStatusCode() && $result >= 100 && $result < 600)
$this->writeErrorPage($response, $request, $result);
else
$response->setContent(new StringContent((string)$result));
$response->setContent(new StringHttpContent((string)$result));
} elseif(!$response->hasContent()) {
foreach($this->contentHandlers as $contentHandler)
if($contentHandler->match($result)) {
@ -290,7 +292,7 @@ class HttpRouter implements Router {
if(!$response->hasContent() && is_scalar($result)) {
$result = (string)$result;
$response->setContent(new StringContent($result));
$response->setContent(new StringHttpContent($result));
if(!$response->hasContentType()) {
if(strtolower(substr($result, 0, 14)) === '<!doctype html')

View file

@ -1,16 +1,16 @@
<?php
// StringContent.php
// StringHttpContent.php
// Created: 2022-02-10
// Updated: 2024-10-02
namespace Index\Http\Content;
namespace Index\Http;
use Stringable;
/**
* Represents string body content for a HTTP message.
*/
class StringContent implements HttpContent {
class StringHttpContent implements HttpContent {
/**
* @param string $string String that represents this message body.
*/
@ -35,32 +35,32 @@ class StringContent implements HttpContent {
* Creates an instance an existing object.
*
* @param Stringable|string $string Object to cast to a string.
* @return StringContent Instance representing the provided object.
* @return StringHttpContent Instance representing the provided object.
*/
public static function fromObject(Stringable|string $string): StringContent {
return new StringContent((string)$string);
public static function fromObject(Stringable|string $string): StringHttpContent {
return new StringHttpContent((string)$string);
}
/**
* Creates an instance from a file.
*
* @param string $path Path to the file.
* @return StringContent Instance representing the provided path.
* @return StringHttpContent Instance representing the provided path.
*/
public static function fromFile(string $path): StringContent {
public static function fromFile(string $path): StringHttpContent {
$string = file_get_contents($path);
if($string === false)
$string = '';
return new StringContent($string);
return new StringHttpContent($string);
}
/**
* Creates an instance from the raw request body.
*
* @return StringContent Instance representing the request body.
* @return StringHttpContent Instance representing the request body.
*/
public static function fromRequest(): StringContent {
public static function fromRequest(): StringHttpContent {
return self::fromFile('php://input');
}
}

View file

@ -1,17 +1,18 @@
<?php
// JsonContent.php
// JsonHttpContent.php
// Created: 2022-02-10
// Updated: 2024-10-02
namespace Index\Http\Content;
namespace Index\Json;
use JsonSerializable;
use RuntimeException;
use Index\Http\HttpContent;
/**
* Represents JSON body content for a HTTP message.
*/
class JsonContent implements HttpContent, JsonSerializable {
class JsonHttpContent implements HttpContent, JsonSerializable {
/**
* @param mixed $content Content to be JSON encoded.
*/
@ -53,19 +54,19 @@ class JsonContent implements HttpContent, JsonSerializable {
* Creates an instance from encoded content.
*
* @param string $encoded JSON encoded content.
* @return JsonContent Instance representing the provided content.
* @return JsonHttpContent Instance representing the provided content.
*/
public static function fromEncoded(string $encoded): JsonContent {
return new JsonContent(json_decode($encoded));
public static function fromEncoded(string $encoded): JsonHttpContent {
return new JsonHttpContent(json_decode($encoded));
}
/**
* Creates an instance from an encoded file.
*
* @param string $path Path to the JSON encoded file.
* @return JsonContent Instance representing the provided path.
* @return JsonHttpContent Instance representing the provided path.
*/
public static function fromFile(string $path): JsonContent {
public static function fromFile(string $path): JsonHttpContent {
$contents = file_get_contents($path);
if($contents === false)
throw new RuntimeException('was unable to read file at $path');
@ -76,9 +77,9 @@ class JsonContent implements HttpContent, JsonSerializable {
/**
* Creates an instance from the raw request body.
*
* @return JsonContent Instance representing the request body.
* @return JsonHttpContent Instance representing the request body.
*/
public static function fromRequest(): JsonContent {
public static function fromRequest(): JsonHttpContent {
return self::fromFile('php://input');
}
}

View file

@ -1,19 +1,18 @@
<?php
// JsonContentHandler.php
// JsonHttpContentHandler.php
// Created: 2024-03-28
// Updated: 2024-10-02
namespace Index\Http\ContentHandling;
namespace Index\Json;
use stdClass;
use JsonSerializable;
use Index\Http\HttpResponseBuilder;
use Index\Http\Content\JsonContent;
use Index\Http\{HttpContentHandler,HttpResponseBuilder};
/**
* Represents a JSON content handler for building HTTP response messages.
*/
class JsonContentHandler implements ContentHandler {
class JsonHttpContentHandler implements HttpContentHandler {
public function match(mixed $content): bool {
return is_array($content) || $content instanceof JsonSerializable || $content instanceof stdClass;
}
@ -22,6 +21,6 @@ class JsonContentHandler implements ContentHandler {
if(!$response->hasContentType())
$response->setTypeJson();
$response->setContent(new JsonContent($content));
$response->setContent(new JsonHttpContent($content));
}
}