From 20fff7105181951f1ca3e95fab4865743d882305 Mon Sep 17 00:00:00 2001 From: twosee Date: Wed, 31 May 2023 17:45:50 +0800 Subject: [PATCH] Only provide interfaces in psr7-plus --- README.md | 4 +- composer.json | 9 +- src/Message/AbstractMessage.php | 275 ---------------- src/Message/BodyDecoder.php | 78 ----- src/Message/BodyEncoder.php | 61 ---- src/Message/ClientPsr17FactoryTrait.php | 63 ---- src/Message/MessagePsr17FactoryTrait.php | 54 ---- src/Message/PhpStream.php | 305 ------------------ src/Message/Psr17Factory.php | 100 ------ src/Message/Request.php | 166 ---------- src/Message/Response.php | 66 ---- src/Message/ServerPsr17FactoryTrait.php | 79 ----- src/Message/ServerRequest.php | 241 -------------- src/Message/UpgradeType.php | 56 ---- src/Message/UploadedFile.php | 219 ------------- src/Message/Uri.php | 390 ----------------------- src/Message/WebSocketFrame.php | 121 ------- src/Psr7.php | 33 -- src/Utils/ConverterTrait.php | 76 ----- src/Utils/CreatorTrait.php | 351 -------------------- src/Utils/DetectorTrait.php | 58 ---- src/Utils/FactoryTrait.php | 110 ------- src/Utils/OperatorTrait.php | 96 ------ 23 files changed, 3 insertions(+), 3008 deletions(-) delete mode 100644 src/Message/AbstractMessage.php delete mode 100644 src/Message/BodyDecoder.php delete mode 100644 src/Message/BodyEncoder.php delete mode 100644 src/Message/ClientPsr17FactoryTrait.php delete mode 100644 src/Message/MessagePsr17FactoryTrait.php delete mode 100644 src/Message/PhpStream.php delete mode 100644 src/Message/Psr17Factory.php delete mode 100644 src/Message/Request.php delete mode 100644 src/Message/Response.php delete mode 100644 src/Message/ServerPsr17FactoryTrait.php delete mode 100644 src/Message/ServerRequest.php delete mode 100644 src/Message/UpgradeType.php delete mode 100644 src/Message/UploadedFile.php delete mode 100644 src/Message/Uri.php delete mode 100644 src/Message/WebSocketFrame.php delete mode 100644 src/Psr7.php delete mode 100644 src/Utils/ConverterTrait.php delete mode 100644 src/Utils/CreatorTrait.php delete mode 100644 src/Utils/DetectorTrait.php delete mode 100644 src/Utils/FactoryTrait.php delete mode 100644 src/Utils/OperatorTrait.php diff --git a/README.md b/README.md index 1bf7670..b6ab7dd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ # Swow Psr7+ -Swow Psr7+ provides modern strong-typed interfaces and more performant -implementations for Psr7, also including Psr17, WebSocket interfaces and some -useful functions. +Swow Psr7+ provides modern strong-typed interfaces for Psr7, also including Psr17, WebSocket interfaces. diff --git a/composer.json b/composer.json index 6737acb..70a9c39 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "swow/psr7-plus", - "description": "Modern strong-typed interfaces and more performant implementations for Psr7, not only HTTP but also WebSocket", + "description": "Modern strong-typed interfaces for Psr7, not only HTTP but also WebSocket", "keywords": [ "swow", "psr7", @@ -26,12 +26,7 @@ }, "autoload": { "psr-4": { - "Swow\\Psr7": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Swow\\Tests\\": "tests/" + "Swow\\Psr7\\Message\\": "src/Message/" } }, "config": { diff --git a/src/Message/AbstractMessage.php b/src/Message/AbstractMessage.php deleted file mode 100644 index 1b35c77..0000000 --- a/src/Message/AbstractMessage.php +++ /dev/null @@ -1,275 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Error; -use Psr\Http\Message\StreamInterface; -use Swow\Object\StringableTrait; -use Swow\Psr7\Psr7; - -use function array_merge; -use function implode; -use function is_array; -use function strpos; -use function strtolower; -use function substr; -use function trim; - -abstract class AbstractMessage implements MessagePlusInterface -{ - use StringableTrait; - - protected string $protocolVersion = self::DEFAULT_PROTOCOL_VERSION; - - /** - * headers holder format like `[ 'X-Header' => [ 'value 1', 'value 2' ] ]` - * - * @var array> - */ - protected array $headers = []; - - /** - * headers names holder format like `[ 'x-header' => 'X-Header' ]` - * - * @var array - */ - protected array $headerNames = []; - - protected bool $shouldKeepAlive = true; - - protected ?StreamInterface $body = null; - - public function getProtocolVersion(): string - { - return $this->protocolVersion; - } - - public function setProtocolVersion(string $protocolVersion): static - { - $this->protocolVersion = $protocolVersion; - - return $this; - } - - public function withProtocolVersion(mixed $version): static - { - if ($version === $this->protocolVersion) { - return $this; - } - - $new = clone $this; - $new->protocolVersion = $version; - - return $new; - } - - public function hasHeader(mixed $name): bool - { - return isset($this->headerNames[strtolower($name)]); - } - - public function getHeader(mixed $name): array - { - $name = $this->headerNames[strtolower($name)] ?? null; - - return $name !== null ? $this->headers[$name] : []; - } - - public function getHeaderLine(mixed $name): string - { - return implode(', ', $this->getHeader($name)); - } - - /** - * @note header will be unset when value is NULL, - * since headerValue must be an array, - * we can't use NULL to mean that this header should not been sent. - * @param string|array|null $value - */ - public function setHeader(string $name, mixed $value): static - { - $lowercaseName = strtolower($name); - $rawName = $this->headerNames[$lowercaseName] ?? null; - if ($rawName !== null) { - unset($this->headers[$rawName]); - } - - if ($value !== null) { - $this->headers[$name] = is_array($value) ? $value : [(string) $value]; - $this->headerNames[$lowercaseName] = $name; - } else { - unset($this->headerNames[$lowercaseName]); - } - - return $this; - } - - /** - * @param string $name - * @param string|string[] $value - */ - public function withHeader(mixed $name, mixed $value): static - { - return (clone $this)->setHeader((string) $name, $value); - } - - /** @param string|array|null $value */ - public function addHeader(string $name, mixed $value): static - { - $lowercaseName = strtolower($name); - $rawName = $this->headerNames[$lowercaseName] ?? null; - - if ($rawName !== null) { - if (is_array($value)) { - $this->headers[$rawName] = array_merge($this->headers[$rawName], $value); - } else { - $this->headers[$rawName][] = $value; - } - } else { - $this->headerNames[$lowercaseName] = $name; - $this->headers[$name] = is_array($value) ? $value : [(string) $value]; - } - - return $this; - } - - /** - * @param string $name - * @param string|string[] $value - */ - public function withAddedHeader(mixed $name, mixed $value): static - { - return (clone $this)->addHeader($name, $value); - } - - public function unsetHeader(string $name): static - { - return $this->setHeader($name, null); - } - - /** - * @param string $name - */ - public function withoutHeader($name): static - { - return (clone $this)->setHeader($name, null); - } - - /** @return array> $headers */ - public function getHeaders(): array - { - return $this->headers; - } - - /** @return array> $headers */ - public function getStandardHeaders(): array - { - $headers = $this->getHeaders(); - if (!$this->hasHeader('connection')) { - $headers['Connection'] = [$this->shouldKeepAlive() ? 'keep-alive' : 'close']; - } - if (!$this->hasHeader('content-length')) { - $headers['Content-Length'] = [(string) $this->getContentLength()]; - } - - return $headers; - } - - /** @param array|string> $headers */ - public function setHeaders(array $headers): static - { - foreach ($headers as $name => $value) { - $this->setHeader($name, $value); - } - - return $this; - } - - /** - * @param array|string> $headers - * @param array $headerNames - */ - public function setHeadersAndHeaderNames(array $headers, array $headerNames): static - { - $this->headers = $headers; - $this->headerNames = $headerNames; - - return $this; - } - - /** @param array|string> $headers */ - public function withHeaders(array $headers): static - { - return (clone $this)->setHeaders($headers); - } - - public function getContentLength(): int - { - return $this->hasHeader('content-length') ? - (int) $this->getHeaderLine('content-length') : - $this->getBody()->getSize(); - } - - public function getContentType(): string - { - $contentTypeLine = $this->getHeaderLine('content-type'); - if (($pos = strpos($contentTypeLine, ';')) !== false) { - // e.g. application/json; charset=UTF-8 - $contentType = strtolower(trim(substr($contentTypeLine, 0, $pos))); - } else { - $contentType = strtolower($contentTypeLine); - } - - return $contentType; - } - - public function shouldKeepAlive(): bool - { - return $this->shouldKeepAlive; - } - - public function setShouldKeepAlive(bool $shouldKeepAlive): static - { - $this->shouldKeepAlive = $shouldKeepAlive; - - return $this; - } - - public function getBody(): StreamInterface - { - return $this->body ??= Psr7::createStream(); - } - - /** @Notice MUST clone the object before you change the body's content */ - public function setBody(mixed $body): static - { - $this->body = Psr7::createStreamFromAny($body); - - return $this; - } - - public function withBody(StreamInterface $body): static - { - if ($body === $this->body) { - return $this; - } - - return (clone $this)->setBody($body); - } - - public function toString(bool $withoutBody = false): string - { - throw new Error('This should be implemented in child classes'); - } -} diff --git a/src/Message/BodyDecoder.php b/src/Message/BodyDecoder.php deleted file mode 100644 index 69eee5a..0000000 --- a/src/Message/BodyDecoder.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use InvalidArgumentException; -use Psr\Http\Message\StreamInterface; -use SimpleXMLElement; -use Swow\Http\Mime\MimeType; - -use function is_array; -use function json_decode; -use function json_last_error; -use function json_last_error_msg; -use function parse_str; -use function simplexml_load_string; - -use const JSON_ERROR_NONE; -use const LIBXML_NOCDATA; -use const LIBXML_NOERROR; - -class BodyDecoder -{ - /** @return array */ - public static function decode(StreamInterface $stream, string $contentType = MimeType::X_WWW_FORM_URLENCODED): array - { - $contents = (string) $stream; - if (!$contents) { - return []; - } - switch ($contentType) { - case MimeType::JSON: - $data = static::decodeJson($contents); - break; - case MimeType::XML: - $data = static::decodeXml($contents); - break; - default: - parse_str($contents, $data); - break; - } - - return $data; - } - - /** @return array */ - protected static function decodeJson(string $json): array - { - $data = json_decode($json, true); - $code = json_last_error(); - if ($code !== JSON_ERROR_NONE) { - throw new InvalidArgumentException(json_last_error_msg(), $code); - } - - return is_array($data) ? $data : []; - } - - /** @return array */ - protected static function decodeXml(string $xml): array - { - $respObject = simplexml_load_string($xml, SimpleXMLElement::class, LIBXML_NOCDATA | LIBXML_NOERROR); - if ($respObject === false) { - throw new InvalidArgumentException('Syntax error.'); - } - - return (array) $respObject; - } -} diff --git a/src/Message/BodyEncoder.php b/src/Message/BodyEncoder.php deleted file mode 100644 index cffedea..0000000 --- a/src/Message/BodyEncoder.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use RuntimeException; -use SimpleXMLElement; -use Swow\Http\Mime\MimeType; - -use function array_walk_recursive; -use function http_build_query; -use function json_encode; - -use const JSON_THROW_ON_ERROR; - -class BodyEncoder -{ - /** @param array $data */ - public static function encode(array $data, string $contentType = ''): string - { - return match ($contentType) { - MimeType::JSON => static::encodeJson($data), - MimeType::XML => static::encodeXml($data), - default => static::encodeQuery($data), - }; - } - - /** @param array $data */ - public static function encodeJson(array $data): string - { - return json_encode($data, JSON_THROW_ON_ERROR); - } - - /** @param array $data */ - public static function encodeXml(array $data): string - { - $xml = new SimpleXMLElement(''); - array_walk_recursive($data, [$xml, 'addChild']); - $xmlString = $xml->asXML(); - if (!$xmlString) { - throw new RuntimeException('XML encode failed'); - } - return $xmlString; - } - - /** @param array $data */ - public static function encodeQuery(array $data): string - { - return http_build_query($data); - } -} diff --git a/src/Message/ClientPsr17FactoryTrait.php b/src/Message/ClientPsr17FactoryTrait.php deleted file mode 100644 index 95fdd2f..0000000 --- a/src/Message/ClientPsr17FactoryTrait.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Psr\Http\Message\RequestFactoryInterface; -use Psr\Http\Message\ResponseFactoryInterface; -use Psr\Http\Message\StreamFactoryInterface; -use Psr\Http\Message\UriFactoryInterface; -use Swow\Psr7\Psr7; - -trait ClientPsr17FactoryTrait -{ - use MessagePsr17FactoryTrait; - - protected RequestFactoryInterface $requestFactory; - protected ResponseFactoryInterface $responseFactory; - - protected function __constructClientPsr17Factory( - ?UriFactoryInterface $uriFactory = null, - ?StreamFactoryInterface $streamFactory = null, - ?RequestFactoryInterface $requestFactory = null, - ?ResponseFactoryInterface $responseFactory = null - ): void { - $this->__constructMessagePsr17Factory($uriFactory, $streamFactory); - $this->requestFactory = $requestFactory ?? Psr7::getDefaultRequestFactory(); - $this->responseFactory = $responseFactory ?? Psr7::getDefaultResponseFactory(); - } - - public function getRequestFactory(): RequestFactoryInterface - { - return $this->requestFactory; - } - - public function setRequestFactory(RequestFactoryInterface $requestFactory): static - { - $this->requestFactory = $requestFactory; - - return $this; - } - - public function getResponseFactory(): ResponseFactoryInterface - { - return $this->responseFactory; - } - - public function setResponseFactory(ResponseFactoryInterface $responseFactory): static - { - $this->responseFactory = $responseFactory; - - return $this; - } -} diff --git a/src/Message/MessagePsr17FactoryTrait.php b/src/Message/MessagePsr17FactoryTrait.php deleted file mode 100644 index d6858bf..0000000 --- a/src/Message/MessagePsr17FactoryTrait.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Psr\Http\Message\StreamFactoryInterface; -use Psr\Http\Message\UriFactoryInterface; -use Swow\Psr7\Psr7; - -trait MessagePsr17FactoryTrait -{ - protected UriFactoryInterface $uriFactory; - protected StreamFactoryInterface $streamFactory; - - protected function __constructMessagePsr17Factory(?UriFactoryInterface $uriFactory = null, ?StreamFactoryInterface $streamFactory = null): void - { - $this->uriFactory = $uriFactory ?? Psr7::getDefaultUriFactory(); - $this->streamFactory = $streamFactory ?? Psr7::getDefaultStreamFactory(); - } - - public function getUriFactory(): UriFactoryInterface - { - return $this->uriFactory; - } - - public function setUriFactory(UriFactoryInterface $uriFactory): static - { - $this->uriFactory = $uriFactory; - - return $this; - } - - public function getStreamFactory(): StreamFactoryInterface - { - return $this->streamFactory; - } - - public function setStreamFactory(StreamFactoryInterface $streamFactory): static - { - $this->streamFactory = $streamFactory; - - return $this; - } -} diff --git a/src/Message/PhpStream.php b/src/Message/PhpStream.php deleted file mode 100644 index 0ec03f4..0000000 --- a/src/Message/PhpStream.php +++ /dev/null @@ -1,305 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use RuntimeException; -use Swow\Object\StringableTrait; -use TypeError; - -use function clearstatcache; -use function error_get_last; -use function fclose; -use function feof; -use function fread; -use function fseek; -use function fstat; -use function ftell; -use function fwrite; -use function is_resource; -use function sprintf; -use function stream_get_contents; -use function stream_get_meta_data; -use function var_export; - -use const SEEK_CUR; -use const SEEK_SET; - -/** - * Refactored from https://github.com/Nyholm/psr7/blob/master/src/Stream.php - */ -class PhpStream implements StreamPlusInterface -{ - use StringableTrait; - - /** @var array> Hash of readable and writable stream types */ - protected const READ_WRITE_HASH = [ - 'read' => [ - 'r' => true, - 'w+' => true, - 'r+' => true, - 'x+' => true, - 'c+' => true, - 'rb' => true, - 'w+b' => true, - 'r+b' => true, - 'x+b' => true, - 'c+b' => true, - 'rt' => true, - 'w+t' => true, - 'r+t' => true, - 'x+t' => true, - 'c+t' => true, - 'a+' => true, - ], - 'write' => [ - 'w' => true, - 'w+' => true, - 'rw' => true, - 'r+' => true, - 'x+' => true, - 'c+' => true, - 'wb' => true, - 'w+b' => true, - 'r+b' => true, - 'x+b' => true, - 'c+b' => true, - 'w+t' => true, - 'r+t' => true, - 'x+t' => true, - 'c+t' => true, - 'a' => true, - 'a+' => true, - ], - ]; - - /** - * @var resource|null A resource reference - * @psalm-var closed-resource|resource|null - */ - protected $stream; - - protected bool $seekable = false; - - protected bool $readable = false; - - protected bool $writable = false; - - protected ?string $uri = null; - - protected ?int $size = null; - - protected bool $detached = false; - - /** - * @param resource $resource php stream resource - */ - public function __construct($resource) - { - if (!is_resource($resource)) { - throw new TypeError(sprintf('%s(): Argument#1 ($stream) must be a resource, %s given', __METHOD__, get_debug_type($resource))); - } - - $this->stream = $resource; - $meta = stream_get_meta_data($resource); - $this->seekable = $meta['seekable'] && fseek($this->stream, 0, SEEK_CUR) === 0; - $this->readable = isset(static::READ_WRITE_HASH['read'][$meta['mode']]); - $this->writable = isset(static::READ_WRITE_HASH['write'][$meta['mode']]); - } - - protected function getUri(): ?string - { - return $this->uri ??= $this->getMetadata('uri'); - } - - public function getSize(): ?int - { - if ($this->size !== null) { - return $this->size; - } - - if ($this->detached) { - return null; - } - - // Clear the stat cache if the stream has a URI - if ($uri = $this->getUri()) { - clearstatcache(true, $uri); - } - - $stats = fstat($this->stream); - if (isset($stats['size'])) { - $this->size = $stats['size']; - - return $this->size; - } - - return null; - } - - public function tell(): int - { - if ($this->detached) { - throw new RuntimeException('Stream is detached'); - } - - if (($result = @ftell($this->stream)) === false) { - throw new RuntimeException('Unable to determine stream position: ' . (error_get_last()['message'] ?? 'unknown error')); - } - - return $result; - } - - public function eof(): bool - { - return $this->detached || feof($this->stream); - } - - public function isSeekable(): bool - { - return $this->seekable; - } - - public function seek($offset, $whence = SEEK_SET): void - { - if ($this->detached) { - throw new RuntimeException('Stream is detached'); - } - - if (!$this->seekable) { - throw new RuntimeException('Stream is not seekable'); - } - - if (fseek($this->stream, $offset, $whence) === -1) { - throw new RuntimeException('Unable to seek to stream position "' . $offset . '" with whence ' . var_export($whence, true)); - } - } - - public function rewind(): void - { - $this->seek(0); - } - - public function isWritable(): bool - { - return $this->writable; - } - - public function write($string): int - { - if ($this->detached) { - throw new RuntimeException('Stream is detached'); - } - - if (!$this->writable) { - throw new RuntimeException('Cannot write to a non-writable stream'); - } - - // We can't know the size after writing anything - $this->size = null; - - if (false === $result = @fwrite($this->stream, $string)) { - throw new RuntimeException('Unable to write to stream: ' . (error_get_last()['message'] ?? 'unknown error')); - } - - return $result; - } - - public function isReadable(): bool - { - return $this->readable; - } - - public function read($length): string - { - if ($this->detached) { - throw new RuntimeException('Stream is detached'); - } - - if (!$this->readable) { - throw new RuntimeException('Cannot read from non-readable stream'); - } - - if (($result = @fread($this->stream, $length)) === false) { - throw new RuntimeException('Unable to read from stream: ' . (error_get_last()['message'] ?? 'unknown error')); - } - - return $result; - } - - public function getContents(): string - { - if ($this->detached) { - throw new RuntimeException('Stream is detached'); - } - - if (($contents = @stream_get_contents($this->stream)) === false) { - throw new RuntimeException('Unable to read stream contents: ' . (error_get_last()['message'] ?? 'unknown error')); - } - - return $contents; - } - - public function getMetadata(mixed $key = null): mixed - { - if ($this->detached) { - return $key ? null : []; - } - - $meta = stream_get_meta_data($this->stream); - - if ($key === null) { - return $meta; - } - - return $meta[$key] ?? null; - } - - public function detach(): mixed - { - if ($this->detached) { - return null; - } - - $result = $this->stream; - $this->stream = $this->size = $this->uri = null; - $this->readable = $this->writable = $this->seekable = false; - $this->detached = true; - - return $result; - } - - public function close(): void - { - if (isset($this->stream)) { - if (is_resource($this->stream)) { - fclose($this->stream); - } - $this->detach(); - } - } - - public function toString(): string - { - if ($this->isSeekable()) { - $this->seek(0); - } - - return $this->getContents(); - } - - public function __destruct() - { - $this->close(); - } -} diff --git a/src/Message/Psr17Factory.php b/src/Message/Psr17Factory.php deleted file mode 100644 index 7260b02..0000000 --- a/src/Message/Psr17Factory.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Psr\Http\Message\StreamInterface; -use RuntimeException; -use Swow\Buffer; -use Swow\Http\Status; -use Swow\Psr7\Server\Server; -use Swow\Psr7\Server\ServerConnection; - -use function error_get_last; -use function fopen; -use function sprintf; -use function strlen; - -use const UPLOAD_ERR_OK; - -class Psr17Factory implements Psr17PlusFactoryInterface -{ - public function createUri(string $uri = ''): Uri - { - return new Uri($uri); - } - - public function createStream(string $content = ''): BufferStream - { - $buffer = new Buffer(strlen($content)); - if ($content !== '') { - $buffer->append($content); - } - return $this->createStreamFromBuffer($buffer); - } - - public function createStreamFromBuffer(Buffer $buffer): BufferStream - { - return new BufferStream($buffer); - } - - public function createStreamFromFile(string $filename, string $mode = 'rb'): PhpStream - { - $resource = @fopen($filename, $mode); - if ($resource === false) { - throw new RuntimeException(sprintf('The file "%s" cannot be opened with %s mode, reason: %s', $filename, $mode, error_get_last()['message'] ?? 'unknown error')); - } - - return new PhpStream($resource); - } - - public function createStreamFromResource($resource): PhpStream - { - return new PhpStream($resource); - } - - public function createRequest(string $method, mixed $uri): Request - { - return (new Request())->setMethod($method)->setUri($uri); - } - - public function createResponse( - int $code = Status::OK, - string $reasonPhrase = '' - ): Response { - return (new Response())->setStatus($code, $reasonPhrase); - } - - /** - * @param array $serverParams - */ - public function createServerRequest(string $method, mixed $uri, array $serverParams = []): ServerRequest - { - return (new ServerRequest())->setMethod($method)->setUri($uri)->setServerParams($serverParams); - } - - public function createUploadedFile( - StreamInterface $stream, - ?int $size = null, - int $error = UPLOAD_ERR_OK, - ?string $clientFilename = null, - ?string $clientMediaType = null - ): UploadedFile { - return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType); - } - - public function createServerConnection(Server $server): ServerConnection - { - return new ServerConnection($server); - } -} diff --git a/src/Message/Request.php b/src/Message/Request.php deleted file mode 100644 index 5373b6b..0000000 --- a/src/Message/Request.php +++ /dev/null @@ -1,166 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Psr\Http\Message\UriInterface; -use Swow\Http\Http; -use Swow\Psr7\Psr7; - -class Request extends AbstractMessage implements RequestPlusInterface -{ - protected const PRESERVE_HOST = false; - - protected string $method = 'GET'; - - protected UriInterface $uri; - - protected ?string $requestTarget = null; - - public function getMethod(): string - { - return $this->method; - } - - public function setMethod(string $method): static - { - $this->method = $method; - - return $this; - } - - /** - * @param string $method - */ - public function withMethod(mixed $method): static - { - if ($method === $this->method) { - return $this; - } - - return (clone $this)->setMethod($method); - } - - protected function getHostFromUri(): string - { - $uri = $this->getUri(); - - $host = $uri->getHost(); - if ($host !== '') { - $port = $uri->getPort(); - if ($port !== null) { - $host .= ':' . $port; - } - } - - return $host; - } - - protected function updateHostFromUri(): void - { - $host = $this->getHostFromUri(); - if ($host === '') { - return; - } - // Ensure Host is the first header. - // See: http://tools.ietf.org/html/rfc7230#section-5.4 - $this->headers = ['Host' => [$host]] + $this->headers; - $this->headerNames['host'] = 'Host'; - } - - public function getUri(): UriInterface - { - return $this->uri ??= Psr7::createUriFromString('/'); - } - - public function setUri(string|UriInterface $uri, ?bool $preserveHost = null): static - { - if (!($uri instanceof UriInterface)) { - $uri = Psr7::createUriFromString($uri); - } - $this->uri = $uri; - - if (!($preserveHost ?? static::PRESERVE_HOST) || !$this->hasHeader('host')) { - $this->updateHostFromUri(); - } - - return $this; - } - - public function withUri(string|UriInterface $uri, $preserveHost = null): static - { - if ($uri === $this->uri) { - return $this; - } - - return (clone $this)->setUri($uri, $preserveHost); - } - - /** @return array> */ - public function getStandardHeaders(): array - { - $headers = parent::getStandardHeaders(); - - if (!$this->hasHeader('host')) { - // Ensure Host is the first header. - // See: http://tools.ietf.org/html/rfc7230#section-5.4 - $headers = ['Host' => [$this->getHostFromUri()]] + $headers; - } - - return $headers; - } - - public function getRequestTarget(): string - { - if ($this->requestTarget !== null) { - return $this->requestTarget; - } - - $uri = $this->getUri(); - - if (($target = $uri->getPath()) === '') { - $target = '/'; - } - if ($uri->getQuery() !== '') { - $target .= '?' . $uri->getQuery(); - } - - return $target; - } - - public function setRequestTarget(string $requestTarget): static - { - $this->requestTarget = $requestTarget; - - return $this; - } - - /** - * @param string $requestTarget - */ - public function withRequestTarget(mixed $requestTarget): static - { - return (clone $this)->setRequestTarget($requestTarget); - } - - public function toString(bool $withoutBody = false): string - { - return Http::packRequest( - method: $this->getMethod(), - uri: (string) $this->getUri(), - headers: $this->getStandardHeaders(), - body: $withoutBody ? '' : (string) $this->getBody(), - protocolVersion: $this->getProtocolVersion() - ); - } -} diff --git a/src/Message/Response.php b/src/Message/Response.php deleted file mode 100644 index 01b328a..0000000 --- a/src/Message/Response.php +++ /dev/null @@ -1,66 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Swow\Http\Http; -use Swow\Http\Status; - -class Response extends AbstractMessage implements ResponsePlusInterface -{ - protected int $statusCode = Status::OK; - - protected string $reasonPhrase = 'OK'; - - public function getStatusCode(): int - { - return $this->statusCode; - } - - public function getReasonPhrase(): string - { - return $this->reasonPhrase; - } - - public function setStatus(int $code, string $reasonPhrase = ''): static - { - $this->statusCode = $code; - $this->reasonPhrase = $reasonPhrase ?: Status::getReasonPhraseOf($code); - - return $this; - } - - /** - * @param int $code - * @param string $reasonPhrase - */ - public function withStatus($code, $reasonPhrase = ''): static - { - if ($reasonPhrase === '' && $code === $this->statusCode) { - return $this; - } - - return (clone $this)->setStatus($code, $reasonPhrase); - } - - public function toString(bool $withoutBody = false): string - { - return Http::packResponse( - statusCode: $this->getStatusCode(), - reasonPhrase: $this->getReasonPhrase(), - headers: $this->getStandardHeaders(), - body: $withoutBody ? '' : (string) $this->getBody(), - protocolVersion: $this->getProtocolVersion() - ); - } -} diff --git a/src/Message/ServerPsr17FactoryTrait.php b/src/Message/ServerPsr17FactoryTrait.php deleted file mode 100644 index 10a2d93..0000000 --- a/src/Message/ServerPsr17FactoryTrait.php +++ /dev/null @@ -1,79 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Psr\Http\Message\ResponseFactoryInterface; -use Psr\Http\Message\ServerRequestFactoryInterface; -use Psr\Http\Message\StreamFactoryInterface; -use Psr\Http\Message\UploadedFileFactoryInterface; -use Psr\Http\Message\UriFactoryInterface; -use Swow\Psr7\Psr7; - -trait ServerPsr17FactoryTrait -{ - use MessagePsr17FactoryTrait; - - protected ServerRequestFactoryInterface $serverRequestFactory; - protected ResponseFactoryInterface $responseFactory; - protected UploadedFileFactoryInterface $uploadedFileFactory; - - protected function __constructServerPsr17Factory( - ?UriFactoryInterface $uriFactory = null, - ?StreamFactoryInterface $streamFactory = null, - ?ServerRequestFactoryInterface $serverRequestFactory = null, - ?ResponseFactoryInterface $responseFactory = null, - ?UploadedFileFactoryInterface $uploadedFileFactory = null - ): void { - $this->__constructMessagePsr17Factory($uriFactory, $streamFactory); - $this->serverRequestFactory = $serverRequestFactory ?? Psr7::getDefaultServerRequestFactory(); - $this->responseFactory = $responseFactory ?? Psr7::getDefaultResponseFactory(); - $this->uploadedFileFactory = $uploadedFileFactory ?? Psr7::getDefaultUploadedFileFactory(); - } - - public function getServerRequestFactory(): ServerRequestFactoryInterface - { - return $this->serverRequestFactory; - } - - public function setServerRequestFactory(ServerRequestFactoryInterface $serverRequestFactory): static - { - $this->serverRequestFactory = $serverRequestFactory; - - return $this; - } - - public function getResponseFactory(): ResponseFactoryInterface - { - return $this->responseFactory; - } - - public function setResponseFactory(ResponseFactoryInterface $responseFactory): static - { - $this->responseFactory = $responseFactory; - - return $this; - } - - public function getUploadedFileFactory(): UploadedFileFactoryInterface - { - return $this->uploadedFileFactory; - } - - public function setUploadedFileFactory(UploadedFileFactoryInterface $uploadedFileFactory): static - { - $this->uploadedFileFactory = $uploadedFileFactory; - - return $this; - } -} diff --git a/src/Message/ServerRequest.php b/src/Message/ServerRequest.php deleted file mode 100644 index 76147c7..0000000 --- a/src/Message/ServerRequest.php +++ /dev/null @@ -1,241 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Psr\Http\Message\UploadedFileInterface; - -use function array_key_exists; - -class ServerRequest extends Request implements ServerRequestPlusInterface -{ - /** - * @var bool Keep the Host header (The server may verify its legitimacy) - */ - protected const PRESERVE_HOST = true; - - /** @var array */ - protected array $serverParams = []; - - /** @var array */ - protected array $cookieParams = []; - - /** @var array */ - protected array $queryParams = []; - - /** @var array|object|null */ - protected array|object|null $parsedBody; - - protected ?int $contentLength = null; - - protected ?string $contentType = null; - - protected ?bool $isUpgrade = null; - - /** - * @var UploadedFileInterface[] - */ - protected array $uploadedFiles = []; - - /** @var array */ - protected array $attributes = []; - - final public function __construct() - { - } - - /** @return array */ - public function getServerParams(): array - { - return $this->serverParams; - } - - /** @param array $serverParams */ - public function setServerParams(array $serverParams): static - { - $this->serverParams = $serverParams; - - return $this; - } - - /** @param array $serverParams */ - public function withServerParams(array $serverParams): static - { - $new = clone $this; - $new->serverParams = $serverParams; - - return $new; - } - - /** @return array */ - public function getQueryParams(): array - { - return $this->queryParams; - } - - /** @param array $query */ - public function setQueryParams(array $query): static - { - $this->queryParams = $query; - - return $this; - } - - /** @param array $query */ - public function withQueryParams(array $query): static - { - $new = clone $this; - $new->queryParams = $query; - - return $new; - } - - /** @return array */ - public function getCookieParams(): array - { - return $this->cookieParams; - } - - /** @param array $cookies */ - public function setCookieParams(array $cookies): static - { - $this->cookieParams = $cookies; - - return $this; - } - - /** @param array $cookies */ - public function withCookieParams(array $cookies): static - { - $new = clone $this; - $new->cookieParams = $cookies; - - return $new; - } - - public function getContentLength(): int - { - return $this->contentLength ??= parent::getContentLength(); - } - - public function getContentType(): string - { - return $this->contentType ??= parent::getContentType(); - } - - public function isUpgrade(): ?bool - { - return $this->isUpgrade; - } - - public function setIsUpgrade(bool $isUpgrade): static - { - $this->isUpgrade = $isUpgrade; - - return $this; - } - - /** @return array|object */ - public function getParsedBody(): array|object - { - return $this->parsedBody ??= BodyDecoder::decode($this->getBody(), $this->getContentType()); - } - - /** @param array|object|null $data */ - public function setParsedBody(array|object|null $data): static - { - $this->parsedBody = $data; - - return $this; - } - - /** @param array|object $data */ - public function withParsedBody($data): static - { - return (clone $this)->setParsedBody($data); - } - - /** @return array */ - public function getUploadedFiles(): array - { - return $this->uploadedFiles; - } - - /** @param array $uploadedFiles */ - public function setUploadedFiles(array $uploadedFiles): static - { - $this->uploadedFiles = $uploadedFiles; - - return $this; - } - - /** @param array $uploadedFiles */ - public function withUploadedFiles(array $uploadedFiles) - { - $new = clone $this; - $new->uploadedFiles = $uploadedFiles; - - return $new; - } - - /** @return array */ - public function getAttributes(): array - { - return $this->attributes; - } - - /** - * @param string $name - * @param mixed $default - */ - public function getAttribute(mixed $name, mixed $default = null): mixed - { - if (array_key_exists($name, $this->attributes) === false) { - return $default; - } - - return $this->attributes[$name]; - } - - public function setAttribute(string $name, mixed $value): static - { - $this->attributes[$name] = $value; - - return $this; - } - - /** - * @param string $name - */ - public function withAttribute(mixed $name, mixed $value): static - { - return (clone $this)->setAttribute($name, $value); - } - - public function unsetAttribute(string $name): static - { - unset($this->attributes[$name]); - - return $this; - } - - /** @param string $name */ - public function withoutAttribute($name): static - { - if (array_key_exists($name, $this->attributes) === false) { - return $this; - } - - return (clone $this)->unsetAttribute($name); - } -} diff --git a/src/Message/UpgradeType.php b/src/Message/UpgradeType.php deleted file mode 100644 index 23f3ecc..0000000 --- a/src/Message/UpgradeType.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use function array_map; -use function explode; -use function strcasecmp; -use function strlen; -use function trim; - -class UpgradeType -{ - public const UPGRADE_TYPE_NONE = 0; - public const UPGRADE_TYPE_WEBSOCKET = 1 << 0; - public const UPGRADE_TYPE_H2C = 1 << 1; - public const UPGRADE_TYPE_UNKNOWN = 1 << 31; - - public static function fromString(string $upgrade): int - { - $upgrade = trim($upgrade); - if ($upgrade === '') { - return static::UPGRADE_TYPE_NONE; - } - $upgradeType = static::UPGRADE_TYPE_NONE; - $upgradeList = array_map('trim', explode(',', $upgrade)); - foreach ($upgradeList as $upgradeElement) { - $upgradeParts = explode('/', $upgradeElement, 2); - $upgradeProtocol = $upgradeParts[0] ?? ''; - if ( - strlen($upgradeProtocol) === strlen('websocket') && - strcasecmp($upgradeProtocol, 'websocket') === 0 - ) { - $upgradeType |= static::UPGRADE_TYPE_WEBSOCKET; - } elseif ( - strlen($upgradeProtocol) === strlen('h2c') && - strcasecmp($upgradeProtocol, 'h2c') === 0 - ) { - $upgradeType |= static::UPGRADE_TYPE_H2C; - } else { - $upgradeType |= static::UPGRADE_TYPE_UNKNOWN; - } - } - return $upgradeType; - } -} diff --git a/src/Message/UploadedFile.php b/src/Message/UploadedFile.php deleted file mode 100644 index 40d6e21..0000000 --- a/src/Message/UploadedFile.php +++ /dev/null @@ -1,219 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Psr\Http\Message\StreamInterface; -use RuntimeException; -use Swow\Object\ArrayableInterface; -use TypeError; -use ValueError; - -use function error_get_last; -use function fopen; -use function is_resource; -use function is_string; -use function pathinfo; -use function sprintf; -use function Swow\Debug\isStringable; - -use const PATHINFO_EXTENSION; -use const PHP_SAPI; -use const UPLOAD_ERR_CANT_WRITE; -use const UPLOAD_ERR_EXTENSION; -use const UPLOAD_ERR_FORM_SIZE; -use const UPLOAD_ERR_INI_SIZE; -use const UPLOAD_ERR_NO_FILE; -use const UPLOAD_ERR_NO_TMP_DIR; -use const UPLOAD_ERR_OK; -use const UPLOAD_ERR_PARTIAL; - -/** - * PSR-7 UploadedFile implementation (https://github.com/Nyholm/psr7/blob/master/src/UploadedFile.php) - */ -class UploadedFile implements UploadedFilePlusInterface, ArrayableInterface -{ - protected const ERRORS = [ - UPLOAD_ERR_OK => true, - UPLOAD_ERR_INI_SIZE => true, - UPLOAD_ERR_FORM_SIZE => true, - UPLOAD_ERR_PARTIAL => true, - UPLOAD_ERR_NO_FILE => true, - UPLOAD_ERR_NO_TMP_DIR => true, - UPLOAD_ERR_CANT_WRITE => true, - UPLOAD_ERR_EXTENSION => true, - ]; - - protected StreamInterface $stream; - - protected ?int $size; - - protected int $error; - - protected ?string $clientFilename; - - protected ?string $clientMediaType; - - protected ?string $file = null; - - protected bool $moved = false; - - /** - * @param string|resource|StreamInterface $streamOrFile - */ - public function __construct(mixed $streamOrFile, ?int $size = null, int $error = UPLOAD_ERR_OK, ?string $clientFilename = null, ?string $clientMediaType = null) - { - if (!isset(static::ERRORS[$error])) { - throw new ValueError(sprintf('Invalid error status for UploadedFile: %s', $error)); - } - - $this->error = $error; - $this->size = $size; - $this->clientFilename = $clientFilename; - $this->clientMediaType = $clientMediaType; - - if ($this->error !== UPLOAD_ERR_OK) { - return; - } - - while (true) { - if ($streamOrFile instanceof StreamInterface) { - $this->stream = $streamOrFile; - $metaData = $streamOrFile->getMetadata(); - if ($metaData['wrapper_type'] === 'plainfile') { - $this->file = $metaData['uri']; - } - } elseif (is_resource($streamOrFile)) { - $streamOrFile = new PhpStream($streamOrFile); - continue; - } elseif (is_string($streamOrFile)) { - $fp = @fopen($streamOrFile, 'rb'); - if ($fp === false) { - throw new RuntimeException(sprintf('Uploaded file "%s" could not be opened: %s', $streamOrFile, error_get_last()['message'] ?? 'unknown error')); - } - $this->stream = new PhpStream($fp); - $this->file = $streamOrFile; - } - break; - } - } - - public function __destruct() - { - if (!$this->moved && $this->file !== null) { - @unlink($this->file); - } - } - - /** - * @throws RuntimeException if is moved or not ok - */ - protected function validateActive(): void - { - if ($this->error !== UPLOAD_ERR_OK) { - throw new RuntimeException('Cannot retrieve stream due to upload error'); - } - - if ($this->moved) { - throw new RuntimeException('Cannot retrieve stream after it has already been moved'); - } - } - - public function getStream(): StreamInterface - { - $this->validateActive(); - - return $this->stream; - } - - public function moveTo(mixed $targetPath): void - { - if (!isStringable($targetPath)) { - throw new TypeError(sprintf('%s(): Argument#1 ($targetPath) must be a string, %s given', __METHOD__, get_debug_type($targetPath))); - } - $targetPath = (string) $targetPath; - if ($targetPath === '') { - throw new ValueError(sprintf('%s(): Argument#1 ($targetPath) must be a non-empty string', __METHOD__)); - } - - $this->validateActive(); - - if ($this->file !== null) { - $this->moved = 'cli' === PHP_SAPI ? @rename($this->file, $targetPath) : @move_uploaded_file($this->file, $targetPath); - if ($this->moved === false) { - throw new RuntimeException(sprintf('Uploaded file could not be moved to "%s": %s', $targetPath, error_get_last()['message'] ?? 'unknown error')); - } - } else { - $stream = $this->getStream(); - if ($stream->isSeekable()) { - $stream->rewind(); - } - if (($resource = @fopen($targetPath, 'wb+')) === false) { - throw new RuntimeException(sprintf('The file "%s" cannot be opened: %s', $targetPath, error_get_last()['message'] ?? 'unknown error')); - } - $dest = new PhpStream($resource); - while (!$stream->eof()) { - if (!$dest->write($stream->read(1024 * 1024))) { - break; - } - } - $this->moved = true; - } - } - - public function getSize(): ?int - { - return $this->size; - } - - public function getError(): int - { - return $this->error; - } - - public function getClientFilename(): ?string - { - return $this->clientFilename; - } - - public function getClientMediaType(): ?string - { - return $this->clientMediaType; - } - - public function getExtension(): string - { - $clientFileName = $this->getClientFilename(); - if (!$clientFileName) { - throw new RuntimeException('Upload file name is not available'); - } - return pathinfo($clientFileName, PATHINFO_EXTENSION); - } - - public function isMoved(): bool - { - return $this->moved; - } - - /** @return array{'name': string|null, 'type': string|null, 'tmp_file': string|null, 'error': int, 'size': int|false} */ - public function toArray(): array - { - return [ - 'name' => $this->getClientFilename(), - 'type' => $this->getClientMediaType(), - 'tmp_file' => $this->file, - 'error' => $this->getError(), - 'size' => $this->getSize(), - ]; - } -} diff --git a/src/Message/Uri.php b/src/Message/Uri.php deleted file mode 100644 index 64f2463..0000000 --- a/src/Message/Uri.php +++ /dev/null @@ -1,390 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use InvalidArgumentException; -use Swow\Object\StringableInterface; -use Swow\Object\StringableTrait; - -use function http_build_query; -use function parse_str; -use function parse_url; -use function preg_replace_callback; -use function rawurlencode; -use function sprintf; -use function str_starts_with; -use function strtolower; - -/** - * PSR-7 URI implementation (https://github.com/Nyholm/psr7/blob/master/src/Uri.php) - */ -class Uri implements UriPlusInterface, StringableInterface -{ - use StringableTrait; - - protected const SCHEMES = ['http' => 80, 'https' => 443]; - - protected string $scheme = ''; - - protected string $userInfo = ''; - - protected string $host = ''; - - protected ?int $port = null; - - protected string $path = ''; - - protected string $query = ''; - - /** @var array|null */ - protected ?array $queryParams = null; - - protected string $fragment = ''; - - public function __construct(string $uri = '') - { - if ($uri !== '') { - $this->apply($uri); - } - } - - public function apply(string $uri): static - { - /** - * @var array|false $parts - */ - $parts = parse_url($uri); - if ($parts === false) { - throw new InvalidArgumentException("Unable to parse URI: {$uri}"); - } - - return $this->applyParts($parts); - } - - /** - * @param array $parts - */ - public function applyParts(array $parts): static - { - $this->scheme = isset($parts['scheme']) ? strtolower($parts['scheme']) : ''; - $this->userInfo = $parts['user'] ?? ''; - $this->host = isset($parts['host']) ? strtolower($parts['host']) : ''; - $this->port = isset($parts['port']) ? $this->filterPort((int) $parts['port']) : null; - $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; - $this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : ''; - $this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : ''; - if (isset($parts['pass'])) { - $this->userInfo .= ':' . $parts['pass']; - } - - return $this; - } - - protected function filterSchemeAndHost(string $host): string - { - return strtolower($host); - } - - public function getScheme(): string - { - return $this->scheme; - } - - public function setScheme(string $scheme): static - { - $scheme = $this->filterSchemeAndHost($scheme); - if ($scheme !== $this->scheme) { - $this->scheme = $scheme; - $this->port = $this->filterPort($this->port); - } - - return $this; - } - - /** @param string $scheme */ - public function withScheme(mixed $scheme): static - { - $scheme = $this->filterSchemeAndHost($scheme); - if ($scheme === $this->scheme) { - return $this; - } - - return (clone $this)->setScheme($scheme); - } - - public function getAuthority(): string - { - if ($this->host === '') { - return ''; - } - - $authority = $this->host; - if ($this->userInfo !== '') { - $authority = $this->userInfo . '@' . $authority; - } - - if ($this->port !== null) { - $authority .= ':' . $this->port; - } - - return $authority; - } - - public function getUserInfo(): string - { - return $this->userInfo; - } - - protected function filterUserInfo(string $user, string $password = ''): string - { - return $password === '' ? $user : "{$user}:{$password}"; - } - - public function setUserInfo(string $user, string $password = ''): static - { - $this->userInfo = $this->filterUserInfo($user, $password); - - return $this; - } - - /** - * @param string $user - * @param string $password - */ - public function withUserInfo(mixed $user, mixed $password = ''): static - { - $userInfo = $this->filterUserInfo($user, $password); - if ($userInfo === $this->userInfo) { - return $this; - } - - $new = clone $this; - $new->userInfo = $userInfo; - - return $new; - } - - public function getHost(): string - { - return $this->host; - } - - public function setHost(string $host): static - { - $this->host = $this->filterSchemeAndHost($host); - - return $this; - } - - /** @param string $host */ - public function withHost(mixed $host): static - { - $host = $this->filterSchemeAndHost($host); - if ($host === $this->host) { - return $this; - } - - return (clone $this)->setHost($host); - } - - public function getPort(): ?int - { - return $this->port; - } - - protected function filterPort(?int $port): ?int - { - if ($port === null) { - return null; - } - - if ($port < 0 || $port > 0xFFFF) { - throw new InvalidArgumentException(sprintf('Invalid port: %d. Must be between 0 and 65535', $port)); - } - - $scheme = $this->scheme; - if (isset(static::SCHEMES[$scheme]) && $port === static::SCHEMES[$scheme]) { - return null; - } - - return $port; - } - - public function setPort(?int $port): static - { - $this->port = $this->filterPort($port); - - return $this; - } - - /** @param int $port */ - public function withPort($port): static - { - $port = $this->filterPort($port); - if ($port === $this->port) { - return $this; - } - - $new = clone $this; - $new->port = $port; - - return $new; - } - - public function getPath(): string - { - return $this->path; - } - - protected function filterPath(string $path): string - { - return preg_replace_callback( - '/[^a-zA-Z0-9_\-.~!&\'()*+,;=%:@\/]++|%(?![A-Fa-f0-9]{2})/', - static fn(array $match): string => rawurlencode($match[0]), - $path - ); - } - - public function setPath(string $path): static - { - $this->path = $this->filterPath($path); - - return $this; - } - - /** @param string $path */ - public function withPath(mixed $path): static - { - $path = $this->filterPath($path); - if ($path === $this->path) { - return $this; - } - - $new = clone $this; - $new->path = $path; - - return $new; - } - - protected function filterQueryAndFragment(string $string): string - { - return preg_replace_callback( - '/[^a-zA-Z0-9_\-.~!&\'()*+,;=%:@\/?]++|%(?![A-Fa-f0-9]{2})/', - static fn(array $match): string => rawurlencode($match[0]), - $string - ); - } - - public function getQuery(): string - { - return $this->query; - } - - public function setQuery(string $query): static - { - $this->query = $this->filterQueryAndFragment($query); - $this->queryParams = null; - - return $this; - } - - /** @param string $query */ - public function withQuery(mixed $query): static - { - $query = $this->filterQueryAndFragment($query); - if ($query === $this->query) { - return $this; - } - - $new = clone $this; - $new->query = $query; - $new->queryParams = null; - - return $new; - } - - /** @return array */ - public function getQueryParams(): array - { - if (!isset($this->queryParams)) { - $query = $this->query; - if ($query === '') { - $this->queryParams = []; - } else { - parse_str($query, $this->queryParams); - } - } - - return $this->queryParams; - } - - public function setQueryParams(array $queryParams): static - { - $this->query = http_build_query($queryParams); - $this->queryParams = $queryParams; - - return $this; - } - - public function withQueryParams(array $queryParams): static - { - return (clone $this)->setQueryParams($queryParams); - } - - public function getFragment(): string - { - return $this->fragment; - } - - public function setFragment(string $fragment): static - { - $this->fragment = $this->filterQueryAndFragment($fragment); - - return $this; - } - - /** @param string $fragment */ - public function withFragment(mixed $fragment): static - { - $fragment = $this->filterQueryAndFragment($fragment); - if ($fragment === $this->fragment) { - return $this; - } - - $new = clone $this; - $new->fragment = $fragment; - - return $new; - } - - public static function build(string $scheme, string $authority, string $path, string $query, string $fragment): string - { - $schemeSuffix = $scheme !== '' ? ':' : ''; - $authorityPrefix = $authority !== '' ? '//' : ''; - $pathPrefix = ''; - if ($path !== '' && !str_starts_with($path, '/') && $authority !== '') { - // If the path is rootless and an authority is present, the path MUST be prefixed by "/" - $pathPrefix = '/'; - } - $queryPrefix = $query !== '' ? '?' : ''; - $fragmentPrefix = $fragment !== '' ? '#' : ''; - - return $scheme . $schemeSuffix . $authorityPrefix . $authority . $pathPrefix . $path . $queryPrefix . $query . $fragmentPrefix . $fragment; - } - - public function toString(): string - { - return static::build($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment); - } -} diff --git a/src/Message/WebSocketFrame.php b/src/Message/WebSocketFrame.php deleted file mode 100644 index 0a89d3e..0000000 --- a/src/Message/WebSocketFrame.php +++ /dev/null @@ -1,121 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Message; - -use Psr\Http\Message\StreamInterface; -use Swow\Object\StringableTrait; -use Swow\Psr7\Psr7; -use Swow\WebSocket\Header as WebSocketHeader; -use Swow\WebSocket\Opcode; - -class WebSocketFrame extends WebSocketHeader implements WebSocketFrameInterface -{ - use StringableTrait; - - protected ?StreamInterface $payloadData = null; - - public function __construct( - bool $fin = true, - bool $rsv1 = false, - bool $rsv2 = false, - bool $rsv3 = false, - int $opcode = Opcode::TEXT, - int $payloadLength = 0, - string $maskingKey = '', - mixed $payloadData = '', - ) { - parent::__construct($fin, $rsv1, $rsv2, $rsv3, $opcode, $payloadLength, $maskingKey); - if ($payloadData !== null && $payloadData !== '') { - $this->setPayloadData($payloadData); - } - } - - public function withOpcode(int $opcode): static - { - return (clone $this)->setOpcode($opcode); - } - - public function withFin(bool $fin): static - { - return (clone $this)->setFin($fin); - } - - public function withRSV1(bool $rsv1): static - { - return (clone $this)->setRSV1($rsv1); - } - - public function withRSV2(bool $rsv2): static - { - return (clone $this)->setRSV2($rsv2); - } - - public function withRSV3(bool $rsv3): static - { - return (clone $this)->setRSV3($rsv3); - } - - public function withPayloadLength(int $payloadLength): static - { - return (clone $this)->setPayloadLength($payloadLength); - } - - public function withMaskingKey(string $maskingKey): static - { - return (clone $this)->setMaskingKey($maskingKey); - } - - protected function updateHeader(): void - { - $this->setPayloadLength($this->getPayloadData()->getSize()); - } - - public function getHeaderSize(): int - { - $this->updateHeader(); - return parent::getHeaderSize(); - } - - public function getPayloadLength(): int - { - return $this->getPayloadData()->getSize(); - } - - public function getPayloadData(): StreamInterface - { - return $this->payloadData ??= Psr7::createStream(); - } - - public function setPayloadData(mixed $payloadData): static - { - $this->payloadData = Psr7::createStreamFromAny($payloadData); - - return $this; - } - - public function withPayloadData(mixed $payloadData): static - { - return (clone $this)->setPayloadData($payloadData); - } - - public function toString(bool $withoutPayloadData = false): string - { - $this->updateHeader(); - $string = parent::toString(); - if (!$withoutPayloadData && $this->payloadData !== null) { - $string .= ((string) $this->payloadData); - } - return $string; - } -} diff --git a/src/Psr7.php b/src/Psr7.php deleted file mode 100644 index e89ec8a..0000000 --- a/src/Psr7.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7; - -use Swow\Psr7\Utils\ConverterTrait; -use Swow\Psr7\Utils\CreatorTrait; -use Swow\Psr7\Utils\DetectorTrait; -use Swow\Psr7\Utils\FactoryTrait; -use Swow\Psr7\Utils\OperatorTrait; - -class Psr7 -{ - use ConverterTrait; - - use CreatorTrait; - - use DetectorTrait; - - use FactoryTrait; - - use OperatorTrait; -} diff --git a/src/Utils/ConverterTrait.php b/src/Utils/ConverterTrait.php deleted file mode 100644 index bf68054..0000000 --- a/src/Utils/ConverterTrait.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Utils; - -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Swow\Http\Http; -use Swow\Psr7\Message\RequestPlusInterface; -use Swow\Psr7\Message\ResponsePlusInterface; - -trait ConverterTrait -{ - /** - * @return array - * @phan-return array{0: string, 1: string} - * @phpstan-return array{0: string, 1: string} - * @psalm-return array{0: string, 1: string} - */ - public static function convertResponseToVector(ResponseInterface $response): array - { - if ($response instanceof ResponsePlusInterface) { - return [ - $response->toString(true), - (string) $response->getBody(), - ]; - } - return [ - Http::packResponse( - statusCode: $response->getStatusCode(), - reasonPhrase: $response->getReasonPhrase(), - headers: $response->getHeaders(), - protocolVersion: $response->getProtocolVersion() - ), - (string) $response->getBody(), - ]; - } - - public static function stringifyRequest(RequestInterface $request, bool $withoutBody = false): string - { - if ($request instanceof RequestPlusInterface) { - return $request->toString($withoutBody); - } - return Http::packRequest( - method: $request->getMethod(), - uri: (string) $request->getUri(), - headers: $request->getHeaders(), - body: $withoutBody ? '' : (string) $request->getBody(), - protocolVersion: $request->getProtocolVersion() - ); - } - - public static function stringifyResponse(ResponseInterface $response, bool $withoutBody = false): string - { - if ($response instanceof ResponsePlusInterface) { - return $response->toString($withoutBody); - } - return Http::packResponse( - statusCode: $response->getStatusCode(), - reasonPhrase: $response->getReasonPhrase(), - headers: $response->getHeaders(), - body: $withoutBody ? '' : (string) $response->getBody(), - protocolVersion: $response->getProtocolVersion() - ); - } -} diff --git a/src/Utils/CreatorTrait.php b/src/Utils/CreatorTrait.php deleted file mode 100644 index 5aa7fe4..0000000 --- a/src/Utils/CreatorTrait.php +++ /dev/null @@ -1,351 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Utils; - -use Psr\Http\Message\RequestFactoryInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseFactoryInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestFactoryInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Message\StreamFactoryInterface; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UploadedFileFactoryInterface; -use Psr\Http\Message\UploadedFileInterface; -use Psr\Http\Message\UriFactoryInterface; -use Psr\Http\Message\UriInterface; -use Swow\Buffer; -use Swow\Http\Message\ResponseEntity; -use Swow\Http\Message\ServerRequestEntity; -use Swow\Http\Status; -use Swow\Psr7\Message\BufferStream; -use Swow\Psr7\Message\PhpStream; -use Swow\Psr7\Message\Psr17Factory; -use Swow\Psr7\Message\Request; -use Swow\Psr7\Message\Response; -use Swow\Psr7\Message\ResponsePlusInterface; -use Swow\Psr7\Message\ServerRequest; -use Swow\Psr7\Message\ServerRequestPlusInterface; -use Swow\Psr7\Message\StreamPlusInterface; -use Swow\Psr7\Message\UploadedFile; -use Swow\Psr7\Message\UploadedFilePlusInterface; -use Swow\Psr7\Message\Uri; -use Swow\Psr7\Message\UriPlusInterface; -use Swow\Psr7\Message\WebSocketFrame; -use Swow\WebSocket\Opcode; -use Swow\WebSocket\WebSocket; - -use function is_resource; -use function is_string; -use function parse_str; - -trait CreatorTrait -{ - /** - * @return UriInterface|UriPlusInterface|Uri - */ - public static function createUriFromString(string $uri, ?UriFactoryInterface $uriFactory = null): UriInterface - { - $uriFactory ??= static::getDefaultUriFactory(); - return $uriFactory->createUri($uri); - } - - /** - * @return StreamInterface|StreamPlusInterface|BufferStream - */ - public static function createStream(string $data = '', ?StreamFactoryInterface $streamFactory = null): StreamInterface - { - return ($streamFactory ?? static::getDefaultStreamFactory())->createStream($data); - } - - /** - * @return StreamInterface|StreamPlusInterface|BufferStream - */ - public static function createStreamFromBuffer(Buffer $buffer, ?StreamFactoryInterface $streamFactory = null): StreamInterface - { - $streamFactory ??= static::getDefaultStreamFactory(); - if ($streamFactory instanceof Psr17Factory) { - return $streamFactory->createStreamFromBuffer($buffer); - } else { - return $streamFactory->createStream((string) $buffer); - } - } - - /** - * @return StreamInterface|StreamPlusInterface|BufferStream|PhpStream - */ - public static function createStreamFromAny(mixed $data = '', ?StreamFactoryInterface $streamFactory = null): StreamInterface - { - if ($data instanceof StreamInterface) { - return $data; - } - $streamFactory ??= static::getDefaultStreamFactory(); - if (is_resource($data)) { - return $streamFactory->createStreamFromResource($data); - } - if ($data instanceof Buffer && $streamFactory instanceof Psr17Factory) { - return $streamFactory->createStreamFromBuffer($data); - } else { - return $streamFactory->createStream((string) $data); - } - } - - /** - * @param array|string> $headers - * @return RequestInterface|Request - */ - public static function createRequest( - string $method, - mixed $uri, - array $headers = [], - mixed $body = null, - ?RequestFactoryInterface $requestFactory = null - ): RequestInterface { - $requestFactory ??= static::getDefaultRequestFactory(); - $request = $requestFactory->createRequest($method, $uri); - if ($headers) { - $request = static::setHeaders($request, $headers); - } - if ($body) { - $request = static::setBody($request, $body); - } - return $request; - } - - /** - * @param array|string> $headers - * @return ResponseInterface|ResponsePlusInterface|Response - */ - public static function createResponse( - int $code = Status::OK, - string $reasonPhrase = '', - array $headers = [], - mixed $body = null, - ?ResponseFactoryInterface $responseFactory = null - ): ResponseInterface { - $responseFactory ??= static::getDefaultResponseFactory(); - $response = $responseFactory->createResponse($code, $reasonPhrase); - if ($headers) { - $response = static::setHeaders($response, $headers); - } - if ($body) { - $response = static::setBody($response, $body); - } - return $response; - } - - /** - * @return ResponseInterface|ResponsePlusInterface|Response - */ - public static function createResponseFromEntity(ResponseEntity $responseEntity, ?ResponseFactoryInterface $responseFactory = null, ?StreamFactoryInterface $streamFactory = null): ResponseInterface - { - $responseFactory ??= static::getDefaultResponseFactory(); - $body = $responseEntity->body; - if ($body) { - $bodyStream = static::createStreamFromBuffer($body, $streamFactory); - } else { - $bodyStream = null; - } - $response = $responseFactory->createResponse( - $responseEntity->statusCode, - $responseEntity->reasonPhrase - ); - if ($response instanceof ResponsePlusInterface) { - $response - ->setProtocolVersion($responseEntity->protocolVersion) - ->setHeadersAndHeaderNames( - $responseEntity->headers, - $responseEntity->headerNames - ); - if ($bodyStream) { - $response->setBody($bodyStream); - } - if ($response instanceof Response) { - if (!$responseEntity->shouldKeepAlive) { - $response->setShouldKeepAlive(false); - } - } - } else { - $response = $response->withProtocolVersion($responseEntity->protocolVersion); - foreach ($responseEntity->headers as $headerName => $headerValue) { - $response = $response->withHeader($headerName, $headerValue); - } - if ($bodyStream) { - $response = $response->withBody($bodyStream); - } - } - return $response; - } - - /** - * @param array<\Swow\Http\Message\UploadedFileEntity> $uploadedFileEntities - * @return array - */ - public static function createUploadedFilesFromEntity(array $uploadedFileEntities, ?StreamFactoryInterface $streamFactory = null, ?UploadedFileFactoryInterface $uploadedFileFactory = null): array - { - $streamFactory ??= static::getDefaultStreamFactory(); - $uploadedFileFactory ??= static::getDefaultUploadedFileFactory(); - $uploadedFiles = []; - foreach ($uploadedFileEntities as $formDataName => $uploadedFileEntity) { - $uploadedFileStream = $streamFactory->createStreamFromResource($uploadedFileEntity->tmpFile); - $uploadedFiles[$formDataName] = $uploadedFileFactory->createUploadedFile( - $uploadedFileStream, - $uploadedFileEntity->size, - $uploadedFileEntity->error, - $uploadedFileEntity->name, - $uploadedFileEntity->type, - ); - } - return $uploadedFiles; - } - - /** - * @param array|string> $headers - * @param array $serverParams - * @return ServerRequestInterface|ServerRequestPlusInterface|ServerRequest - */ - public static function createServerRequest( - string $method, - mixed $uri, - array $serverParams, - array $headers = [], - mixed $body = null, - ?ServerRequestFactoryInterface $serverRequestFactory = null - ): ServerRequestInterface { - $serverRequestFactory ??= static::getDefaultServerRequestFactory(); - $serverRequest = $serverRequestFactory->createServerRequest($method, $uri, $serverParams); - if ($headers) { - $serverRequest = static::setHeaders($serverRequest, $headers); - } - if ($body) { - $serverRequest = static::setBody($serverRequest, $body); - } - return $serverRequest; - } - - /** - * @return ServerRequestInterface|ServerRequestPlusInterface|ServerRequest - */ - public static function createServerRequestFromEntity( - ServerRequestEntity $serverRequestEntity, - ?ServerRequestFactoryInterface $serverRequestFactory = null, - ?UriFactoryInterface $uriFactory = null, - ?StreamFactoryInterface $streamFactory = null, - ?UploadedFileFactoryInterface $uploadedFileFactory = null - ): ServerRequestInterface { - $serverRequestFactory ??= static::getDefaultServerRequestFactory(); - $serverRequest = $serverRequestFactory->createServerRequest( - $serverRequestEntity->method, - static::createUriFromString($serverRequestEntity->uri, $uriFactory), - $serverRequestEntity->serverParams - ); - $query = $serverRequest->getUri()->getQuery(); - if ($query) { - parse_str($query, $queryParams); - } else { - $queryParams = []; - } - if ($serverRequestEntity->body) { - $bodyStream = $streamFactory->createStream((string) $serverRequestEntity->body); - } else { - $bodyStream = null; - } - if ($serverRequestEntity->uploadedFiles) { - $uploadedFiles = static::createUploadedFilesFromEntity( - $serverRequestEntity->uploadedFiles, - $streamFactory, $uploadedFileFactory - ); - } else { - $uploadedFiles = null; - } - if ($serverRequest instanceof ServerRequestPlusInterface) { - if ($queryParams) { - $serverRequest->setQueryParams($queryParams); - } - $serverRequest->setHeadersAndHeaderNames( - $serverRequestEntity->headers, - $serverRequestEntity->headerNames - ); - if ($serverRequestEntity->cookies) { - $serverRequest->setCookieParams($serverRequestEntity->cookies); - } - if ($bodyStream) { - $serverRequest->setBody($bodyStream); - } - if ($serverRequestEntity->formData) { - $serverRequest->setParsedBody($serverRequestEntity->formData); - } - if ($uploadedFiles) { - $serverRequest->setUploadedFiles($uploadedFiles); - } - if ($serverRequest instanceof ServerRequest) { - $serverRequest->setShouldKeepAlive($serverRequestEntity->shouldKeepAlive); - if ($serverRequestEntity->isUpgrade) { - $serverRequest->setIsUpgrade(true); - } - } - } else { - if ($queryParams) { - $serverRequest = $serverRequest->withQueryParams($queryParams); - } - foreach ($serverRequestEntity->headers as $headerName => $headerValue) { - $serverRequest = $serverRequest->withHeader($headerName, $headerValue); - } - if ($serverRequestEntity->cookies) { - $serverRequest = $serverRequest->withCookieParams($serverRequestEntity->cookies); - } - if ($bodyStream) { - $serverRequest = $serverRequest->withBody($bodyStream); - } - if ($serverRequestEntity->formData) { - $serverRequest = $serverRequest->withParsedBody($serverRequestEntity->formData); - } - if ($uploadedFiles) { - $serverRequest = $serverRequest->withUploadedFiles($uploadedFiles); - } - } - return $serverRequest; - } - - public static function createWebSocketFrame(int $opcode, mixed $payloadData, bool $fin = true, bool|string $mask = false): WebSocketFrame - { - if ($mask) { - $maskingKey = is_string($mask) ? $mask : WebSocket::DEFAULT_MASKING_KEY; - $payloadData = WebSocket::mask((string) $payloadData, maskingKey: $maskingKey); - } else { - $maskingKey = ''; - } - return new WebSocketFrame(fin: $fin, opcode: $opcode, maskingKey: $maskingKey, payloadData: $payloadData); - } - - public static function createWebSocketTextFrame(mixed $payloadData, bool $fin = true, bool|string $mask = false): WebSocketFrame - { - return static::createWebSocketFrame(opcode: Opcode::TEXT, payloadData: $payloadData, fin: $fin, mask: $mask); - } - - public static function createWebSocketTextMaskedFrame(mixed $payloadData, bool $fin = true): WebSocketFrame - { - return static::createWebSocketFrame(opcode: Opcode::TEXT, payloadData: $payloadData, fin: $fin, mask: true); - } - - public static function createWebSocketBinaryFrame(mixed $payloadData, bool $fin = true, bool|string $mask = false): WebSocketFrame - { - return static::createWebSocketFrame(opcode: Opcode::BINARY, payloadData: $payloadData, fin: $fin, mask: $mask); - } - - public static function createWebSocketBinaryMaskedFrame(mixed $payloadData, bool $fin = true): WebSocketFrame - { - return static::createWebSocketFrame(opcode: Opcode::BINARY, payloadData: $payloadData, fin: $fin, mask: true); - } -} diff --git a/src/Utils/DetectorTrait.php b/src/Utils/DetectorTrait.php deleted file mode 100644 index 187e464..0000000 --- a/src/Utils/DetectorTrait.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Utils; - -use Psr\Http\Message\MessageInterface; -use Swow\Psr7\Message\MessagePlusInterface; -use Swow\Psr7\Message\ServerRequest; -use Swow\Psr7\Message\UpgradeType; - -use function explode; -use function strcasecmp; -use function strlen; - -trait DetectorTrait -{ - public static function detectShouldKeepAlive(MessageInterface $message): bool - { - if ($message instanceof MessagePlusInterface) { - return $message->shouldKeepAlive(); - } - $protocolVersion = $message->getProtocolVersion(); - $parts = explode('.', $protocolVersion, 2); - $majorVersion = (int) $parts[0]; - $minorVersion = (int) $parts[1]; - $connection = $message->getHeaderLine('connection'); - if ($majorVersion > 0 && $minorVersion > 0) { - /* HTTP/1.1+ */ - if (strlen($connection) === strlen('close') && strcasecmp($connection, 'close') === 0) { - return false; - } - } else { - /* HTTP/1.0 or earlier */ - if (strlen($connection) !== strlen('keep-alive') || strcasecmp($connection, 'keep-alive') !== 0) { - return false; - } - } - return true; - } - - public static function detectUpgradeType(MessageInterface $message): int - { - if ($message instanceof ServerRequest && $message->isUpgrade() === false) { - return UpgradeType::UPGRADE_TYPE_NONE; - } - return UpgradeType::fromString($message->getHeaderLine('upgrade')); - } -} diff --git a/src/Utils/FactoryTrait.php b/src/Utils/FactoryTrait.php deleted file mode 100644 index dd8c12f..0000000 --- a/src/Utils/FactoryTrait.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Utils; - -use Psr\Http\Message\RequestFactoryInterface; -use Psr\Http\Message\ResponseFactoryInterface; -use Psr\Http\Message\ServerRequestFactoryInterface; -use Psr\Http\Message\StreamFactoryInterface; -use Psr\Http\Message\UploadedFileFactoryInterface; -use Psr\Http\Message\UriFactoryInterface; -use Swow\Psr7\Message\Psr17Factory; -use Swow\Psr7\Server\ServerConnectionFactoryInterface; - -trait FactoryTrait -{ - protected static Psr17Factory $builtinPsr17Factory; - protected static UriFactoryInterface $uriFactory; - protected static StreamFactoryInterface $streamFactory; - protected static RequestFactoryInterface $requestFactory; - protected static ResponseFactoryInterface $responseFactory; - protected static ServerRequestFactoryInterface $serverRequestFactory; - protected static UploadedFileFactoryInterface $uploadedFileFactory; - protected static ServerConnectionFactoryInterface $serverConnectionFactory; - - public static function getBuiltinPsr17Factory(): Psr17Factory - { - return static::$builtinPsr17Factory ??= new Psr17Factory(); - } - - public static function getDefaultUriFactory(): UriFactoryInterface - { - return static::$uriFactory ??= static::getBuiltinPsr17Factory(); - } - - public static function setDefaultUriFactory(UriFactoryInterface $uriFactory): void - { - static::$uriFactory = $uriFactory; - } - - public static function getDefaultStreamFactory(): StreamFactoryInterface - { - return static::$streamFactory ??= static::getBuiltinPsr17Factory(); - } - - public static function setDefaultStreamFactory(StreamFactoryInterface $streamFactory): void - { - static::$streamFactory = $streamFactory; - } - - public static function getDefaultRequestFactory(): RequestFactoryInterface - { - return static::$requestFactory ??= static::getBuiltinPsr17Factory(); - } - - public static function setDefaultRequestFactory(RequestFactoryInterface $requestFactory): void - { - static::$requestFactory = $requestFactory; - } - - public static function getDefaultResponseFactory(): ResponseFactoryInterface - { - return static::$responseFactory ??= static::getBuiltinPsr17Factory(); - } - - public static function setDefaultResponseFactory(ResponseFactoryInterface $responseFactory): void - { - static::$responseFactory = $responseFactory; - } - - public static function getDefaultServerRequestFactory(): ServerRequestFactoryInterface - { - return static::$serverRequestFactory ??= static::getBuiltinPsr17Factory(); - } - - public static function setDefaultServerRequestFactory(ServerRequestFactoryInterface $serverRequestFactory): void - { - static::$serverRequestFactory = $serverRequestFactory; - } - - public static function getDefaultUploadedFileFactory(): UploadedFileFactoryInterface - { - return static::$uploadedFileFactory ??= static::getBuiltinPsr17Factory(); - } - - public static function setDefaultUploadedFileFactory(UploadedFileFactoryInterface $uploadedFileFactory): void - { - static::$uploadedFileFactory = $uploadedFileFactory; - } - - public static function getDefaultServerConnectionFactory(): ServerConnectionFactoryInterface - { - return static::$serverConnectionFactory ??= static::getBuiltinPsr17Factory(); - } - - public static function setDefaultServerConnectionFactory(ServerConnectionFactoryInterface $serverConnectionFactory): void - { - static::$serverConnectionFactory = $serverConnectionFactory; - } -} diff --git a/src/Utils/OperatorTrait.php b/src/Utils/OperatorTrait.php deleted file mode 100644 index 5254941..0000000 --- a/src/Utils/OperatorTrait.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, - * please view the LICENSE file that was distributed with this source code - */ - -declare(strict_types=1); - -namespace Swow\Psr7\Utils; - -use Psr\Http\Message\MessageInterface; -use Psr\Http\Message\ResponseInterface; -use Swow\Psr7\Message\MessagePlusInterface; -use Swow\Psr7\Message\ResponsePlusInterface; - -trait OperatorTrait -{ - /** - * @template T of MessageInterface - * @param T $message - * @param array|string> $headers - * @return T - */ - public static function setHeaders(MessageInterface $message, array $headers): MessageInterface - { - if ($message instanceof MessagePlusInterface) { - $message->setHeaders($headers); - } else { - $message = static::withHeaders($message, $headers); - } - return $message; - } - - /** - * @template T of MessageInterface - * @param T $message - * @param array|string> $headers - * @return T - */ - public static function withHeaders(MessageInterface $message, array $headers): MessageInterface - { - if ($message instanceof MessagePlusInterface) { - $message = $message->withHeaders($headers); - } else { - foreach ($headers as $headerName => $headerValue) { - $message = $message->withHeader($headerName, $headerValue); - } - } - return $message; - } - - /** - * @template T of MessageInterface - * @param T $message - * @return T - */ - public static function setBody(MessageInterface $message, mixed $body): MessageInterface - { - if ($message instanceof MessagePlusInterface) { - $message->setBody($body); - } else { - $message = $message->withBody(static::createStreamFromAny($body)); - } - return $message; - } - - /** - * @template T of MessageInterface - * @param T $message - * @return T - */ - public static function withBody(MessageInterface $message, mixed $body): MessageInterface - { - return $message->withBody(static::createStreamFromAny($body)); - } - - /** - * @template T of ResponseInterface - * @param T $response - * @return T - */ - public static function setStatus(ResponseInterface $response, int $code, string $reasonPhrase = ''): ResponseInterface - { - if ($response instanceof ResponsePlusInterface) { - $response->setStatus($code, $reasonPhrase); - } else { - $response = $response->withStatus($code, $reasonPhrase); - } - return $response; - } -}