diff --git a/composer.json b/composer.json index 448a765f2..377bdd703 100644 --- a/composer.json +++ b/composer.json @@ -23,12 +23,11 @@ "php": "^7.2|^8.0", "ext-json": "*", "ext-mbstring": "*", + "friendsofphp/well-known-implementations": "^1", "guzzlehttp/promises": "^1.4", - "guzzlehttp/psr7": "^1.8.4|^2.1.1", "jean85/pretty-package-versions": "^1.5|^2.0.4", "php-http/async-client-implementation": "^1.0", "php-http/client-common": "^1.5|^2.0", - "php-http/discovery": "^1.11", "php-http/httplug": "^1.1|^2.0", "php-http/message": "^1.5", "psr/http-factory": "^1.0", @@ -39,6 +38,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.19|3.4.*", + "guzzlehttp/psr7": "^1.8.4|^2.1.1", "http-interop/http-factory-guzzle": "^1.0", "monolog/monolog": "^1.6|^2.0|^3.0", "nikic/php-parser": "^4.10.3", @@ -89,6 +89,7 @@ "sort-packages": true, "allow-plugins": { "composer/package-versions-deprecated": true, + "friendsofphp/well-known-implementations": false, "phpstan/extension-installer": true } }, diff --git a/src/ClientBuilder.php b/src/ClientBuilder.php index 39d1e6cc3..31607e15d 100644 --- a/src/ClientBuilder.php +++ b/src/ClientBuilder.php @@ -4,7 +4,7 @@ namespace Sentry; -use Http\Discovery\Psr17FactoryDiscovery; +use FriendsOfPHP\WellKnownImplementations\WellKnownPsr17Factory; use Psr\Log\LoggerInterface; use Sentry\HttpClient\HttpClientFactory; use Sentry\Serializer\RepresentationSerializerInterface; @@ -175,19 +175,19 @@ private function createTransportInstance(): TransportInterface */ private function createDefaultTransportFactory(): DefaultTransportFactory { - $streamFactory = Psr17FactoryDiscovery::findStreamFactory(); + $psr17Factory = new WellKnownPsr17Factory(); $httpClientFactory = new HttpClientFactory( - Psr17FactoryDiscovery::findUriFactory(), - Psr17FactoryDiscovery::findResponseFactory(), - $streamFactory, + null, + null, + $psr17Factory, null, $this->sdkIdentifier, $this->sdkVersion ); return new DefaultTransportFactory( - $streamFactory, - Psr17FactoryDiscovery::findRequestFactory(), + $psr17Factory, + $psr17Factory, $httpClientFactory, $this->logger ); diff --git a/src/HttpClient/HttpClientFactory.php b/src/HttpClient/HttpClientFactory.php index d18f72d3e..6bc80996e 100644 --- a/src/HttpClient/HttpClientFactory.php +++ b/src/HttpClient/HttpClientFactory.php @@ -4,6 +4,8 @@ namespace Sentry\HttpClient; +use FriendsOfPHP\WellKnownImplementations\ConcreteImplementation; +use FriendsOfPHP\WellKnownImplementations\WellKnownHttplugClient; use GuzzleHttp\RequestOptions as GuzzleHttpClientOptions; use Http\Adapter\Guzzle6\Client as GuzzleHttpClient; use Http\Client\Common\Plugin\AuthenticationPlugin; @@ -14,7 +16,6 @@ use Http\Client\Common\PluginClient; use Http\Client\Curl\Client as CurlHttpClient; use Http\Client\HttpAsyncClient as HttpAsyncClientInterface; -use Http\Discovery\HttpAsyncClientDiscovery; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\StreamFactoryInterface; @@ -54,16 +55,16 @@ final class HttpClientFactory implements HttpClientFactoryInterface /** * Constructor. * - * @param UriFactoryInterface $uriFactory The PSR-7 URI factory - * @param ResponseFactoryInterface $responseFactory The PSR-7 response factory + * @param UriFactoryInterface|null $uriFactory The PSR-7 URI factory + * @param ResponseFactoryInterface|null $responseFactory The PSR-7 response factory * @param StreamFactoryInterface $streamFactory The PSR-17 stream factory * @param HttpAsyncClientInterface|null $httpClient The HTTP client * @param string $sdkIdentifier The SDK identifier * @param string $sdkVersion The SDK version */ public function __construct( - UriFactoryInterface $uriFactory, - ResponseFactoryInterface $responseFactory, + ?UriFactoryInterface $uriFactory, + ?ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, ?HttpAsyncClientInterface $httpClient, string $sdkIdentifier, @@ -110,7 +111,7 @@ public function create(Options $options): HttpAsyncClientInterface */ private function resolveClient(Options $options) { - if (class_exists(SymfonyHttplugClient::class)) { + if (ConcreteImplementation::VENDOR_SYMFONY === ConcreteImplementation::HTTPLUG_VENDOR) { $symfonyConfig = [ 'timeout' => $options->getHttpConnectTimeout(), 'max_duration' => $options->getHttpTimeout(), @@ -123,7 +124,7 @@ private function resolveClient(Options $options) return new SymfonyHttplugClient(SymfonyHttpClient::create($symfonyConfig)); } - if (class_exists(GuzzleHttpClient::class)) { + if (ConcreteImplementation::VENDOR_HTTPLUG_GUZZLE6 === ConcreteImplementation::HTTPLUG_VENDOR) { $guzzleConfig = [ GuzzleHttpClientOptions::TIMEOUT => $options->getHttpTimeout(), GuzzleHttpClientOptions::CONNECT_TIMEOUT => $options->getHttpConnectTimeout(), @@ -136,7 +137,7 @@ private function resolveClient(Options $options) return GuzzleHttpClient::createWithConfig($guzzleConfig); } - if (class_exists(CurlHttpClient::class)) { + if (ConcreteImplementation::VENDOR_HTTPLUG_CURL === ConcreteImplementation::HTTPLUG_VENDOR) { $curlConfig = [ \CURLOPT_TIMEOUT => $options->getHttpTimeout(), \CURLOPT_CONNECTTIMEOUT => $options->getHttpConnectTimeout(), @@ -153,6 +154,6 @@ private function resolveClient(Options $options) throw new \RuntimeException('The "http_proxy" option requires either the "php-http/curl-client", the "symfony/http-client" or the "php-http/guzzle6-adapter" package to be installed.'); } - return HttpAsyncClientDiscovery::find(); + return new WellKnownHttplugClient(); } } diff --git a/src/Integration/RequestFetcher.php b/src/Integration/RequestFetcher.php index 333205b5f..4b0e1779f 100644 --- a/src/Integration/RequestFetcher.php +++ b/src/Integration/RequestFetcher.php @@ -4,7 +4,7 @@ namespace Sentry\Integration; -use GuzzleHttp\Psr7\ServerRequest; +use FriendsOfPHP\WellKnownImplementations\WellKnownPsr17Factory; use Psr\Http\Message\ServerRequestInterface; /** @@ -22,6 +22,6 @@ public function fetchRequest(): ?ServerRequestInterface return null; } - return ServerRequest::fromGlobals(); + return (new WellKnownPsr17Factory())->createServerRequestFromGlobals(); } } diff --git a/tests/HttpClient/HttpClientFactoryTest.php b/tests/HttpClient/HttpClientFactoryTest.php index 852dc430d..b20247a15 100644 --- a/tests/HttpClient/HttpClientFactoryTest.php +++ b/tests/HttpClient/HttpClientFactoryTest.php @@ -4,8 +4,8 @@ namespace Sentry\Tests\HttpClient; +use FriendsOfPHP\WellKnownImplementations\WellKnownPsr17Factory; use Http\Client\HttpAsyncClient as HttpAsyncClientInterface; -use Http\Discovery\Psr17FactoryDiscovery; use Http\Mock\Client as HttpMockClient; use PHPUnit\Framework\TestCase; use Sentry\HttpClient\HttpClientFactory; @@ -19,13 +19,13 @@ final class HttpClientFactoryTest extends TestCase */ public function testCreate(bool $isCompressionEnabled, string $expectedRequestBody): void { - $streamFactory = Psr17FactoryDiscovery::findStreamFactory(); + $psr17Factory = new WellKnownPsr17Factory(); $mockHttpClient = new HttpMockClient(); $httpClientFactory = new HttpClientFactory( - Psr17FactoryDiscovery::findUrlFactory(), - Psr17FactoryDiscovery::findResponseFactory(), - $streamFactory, + null, + null, + $psr17Factory, $mockHttpClient, 'sentry.php.test', '1.2.3' @@ -37,9 +37,9 @@ public function testCreate(bool $isCompressionEnabled, string $expectedRequestBo 'enable_compression' => $isCompressionEnabled, ])); - $request = Psr17FactoryDiscovery::findRequestFactory() + $request = $psr17Factory ->createRequest('POST', 'http://example.com/sentry/foo') - ->withBody($streamFactory->createStream('foo bar')); + ->withBody($psr17Factory->createStream('foo bar')); $httpClient->sendAsyncRequest($request); @@ -67,9 +67,9 @@ public function createDataProvider(): \Generator public function testCreateThrowsIfDsnOptionIsNotConfigured(): void { $httpClientFactory = new HttpClientFactory( - Psr17FactoryDiscovery::findUrlFactory(), - Psr17FactoryDiscovery::findResponseFactory(), - Psr17FactoryDiscovery::findStreamFactory(), + null, + null, + new WellKnownPsr17Factory(), null, 'sentry.php.test', '1.2.3' @@ -84,9 +84,9 @@ public function testCreateThrowsIfDsnOptionIsNotConfigured(): void public function testCreateThrowsIfHttpProxyOptionIsUsedWithCustomHttpClient(): void { $httpClientFactory = new HttpClientFactory( - Psr17FactoryDiscovery::findUrlFactory(), - Psr17FactoryDiscovery::findResponseFactory(), - Psr17FactoryDiscovery::findStreamFactory(), + null, + null, + new WellKnownPsr17Factory(), $this->createMock(HttpAsyncClientInterface::class), 'sentry.php.test', '1.2.3' diff --git a/tests/HttpClient/Plugin/GzipEncoderPluginTest.php b/tests/HttpClient/Plugin/GzipEncoderPluginTest.php index 638406393..d0ffae7b4 100644 --- a/tests/HttpClient/Plugin/GzipEncoderPluginTest.php +++ b/tests/HttpClient/Plugin/GzipEncoderPluginTest.php @@ -4,7 +4,7 @@ namespace Sentry\Tests\HttpClient\Plugin; -use Http\Discovery\Psr17FactoryDiscovery; +use FriendsOfPHP\WellKnownImplementations\WellKnownPsr17Factory; use Http\Promise\Promise as PromiseInterface; use PHPUnit\Framework\TestCase; use Psr\Http\Message\RequestInterface; @@ -17,11 +17,12 @@ final class GzipEncoderPluginTest extends TestCase { public function testHandleRequest(): void { - $plugin = new GzipEncoderPlugin(Psr17FactoryDiscovery::findStreamFactory()); + $psr17Factory = new WellKnownPsr17Factory(); + $plugin = new GzipEncoderPlugin($psr17Factory); $expectedPromise = $this->createMock(PromiseInterface::class); - $request = Psr17FactoryDiscovery::findRequestFactory() + $request = $psr17Factory ->createRequest('POST', 'http://www.example.com') - ->withBody(Psr17FactoryDiscovery::findStreamFactory()->createStream('foo')); + ->withBody($psr17Factory->createStream('foo')); $this->assertSame('foo', (string) $request->getBody()); $this->assertSame($expectedPromise, $plugin->handleRequest( diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 0632c8aa0..4766219f0 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -2,8 +2,6 @@ declare(strict_types=1); -use Http\Discovery\ClassDiscovery; -use Http\Discovery\Strategy\MockClientStrategy; use Sentry\Breadcrumb; use Sentry\Event; use Sentry\Tracing\Span; @@ -12,8 +10,6 @@ require_once __DIR__ . '/../vendor/autoload.php'; -ClassDiscovery::appendStrategy(MockClientStrategy::class); - // According to the Symfony documentation the proper way to register the mocked // functions for a certain class would be to configure the listener in the // phpunit.xml file, however in our case it doesn't work because PHPUnit loads