From 3c581f98c1a8dd26fd931a797eee149360bbf1f1 Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Thu, 20 Feb 2025 22:43:19 +0100 Subject: [PATCH 1/2] Update CI scripts & composer.json to PHP 8.4. --- .github/workflows/ci.yml | 7 +++++-- composer.json | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9eddc527..0dbd0cd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,12 +18,15 @@ jobs: - operating-system: 'ubuntu-latest' php-version: '8.3' + - operating-system: 'ubuntu-latest' + php-version: '8.4' + - operating-system: 'windows-latest' - php-version: '8.3' + php-version: '8.4' job-description: 'on Windows' - operating-system: 'macos-latest' - php-version: '8.3' + php-version: '8.4' job-description: 'on macOS' name: PHP ${{ matrix.php-version }} ${{ matrix.job-description }} diff --git a/composer.json b/composer.json index 0780e843..f60cf516 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,7 @@ "amphp/http-server": "^3", "kelunik/link-header-rfc5988": "^1", "psalm/phar": "~5.23", - "laminas/laminas-diactoros": "^2.3" + "laminas/laminas-diactoros": "^3.5.0" }, "suggest": { "ext-zlib": "Allows using compression for response bodies.", From cd9910945ce5e1f8648b56f86df274443c9db872 Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Fri, 21 Feb 2025 00:16:28 +0100 Subject: [PATCH 2/2] Update PSALM config Fix psalm config PSAML has problems with goto analyze. It leads to wrong issues: https://github.com/vimeo/psalm/issues/11327 --- composer.json | 2 +- examples/pagination/1-iterator.php | 2 +- examples/pagination/2-iterator-batch.php | 4 +-- examples/streaming/1-large-response.php | 1 + examples/streaming/2-http1-http2.php | 1 + .../streaming/3-large-response-slow-read.php | 1 + psalm.xml | 29 +++++++++++++++---- src/Connection/Internal/Http1Parser.php | 2 ++ .../Internal/Http2ConnectionProcessor.php | 1 + src/EventListener/LogHttpArchive.php | 2 +- src/Interceptor/FollowRedirects.php | 2 ++ src/Interceptor/RetryRequests.php | 3 ++ src/Interceptor/TooManyRedirectsException.php | 3 ++ 13 files changed, 42 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index f60cf516..84b951d5 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ "phpunit/phpunit": "^9", "amphp/http-server": "^3", "kelunik/link-header-rfc5988": "^1", - "psalm/phar": "~5.23", + "psalm/phar": "*", "laminas/laminas-diactoros": "^3.5.0" }, "suggest": { diff --git a/examples/pagination/1-iterator.php b/examples/pagination/1-iterator.php index 0e013d95..57528459 100644 --- a/examples/pagination/1-iterator.php +++ b/examples/pagination/1-iterator.php @@ -8,7 +8,7 @@ require __DIR__ . '/../.helper/functions.php'; -class GitHubApi +final class GitHubApi { private HttpClient $httpClient; diff --git a/examples/pagination/2-iterator-batch.php b/examples/pagination/2-iterator-batch.php index b4dc23db..e4d3b217 100644 --- a/examples/pagination/2-iterator-batch.php +++ b/examples/pagination/2-iterator-batch.php @@ -10,7 +10,7 @@ require __DIR__ . '/../.helper/functions.php'; -class GitHubApi +final class GitHubApi { private HttpClient $httpClient; @@ -36,7 +36,7 @@ public function getEvents(string $organization): iterable $events = json_decode($json); yield $events; - $links = parseLinks($response->getHeader('link')); + $links = parseLinks($response->getHeader('link') ?? ''); $next = $links->getByRel('next'); if ($next) { diff --git a/examples/streaming/1-large-response.php b/examples/streaming/1-large-response.php index d1b8d1a4..b3fab805 100644 --- a/examples/streaming/1-large-response.php +++ b/examples/streaming/1-large-response.php @@ -47,6 +47,7 @@ function formatBytes(int $size, int $precision = 2): string print "\n"; $path = tempnam(sys_get_temp_dir(), "artax-streaming-"); + assert($path !== false); $file = Amp\File\openFile($path, "w"); diff --git a/examples/streaming/2-http1-http2.php b/examples/streaming/2-http1-http2.php index eba32390..0d116563 100644 --- a/examples/streaming/2-http1-http2.php +++ b/examples/streaming/2-http1-http2.php @@ -34,6 +34,7 @@ function fetch(string $uri, array $protocolVersions): void print "\n"; $path = tempnam(sys_get_temp_dir(), "artax-streaming-"); + assert($path !== false); $file = Amp\File\openFile($path, "w"); diff --git a/examples/streaming/3-large-response-slow-read.php b/examples/streaming/3-large-response-slow-read.php index b7535b33..5fee42a6 100644 --- a/examples/streaming/3-large-response-slow-read.php +++ b/examples/streaming/3-large-response-slow-read.php @@ -48,6 +48,7 @@ function formatBytes(int $size, int $precision = 2): string print "\n"; $path = tempnam(sys_get_temp_dir(), "artax-streaming-"); + assert($path !== false); $file = Amp\File\openFile($path, "w"); diff --git a/psalm.xml b/psalm.xml index a929dff5..4b0cea43 100644 --- a/psalm.xml +++ b/psalm.xml @@ -4,9 +4,12 @@ phpVersion="8.1" resolveFromConfigFile="true" rememberPropertyAssignmentsAfterCall="false" + ensureOverrideAttribute="false" + findUnusedCode="false" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" + xmlns:xi="http://www.w3.org/2001/XInclude" > @@ -24,6 +27,20 @@ + + + + + + + + + + + + + + @@ -42,12 +59,6 @@ - - - - - - @@ -59,5 +70,11 @@ + + + + + + diff --git a/src/Connection/Internal/Http1Parser.php b/src/Connection/Internal/Http1Parser.php index 7b8914b3..38ffec4d 100644 --- a/src/Connection/Internal/Http1Parser.php +++ b/src/Connection/Internal/Http1Parser.php @@ -322,6 +322,8 @@ private function parseRawHeaders(string $rawHeaders): array $rawHeaders = \preg_replace("/\r\n[\x20\t]++/", ' ', $rawHeaders); } + \assert($rawHeaders !== null); + try { $headers = Rfc7230::parseHeaderPairs($rawHeaders); $headerMap = mapHeaderPairs($headers); diff --git a/src/Connection/Internal/Http2ConnectionProcessor.php b/src/Connection/Internal/Http2ConnectionProcessor.php index 762937fd..ab2c7a88 100644 --- a/src/Connection/Internal/Http2ConnectionProcessor.php +++ b/src/Connection/Internal/Http2ConnectionProcessor.php @@ -1013,6 +1013,7 @@ public function request(Request $request, Cancellation $cancellation, Stream $st $this->writeFrame(Http2Parser::CONTINUATION, Http2Parser::NO_FLAG, $streamId, $headerChunk)->ignore(); } + \assert($lastChunk !== null); $this->writeFrame(Http2Parser::CONTINUATION, $flag, $streamId, $lastChunk)->await(); } else { $this->writeFrame(Http2Parser::HEADERS, $flag, $streamId, $headers)->await(); diff --git a/src/EventListener/LogHttpArchive.php b/src/EventListener/LogHttpArchive.php index bcaba90e..1b126fd0 100644 --- a/src/EventListener/LogHttpArchive.php +++ b/src/EventListener/LogHttpArchive.php @@ -229,7 +229,7 @@ private function writeLog(Response $response): void $fileHandle->seek(-3, Whence::Current); } - $json = \json_encode(self::formatEntry($response)); + $json = \json_encode(self::formatEntry($response), flags: JSON_THROW_ON_ERROR); $fileHandle->write(($firstEntry ? '' : ',') . $json . ']}}'); diff --git a/src/Interceptor/FollowRedirects.php b/src/Interceptor/FollowRedirects.php index e2555e1c..3ffed842 100644 --- a/src/Interceptor/FollowRedirects.php +++ b/src/Interceptor/FollowRedirects.php @@ -66,6 +66,7 @@ private static function removeDotSegments(string $input): string $patternE = ',(/*[^/]*),'; while ($input !== '') { + \assert($input !== null); if (\preg_match($patternA, $input)) { $input = \preg_replace($patternA, '', $input); } elseif (\preg_match($patternB1, $input, $match) || \preg_match($patternB2, $input, $match)) { @@ -80,6 +81,7 @@ private static function removeDotSegments(string $input): string $input = \preg_replace(',^' . \preg_quote($initialSegment, ',') . ',', '', $input, 1); $output .= $initialSegment; } + \assert($output !== null); } return $output; diff --git a/src/Interceptor/RetryRequests.php b/src/Interceptor/RetryRequests.php index 6a616dc1..0cf0f388 100644 --- a/src/Interceptor/RetryRequests.php +++ b/src/Interceptor/RetryRequests.php @@ -26,6 +26,7 @@ public function request( DelegateHttpClient $httpClient ): Response { $attempt = 1; + $exception = null; do { $clonedRequest = clone $request; @@ -43,6 +44,8 @@ public function request( } } while ($attempt++ <= $this->retryLimit); + \assert($exception !== null); + throw $exception; } } diff --git a/src/Interceptor/TooManyRedirectsException.php b/src/Interceptor/TooManyRedirectsException.php index 49f543ab..9fd4c6ac 100755 --- a/src/Interceptor/TooManyRedirectsException.php +++ b/src/Interceptor/TooManyRedirectsException.php @@ -5,6 +5,9 @@ use Amp\Http\Client\HttpException; use Amp\Http\Client\Response; +/** + * @api + */ class TooManyRedirectsException extends HttpException { private Response $response;