From 1f8fecc2bcbfdaf090c89d7175688b2e6a8d9b7d Mon Sep 17 00:00:00 2001 From: Andrii Dembitskyi Date: Sun, 1 Sep 2024 14:46:23 +0300 Subject: [PATCH] Make package compatible with stream interface Compatibility stream interface v2 (#75) * make compatible with stream interface * :rotating_light: Explicitly specify what features of HTTP client is not supported by current implementation to avoid having failed tests * :package: Explicitly declare compatibility versions for `psr/http-message` There is implementation for interface from this package * :package: `fread` requires to pass only `int<1, max>` - early return empty string in case of `0` length --------- Co-authored-by: David Buchmann --- .github/workflows/ci.yml | 6 +++-- CHANGELOG.md | 5 +++++ README.md | 2 +- composer.json | 18 ++++++++------- phpunit.xml.dist | 1 - src/ResponseReader.php | 6 ----- src/Stream.php | 37 +++++++++++++++---------------- tests/SocketClientFeatureTest.php | 25 +++++++++++++++++++++ tests/SocketHttpClientTest.php | 6 ++--- 9 files changed, 65 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0e4f6a..1231aa2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,9 @@ name: CI on: push: branches: - - 2.x + - '[0-9]+.x' + - '[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.x' pull_request: jobs: @@ -91,7 +93,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.3 tools: composer coverage: xdebug diff --git a/CHANGELOG.md b/CHANGELOG.md index b030fcb..b766856 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 2.3.0 + + * Fixed compatibility with `psr/http-message` v2 + * The `Http\Client\Socket\Stream` has BC breaks if you extended it. It is not meant to be extended, declaring it as `@internal` now. + ## 2.2.0 * Allow installation with Symfony 7 diff --git a/README.md b/README.md index 193ff9b..27be400 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ First launch the http server: $ ./vendor/bin/http_test_server > /dev/null 2>&1 & ``` -Then generate ssh certificates: +Then generate SSL certificates: ```bash $ composer gen-ssl diff --git a/composer.json b/composer.json index 11542e4..0689754 100644 --- a/composer.json +++ b/composer.json @@ -9,18 +9,20 @@ } ], "require": { - "php": "^7.2 || ^8.0", - "nyholm/psr7": "^1.3", - "php-http/httplug": "^2.0", + "php": "^8.1", + "nyholm/psr7": "^1.8.1", + "php-http/httplug": "^2.4", "psr/http-client": "^1.0", + "psr/http-message": "^1.0 || ^2.0", "symfony/options-resolver": "^2.6 || ^3.4 || ^4.4 || ^5.0 || ^6.0 || ^7.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.2 || ^3.0", - "php-http/client-integration-tests": "^3.0", - "php-http/message": "^1.9", - "php-http/client-common": "^2.3", - "phpunit/phpunit": "^8.5.23 || ~9.5" + "friendsofphp/php-cs-fixer": "^3.51", + "php-http/client-integration-tests": "^3.1.1", + "php-http/message": "^1.16", + "php-http/client-common": "^2.7", + "phpunit/phpunit": "^8.5.23 || ~9.5", + "php-http/message-factory": "^1.1" }, "provide": { "php-http/client-implementation": "1.0", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 034d22e..f12146d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,7 +8,6 @@ tests/ - tests/SocketClientFeatureTest.php diff --git a/src/ResponseReader.php b/src/ResponseReader.php index 66431b0..d5beae6 100644 --- a/src/ResponseReader.php +++ b/src/ResponseReader.php @@ -4,7 +4,6 @@ use Http\Client\Socket\Exception\BrokenPipeException; use Http\Client\Socket\Exception\TimeoutException; -use Http\Message\ResponseFactory; use Nyholm\Psr7\Response; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -18,11 +17,6 @@ */ trait ResponseReader { - /** - * @var ResponseFactory For creating response - */ - protected $responseFactory; - /** * Read a response from a socket. * diff --git a/src/Stream.php b/src/Stream.php index 8d26ca0..afe6dd6 100644 --- a/src/Stream.php +++ b/src/Stream.php @@ -61,7 +61,7 @@ public function __construct(RequestInterface $request, $socket, ?int $size = nul $this->request = $request; } - public function __toString() + public function __toString(): string { try { return $this->getContents(); @@ -70,7 +70,7 @@ public function __toString() } } - public function close() + public function close(): void { if ($this->isDetached || null === $this->socket) { throw new StreamException('Stream is detached'); @@ -93,12 +93,12 @@ public function detach() /** * @return int<0, max>|null */ - public function getSize() + public function getSize(): ?int { return $this->size; } - public function tell() + public function tell(): int { if ($this->isDetached || null === $this->socket) { throw new StreamException('Stream is detached'); @@ -111,7 +111,7 @@ public function tell() return $tell; } - public function eof() + public function eof(): bool { if ($this->isDetached || null === $this->socket) { throw new StreamException('Stream is detached'); @@ -120,38 +120,32 @@ public function eof() return feof($this->socket); } - public function isSeekable() + public function isSeekable(): bool { return false; } - /** - * @return void - */ - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { throw new StreamException('This stream is not seekable'); } - /** - * @return void - */ - public function rewind() + public function rewind(): void { throw new StreamException('This stream is not seekable'); } - public function isWritable() + public function isWritable(): bool { return false; } - public function write($string) + public function write($string): int { throw new StreamException('This stream is not writable'); } - public function isReadable() + public function isReadable(): bool { return true; } @@ -159,11 +153,16 @@ public function isReadable() /** * @param int<0, max> $length */ - public function read($length) + public function read($length): string { + if (0 === $length) { + return ''; + } + if ($this->isDetached || null === $this->socket) { throw new StreamException('Stream is detached'); } + if (null === $this->getSize()) { $read = fread($this->socket, $length); if (false === $read) { @@ -197,7 +196,7 @@ public function read($length) return $read; } - public function getContents() + public function getContents(): string { if ($this->isDetached || null === $this->socket) { throw new StreamException('Stream is detached'); diff --git a/tests/SocketClientFeatureTest.php b/tests/SocketClientFeatureTest.php index e6e698b..f1fe854 100644 --- a/tests/SocketClientFeatureTest.php +++ b/tests/SocketClientFeatureTest.php @@ -12,4 +12,29 @@ protected function createClient(): ClientInterface { return new SocketHttpClient(); } + + public function testAutoSetContentLength(): void + { + $this->markTestSkipped('Feature is unsupported'); + } + + public function testGzip(): void + { + $this->markTestSkipped('Feature is unsupported'); + } + + public function testDeflate(): void + { + $this->markTestSkipped('Feature is unsupported'); + } + + public function testChunked(): void + { + $this->markTestSkipped('Feature is unsupported'); + } + + public function testRedirect(): void + { + $this->markTestSkipped('Feature is unsupported'); + } } diff --git a/tests/SocketHttpClientTest.php b/tests/SocketHttpClientTest.php index c3e5da2..657f2ff 100644 --- a/tests/SocketHttpClientTest.php +++ b/tests/SocketHttpClientTest.php @@ -6,15 +6,13 @@ use Http\Client\Socket\Client as SocketHttpClient; use Http\Client\Socket\Exception\NetworkException; use Http\Client\Socket\Exception\TimeoutException; -use Http\Message\MessageFactory\GuzzleMessageFactory; +use Nyholm\Psr7\Factory\Psr17Factory; class SocketHttpClientTest extends BaseTestCase { public function createClient($options = []) { - $messageFactory = new GuzzleMessageFactory(); - - return new HttpMethodsClient(new SocketHttpClient($options), $messageFactory); + return new HttpMethodsClient(new SocketHttpClient($options), new Psr17Factory()); } public function testTcpSocketDomain()