From 8133e71760f1244869c1f490dbddb684034676b0 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 9 Apr 2026 09:53:41 +0200 Subject: [PATCH 1/9] bisect: advertise gzip,deflate encoding when supported --- src/Command/BisectCommand.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Command/BisectCommand.php b/src/Command/BisectCommand.php index 8cb0c0382d..5e105195cd 100644 --- a/src/Command/BisectCommand.php +++ b/src/Command/BisectCommand.php @@ -106,19 +106,25 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } + $headers = [ + 'Authorization' => 'token ' . $token, + 'Accept' => 'application/vnd.github.v3+json', + ]; + if (extension_loaded('zlib')) { + $headers['Accept-Encoding'] = 'gzip,deflate'; + } + $client = new Client([ RequestOptions::TIMEOUT => 30, RequestOptions::CONNECT_TIMEOUT => 10, - 'headers' => [ - 'Authorization' => 'token ' . $token, - 'Accept' => 'application/vnd.github.v3+json', - ], + 'headers' => $headers ]); $io->section(sprintf('Fetching commits between %s and %s...', $good, $bad)); try { $commits = $this->getCommitsBetween($client, $good, $bad); + exit(); } catch (GuzzleException $e) { $io->error(sprintf('Failed to fetch commits from GitHub: %s', $e->getMessage())); return 1; From ff7fe8de581721f134918a960f37a9b6374913bf Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 9 Apr 2026 09:58:16 +0200 Subject: [PATCH 2/9] Update BisectCommand.php --- src/Command/BisectCommand.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Command/BisectCommand.php b/src/Command/BisectCommand.php index 5e105195cd..bcb3e338f0 100644 --- a/src/Command/BisectCommand.php +++ b/src/Command/BisectCommand.php @@ -124,7 +124,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { $commits = $this->getCommitsBetween($client, $good, $bad); - exit(); } catch (GuzzleException $e) { $io->error(sprintf('Failed to fetch commits from GitHub: %s', $e->getMessage())); return 1; From 810a43b42f06ce36c5e3ea9ed873f34141929c14 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 9 Apr 2026 10:03:52 +0200 Subject: [PATCH 3/9] cs --- src/Command/BisectCommand.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Command/BisectCommand.php b/src/Command/BisectCommand.php index bcb3e338f0..e3d4333b62 100644 --- a/src/Command/BisectCommand.php +++ b/src/Command/BisectCommand.php @@ -23,6 +23,7 @@ use function chmod; use function count; use function escapeshellarg; +use function extension_loaded; use function getenv; use function implode; use function is_array; @@ -106,7 +107,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $headers = [ + $headers = [ 'Authorization' => 'token ' . $token, 'Accept' => 'application/vnd.github.v3+json', ]; @@ -117,7 +118,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $client = new Client([ RequestOptions::TIMEOUT => 30, RequestOptions::CONNECT_TIMEOUT => 10, - 'headers' => $headers + 'headers' => $headers, ]); $io->section(sprintf('Fetching commits between %s and %s...', $good, $bad)); From 60457f00ab3df5886daa4e0440399b0b62101ddc Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 9 Apr 2026 10:26:15 +0200 Subject: [PATCH 4/9] HttpClientFactory --- src/Command/BisectCommand.php | 18 +++++++----------- src/Internal/HttpClientFactory.php | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 src/Internal/HttpClientFactory.php diff --git a/src/Command/BisectCommand.php b/src/Command/BisectCommand.php index e3d4333b62..5c1aed108b 100644 --- a/src/Command/BisectCommand.php +++ b/src/Command/BisectCommand.php @@ -9,6 +9,7 @@ use Override; use PHPStan\Command\Bisect\BinarySearch; use PHPStan\File\FileReader; +use PHPStan\Internal\HttpClientFactory; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; @@ -23,7 +24,6 @@ use function chmod; use function count; use function escapeshellarg; -use function extension_loaded; use function getenv; use function implode; use function is_array; @@ -107,24 +107,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $headers = [ - 'Authorization' => 'token ' . $token, - 'Accept' => 'application/vnd.github.v3+json', - ]; - if (extension_loaded('zlib')) { - $headers['Accept-Encoding'] = 'gzip,deflate'; - } - - $client = new Client([ + $client = HttpClientFactory::createClient([ RequestOptions::TIMEOUT => 30, RequestOptions::CONNECT_TIMEOUT => 10, - 'headers' => $headers, + 'headers' => [ + 'Authorization' => 'token ' . $token, + 'Accept' => 'application/vnd.github.v3+json', + ], ]); $io->section(sprintf('Fetching commits between %s and %s...', $good, $bad)); try { $commits = $this->getCommitsBetween($client, $good, $bad); + exit; } catch (GuzzleException $e) { $io->error(sprintf('Failed to fetch commits from GitHub: %s', $e->getMessage())); return 1; diff --git a/src/Internal/HttpClientFactory.php b/src/Internal/HttpClientFactory.php new file mode 100644 index 0000000000..6109d36908 --- /dev/null +++ b/src/Internal/HttpClientFactory.php @@ -0,0 +1,26 @@ + Date: Thu, 9 Apr 2026 10:27:15 +0200 Subject: [PATCH 5/9] Update FixerApplication.php --- src/Command/FixerApplication.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Command/FixerApplication.php b/src/Command/FixerApplication.php index 8d6432258c..ef326ddb7b 100644 --- a/src/Command/FixerApplication.php +++ b/src/Command/FixerApplication.php @@ -23,6 +23,7 @@ use PHPStan\Internal\ComposerHelper; use PHPStan\Internal\DirectoryCreator; use PHPStan\Internal\DirectoryCreatorException; +use PHPStan\Internal\HttpClientFactory; use PHPStan\PhpDoc\StubFilesProvider; use PHPStan\Process\ProcessCanceledException; use PHPStan\Process\ProcessCrashedException; @@ -325,7 +326,7 @@ private function downloadPhar( $output->writeln('Checking if there\'s a new PHPStan Pro release...'); } - $client = new Client([ + $client = HttpClientFactory::createClient([ RequestOptions::TIMEOUT => 30, RequestOptions::CONNECT_TIMEOUT => 5, ]); From 97e5b101ba279ecac957f91e4cdf37b799b24045 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 9 Apr 2026 10:28:24 +0200 Subject: [PATCH 6/9] fix --- src/Command/BisectCommand.php | 1 - src/Internal/HttpClientFactory.php | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Command/BisectCommand.php b/src/Command/BisectCommand.php index 5c1aed108b..6e49099a76 100644 --- a/src/Command/BisectCommand.php +++ b/src/Command/BisectCommand.php @@ -120,7 +120,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { $commits = $this->getCommitsBetween($client, $good, $bad); - exit; } catch (GuzzleException $e) { $io->error(sprintf('Failed to fetch commits from GitHub: %s', $e->getMessage())); return 1; diff --git a/src/Internal/HttpClientFactory.php b/src/Internal/HttpClientFactory.php index 6109d36908..cf548fb7fe 100644 --- a/src/Internal/HttpClientFactory.php +++ b/src/Internal/HttpClientFactory.php @@ -9,6 +9,8 @@ final class HttpClientFactory { /** + * @param array $config + * * @see \GuzzleHttp\RequestOptions */ public static function createClient(array $config): Client From dcc038f15d35e979ad5f6e87a007b75db422bbad Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 9 Apr 2026 10:39:05 +0200 Subject: [PATCH 7/9] Update FixerApplication.php --- src/Command/FixerApplication.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Command/FixerApplication.php b/src/Command/FixerApplication.php index ef326ddb7b..e08d752623 100644 --- a/src/Command/FixerApplication.php +++ b/src/Command/FixerApplication.php @@ -7,7 +7,6 @@ use DateTime; use DateTimeImmutable; use DateTimeZone; -use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\RequestOptions; use Nette\Utils\Json; From 049c03ca23a437f3a6b24a00d0942e61e58b5f0c Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 10 Apr 2026 07:29:51 +0200 Subject: [PATCH 8/9] made HttpClientFactory a service --- src/Command/BisectCommand.php | 2 +- src/Command/FixerApplication.php | 3 ++- src/Internal/HttpClientFactory.php | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Command/BisectCommand.php b/src/Command/BisectCommand.php index 6e49099a76..f9c86074c0 100644 --- a/src/Command/BisectCommand.php +++ b/src/Command/BisectCommand.php @@ -107,7 +107,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $client = HttpClientFactory::createClient([ + $client = (new HttpClientFactory())->createClient([ RequestOptions::TIMEOUT => 30, RequestOptions::CONNECT_TIMEOUT => 10, 'headers' => [ diff --git a/src/Command/FixerApplication.php b/src/Command/FixerApplication.php index e08d752623..81785b0304 100644 --- a/src/Command/FixerApplication.php +++ b/src/Command/FixerApplication.php @@ -93,6 +93,7 @@ public function __construct( private ?string $editorUrl, #[AutowiredParameter] private string $usedLevel, + private HttpClientFactory $httpClientFactory, ) { } @@ -325,7 +326,7 @@ private function downloadPhar( $output->writeln('Checking if there\'s a new PHPStan Pro release...'); } - $client = HttpClientFactory::createClient([ + $client = $this->httpClientFactory->createClient([ RequestOptions::TIMEOUT => 30, RequestOptions::CONNECT_TIMEOUT => 5, ]); diff --git a/src/Internal/HttpClientFactory.php b/src/Internal/HttpClientFactory.php index cf548fb7fe..07b7ac8a86 100644 --- a/src/Internal/HttpClientFactory.php +++ b/src/Internal/HttpClientFactory.php @@ -3,17 +3,28 @@ namespace PHPStan\Internal; use GuzzleHttp\Client; +use PHPStan\DependencyInjection\AutowiredService; use function extension_loaded; +#[AutowiredService] final class HttpClientFactory { + /** + * @param array $defaults + * + * @see \GuzzleHttp\RequestOptions + */ + public function __construct(private readonly array $defaults = []) + { + } + /** * @param array $config * * @see \GuzzleHttp\RequestOptions */ - public static function createClient(array $config): Client + public function createClient(array $config): Client { if ( !isset($config['headers']['Accept-Encoding']) @@ -22,7 +33,7 @@ public static function createClient(array $config): Client $config['headers']['Accept-Encoding'] = 'gzip,deflate'; } - return new Client($config); + return new Client($config + $this->defaults); } } From 4b03db7b7c9b58dd738e626a970f1f06269fe552 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 10 Apr 2026 07:39:28 +0200 Subject: [PATCH 9/9] centralize timeout --- src/Command/BisectCommand.php | 2 -- src/Command/FixerApplication.php | 5 +---- src/Internal/HttpClientFactory.php | 18 +++++++++++------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Command/BisectCommand.php b/src/Command/BisectCommand.php index f9c86074c0..9c1e3932d0 100644 --- a/src/Command/BisectCommand.php +++ b/src/Command/BisectCommand.php @@ -108,8 +108,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $client = (new HttpClientFactory())->createClient([ - RequestOptions::TIMEOUT => 30, - RequestOptions::CONNECT_TIMEOUT => 10, 'headers' => [ 'Authorization' => 'token ' . $token, 'Accept' => 'application/vnd.github.v3+json', diff --git a/src/Command/FixerApplication.php b/src/Command/FixerApplication.php index 81785b0304..61f89f155b 100644 --- a/src/Command/FixerApplication.php +++ b/src/Command/FixerApplication.php @@ -326,10 +326,7 @@ private function downloadPhar( $output->writeln('Checking if there\'s a new PHPStan Pro release...'); } - $client = $this->httpClientFactory->createClient([ - RequestOptions::TIMEOUT => 30, - RequestOptions::CONNECT_TIMEOUT => 5, - ]); + $client = $this->httpClientFactory->createClient([]); $latestUrl = sprintf('https://fixer-download-api.phpstan.com/latest?%s', http_build_query(['phpVersion' => PHP_VERSION_ID, 'branch' => $branch])); diff --git a/src/Internal/HttpClientFactory.php b/src/Internal/HttpClientFactory.php index 07b7ac8a86..335b45b950 100644 --- a/src/Internal/HttpClientFactory.php +++ b/src/Internal/HttpClientFactory.php @@ -3,6 +3,7 @@ namespace PHPStan\Internal; use GuzzleHttp\Client; +use GuzzleHttp\RequestOptions; use PHPStan\DependencyInjection\AutowiredService; use function extension_loaded; @@ -10,12 +11,10 @@ final class HttpClientFactory { - /** - * @param array $defaults - * - * @see \GuzzleHttp\RequestOptions - */ - public function __construct(private readonly array $defaults = []) + public function __construct( + private int $timeout = 30, + private int $connectTimeout = 10, + ) { } @@ -33,7 +32,12 @@ public function createClient(array $config): Client $config['headers']['Accept-Encoding'] = 'gzip,deflate'; } - return new Client($config + $this->defaults); + $defaults = [ + RequestOptions::TIMEOUT => $this->timeout, + RequestOptions::CONNECT_TIMEOUT => $this->connectTimeout, + ]; + + return new Client($config + $defaults); } }