Skip to content

Commit

Permalink
Add a default cURL HTTP client (#1589)
Browse files Browse the repository at this point in the history
  • Loading branch information
cleptric authored Oct 18, 2023
1 parent b6dc1d2 commit 83d6d01
Show file tree
Hide file tree
Showing 43 changed files with 820 additions and 1,518 deletions.
11 changes: 2 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,14 @@
"php": "^7.2|^8.0",
"ext-json": "*",
"ext-mbstring": "*",
"guzzlehttp/promises": "^1.5.3|^2.0",
"ext-curl": "*",
"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.15",
"php-http/httplug": "^1.1|^2.0",
"php-http/message": "^1.5",
"php-http/message-factory": "^1.1",
"psr/http-factory": "^1.0",
"psr/http-factory-implementation": "^1.0",
"psr/log": "^1.0|^2.0|^3.0",
"symfony/options-resolver": "^3.4.43|^4.4.30|^5.0.11|^6.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.19|3.4.*",
"guzzlehttp/promises": "^1.0|^2.0",
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
"http-interop/http-factory-guzzle": "^1.0",
"monolog/monolog": "^1.6|^2.0|^3.0",
Expand Down
65 changes: 20 additions & 45 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -35,51 +35,6 @@ parameters:
count: 1
path: src/Dsn.php

-
message: "#^Access to constant CONNECT_TIMEOUT on an unknown class GuzzleHttp\\\\RequestOptions\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Access to constant PROXY on an unknown class GuzzleHttp\\\\RequestOptions\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Access to constant TIMEOUT on an unknown class GuzzleHttp\\\\RequestOptions\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Call to static method create\\(\\) on an unknown class Symfony\\\\Component\\\\HttpClient\\\\HttpClient\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Call to static method createWithConfig\\(\\) on an unknown class Http\\\\Adapter\\\\Guzzle6\\\\Client\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Constructor of class Sentry\\\\HttpClient\\\\HttpClientFactory has an unused parameter \\$responseFactory\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Constructor of class Sentry\\\\HttpClient\\\\HttpClientFactory has an unused parameter \\$uriFactory\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Method Sentry\\\\HttpClient\\\\HttpClientFactory\\:\\:resolveClient\\(\\) should return Http\\\\Client\\\\HttpAsyncClient\\|Psr\\\\Http\\\\Client\\\\ClientInterface but returns Http\\\\Client\\\\Curl\\\\Client\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Method Sentry\\\\HttpClient\\\\HttpClientFactory\\:\\:resolveClient\\(\\) should return Http\\\\Client\\\\HttpAsyncClient\\|Psr\\\\Http\\\\Client\\\\ClientInterface but returns Symfony\\\\Component\\\\HttpClient\\\\HttplugClient\\.$#"
count: 1
path: src/HttpClient/HttpClientFactory.php

-
message: "#^Property Sentry\\\\Integration\\\\IgnoreErrorsIntegration\\:\\:\\$options \\(array\\{ignore_exceptions\\: array\\<int, class\\-string\\<Throwable\\>\\>, ignore_tags\\: array\\<string, string\\>\\}\\) does not accept array\\.$#"
count: 1
Expand Down Expand Up @@ -140,6 +95,11 @@ parameters:
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getHttpClient\\(\\) should return Sentry\\\\HttpClient\\\\HttpClientInterface\\|null but returns mixed\\.$#"
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getHttpConnectTimeout\\(\\) should return float but returns mixed\\.$#"
count: 1
Expand All @@ -150,6 +110,16 @@ parameters:
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getHttpProxyAuthentication\\(\\) should return string\\|null but returns mixed\\.$#"
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getHttpSslVerifyPeer\\(\\) should return bool but returns mixed\\.$#"
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getHttpTimeout\\(\\) should return float but returns mixed\\.$#"
count: 1
Expand Down Expand Up @@ -245,6 +215,11 @@ parameters:
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getTransport\\(\\) should return Sentry\\\\Transport\\\\TransportInterface\\|null but returns mixed\\.$#"
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:hasDefaultIntegrations\\(\\) should return bool but returns mixed\\.$#"
count: 1
Expand Down
14 changes: 9 additions & 5 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Sentry;

use GuzzleHttp\Promise\PromiseInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Sentry\Integration\IntegrationInterface;
Expand All @@ -13,6 +12,7 @@
use Sentry\Serializer\RepresentationSerializerInterface;
use Sentry\Serializer\SerializerInterface;
use Sentry\State\Scope;
use Sentry\Transport\Result;
use Sentry\Transport\TransportInterface;

/**
Expand Down Expand Up @@ -173,14 +173,18 @@ public function captureEvent(Event $event, ?EventHint $hint = null, ?Scope $scop
}

try {
/** @var Response $response */
$response = $this->transport->send($event)->wait();
$event = $response->getEvent();
/** @var Result $result */
$result = $this->transport->send($event);
$event = $result->getEvent();

if (null !== $event) {
return $event->getId();
}
} catch (\Throwable $exception) {
$this->logger->error(
sprintf('Failed to send the event to Sentry. Reason: "%s".', $exception->getMessage()),
['exception' => $exception, 'event' => $event]
);
}

return null;
Expand Down Expand Up @@ -216,7 +220,7 @@ public function getIntegration(string $className): ?IntegrationInterface
/**
* {@inheritdoc}
*/
public function flush(?int $timeout = null): PromiseInterface
public function flush(?int $timeout = null): Result
{
return $this->transport->close($timeout);
}
Expand Down
120 changes: 45 additions & 75 deletions src/ClientBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,36 @@

namespace Sentry;

use Http\Discovery\Psr17FactoryDiscovery;
use Psr\Log\LoggerInterface;
use Sentry\HttpClient\HttpClientFactory;
use Sentry\HttpClient\HttpClient;
use Sentry\HttpClient\HttpClientInterface;
use Sentry\Serializer\PayloadSerializer;
use Sentry\Serializer\RepresentationSerializerInterface;
use Sentry\Serializer\SerializerInterface;
use Sentry\Transport\DefaultTransportFactory;
use Sentry\Transport\TransportFactoryInterface;
use Sentry\Transport\HttpTransport;
use Sentry\Transport\TransportInterface;

/**
* The default implementation of {@link ClientBuilderInterface}.
* A configurable builder for Client objects.
*
* @author Stefano Arlandini <sarlandini@alice.it>
* @internal
*/
final class ClientBuilder implements ClientBuilderInterface
final class ClientBuilder
{
/**
* @var Options The client options
*/
private $options;

/**
* @var TransportFactoryInterface|null The transport factory
* @var TransportInterface The transport
*/
private $transportFactory;
private $transport;

/**
* @var TransportInterface|null The transport
* @var HttpClientInterface The HTTP client
*/
private $transport;
private $httpClient;

/**
* @var SerializerInterface|null The serializer to be injected in the client
Expand Down Expand Up @@ -68,127 +68,97 @@ final class ClientBuilder implements ClientBuilderInterface
public function __construct(Options $options = null)
{
$this->options = $options ?? new Options();

$this->httpClient = $this->options->getHttpClient() ?? new HttpClient($this->sdkIdentifier, $this->sdkVersion);
$this->transport = $this->options->getTransport() ?? new HttpTransport(
$this->options,
$this->httpClient,
new PayloadSerializer($this->options),
$this->logger
);
}

/**
* {@inheritdoc}
* @param array<string, mixed> $options The client options, in naked array form
*/
public static function create(array $options = []): ClientBuilderInterface
public static function create(array $options = []): ClientBuilder
{
return new self(new Options($options));
}

/**
* {@inheritdoc}
*/
public function getOptions(): Options
{
return $this->options;
}

/**
* {@inheritdoc}
*/
public function setSerializer(SerializerInterface $serializer): ClientBuilderInterface
public function setSerializer(SerializerInterface $serializer): ClientBuilder
{
$this->serializer = $serializer;

return $this;
}

/**
* {@inheritdoc}
*/
public function setRepresentationSerializer(RepresentationSerializerInterface $representationSerializer): ClientBuilderInterface
public function setRepresentationSerializer(RepresentationSerializerInterface $representationSerializer): ClientBuilder
{
$this->representationSerializer = $representationSerializer;

return $this;
}

/**
* {@inheritdoc}
*/
public function setLogger(LoggerInterface $logger): ClientBuilderInterface
public function setLogger(LoggerInterface $logger): ClientBuilder
{
$this->logger = $logger;

return $this;
}

/**
* {@inheritdoc}
*/
public function setSdkIdentifier(string $sdkIdentifier): ClientBuilderInterface
public function setSdkIdentifier(string $sdkIdentifier): ClientBuilder
{
$this->sdkIdentifier = $sdkIdentifier;

return $this;
}

/**
* {@inheritdoc}
*/
public function setSdkVersion(string $sdkVersion): ClientBuilderInterface
public function setSdkVersion(string $sdkVersion): ClientBuilder
{
$this->sdkVersion = $sdkVersion;

return $this;
}

/**
* {@inheritdoc}
*/
public function setTransportFactory(TransportFactoryInterface $transportFactory): ClientBuilderInterface
public function getTransport(): TransportInterface
{
$this->transportFactory = $transportFactory;

return $this;
return $this->transport;
}

/**
* {@inheritdoc}
*/
public function getClient(): ClientInterface
public function setTransport(TransportInterface $transport): ClientBuilder
{
$this->transport = $this->transport ?? $this->createTransportInstance();
$this->transport = $transport;

return new Client($this->options, $this->transport, $this->sdkIdentifier, $this->sdkVersion, $this->serializer, $this->representationSerializer, $this->logger);
return $this;
}

/**
* Creates a new instance of the transport mechanism.
*/
private function createTransportInstance(): TransportInterface
public function getHttpClient(): HttpClientInterface
{
if (null !== $this->transport) {
return $this->transport;
}
return $this->httpClient;
}

$transportFactory = $this->transportFactory ?? $this->createDefaultTransportFactory();
public function setHttpClient(HttpClientInterface $httpClient): ClientBuilder
{
$this->httpClient = $httpClient;

return $transportFactory->create($this->options);
return $this;
}

/**
* Creates a new instance of the {@see DefaultTransportFactory} factory.
*/
private function createDefaultTransportFactory(): DefaultTransportFactory
public function getClient(): ClientInterface
{
$streamFactory = Psr17FactoryDiscovery::findStreamFactory();
$httpClientFactory = new HttpClientFactory(
null,
null,
$streamFactory,
null,
return new Client(
$this->options,
$this->transport,
$this->sdkIdentifier,
$this->sdkVersion
);

return new DefaultTransportFactory(
$streamFactory,
Psr17FactoryDiscovery::findRequestFactory(),
$httpClientFactory,
$this->sdkVersion,
$this->serializer,
$this->representationSerializer,
$this->logger
);
}
Expand Down
Loading

0 comments on commit 83d6d01

Please sign in to comment.