Skip to content

Support http_connect_timeout and http_timeout options #1282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
May 16, 2022
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- Bump minimum version of `guzzlehttp/psr7` package to avoid [`CVE-2022-24775`](https://github.com/guzzle/psr7/security/advisories/GHSA-q7rv-6hp3-vh96) (#1305)
- Add `http_connect_timeout` and `http_timeout` client options (#1282)

## 3.4.0 (2022-03-14)

Expand Down
10 changes: 10 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,21 @@ parameters:
count: 1
path: src/Options.php

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

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

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

-
message: "#^Method Sentry\\\\Options\\:\\:getInAppExcludedPaths\\(\\) should return array\\<string\\> but returns mixed\\.$#"
count: 1
Expand Down
22 changes: 6 additions & 16 deletions src/HttpClient/HttpClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,6 @@
*/
final class HttpClientFactory implements HttpClientFactoryInterface
{
/**
* @var int The timeout of the request in seconds
*/
private const DEFAULT_HTTP_TIMEOUT = 5;

/**
* @var int The default number of seconds to wait while trying to connect
* to a server
*/
private const DEFAULT_HTTP_CONNECT_TIMEOUT = 2;

/**
* @var StreamFactoryInterface The PSR-17 stream factory
*/
Expand Down Expand Up @@ -123,7 +112,8 @@ private function resolveClient(Options $options)
{
if (class_exists(SymfonyHttplugClient::class)) {
$symfonyConfig = [
'max_duration' => self::DEFAULT_HTTP_TIMEOUT,
'timeout' => $options->getHttpConnectTimeout(),
'max_duration' => $options->getHttpTimeout(),
];

if (null !== $options->getHttpProxy()) {
Expand All @@ -135,8 +125,8 @@ private function resolveClient(Options $options)

if (class_exists(GuzzleHttpClient::class)) {
$guzzleConfig = [
GuzzleHttpClientOptions::TIMEOUT => self::DEFAULT_HTTP_TIMEOUT,
GuzzleHttpClientOptions::CONNECT_TIMEOUT => self::DEFAULT_HTTP_CONNECT_TIMEOUT,
GuzzleHttpClientOptions::TIMEOUT => $options->getHttpTimeout(),
GuzzleHttpClientOptions::CONNECT_TIMEOUT => $options->getHttpConnectTimeout(),
];

if (null !== $options->getHttpProxy()) {
Expand All @@ -148,8 +138,8 @@ private function resolveClient(Options $options)

if (class_exists(CurlHttpClient::class)) {
$curlConfig = [
\CURLOPT_TIMEOUT => self::DEFAULT_HTTP_TIMEOUT,
\CURLOPT_CONNECTTIMEOUT => self::DEFAULT_HTTP_CONNECT_TIMEOUT,
\CURLOPT_TIMEOUT => $options->getHttpTimeout(),
\CURLOPT_CONNECTTIMEOUT => $options->getHttpConnectTimeout(),
];

if (null !== $options->getHttpProxy()) {
Expand Down
60 changes: 59 additions & 1 deletion src/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,22 @@ final class Options
*/
public const DEFAULT_MAX_BREADCRUMBS = 100;

/**
* The default maximum execution time in seconds for the request+response
* as a whole.
*/
public const DEFAULT_HTTP_TIMEOUT = 5;

/**
* The default maximum number of seconds to wait while trying to connect to a
* server.
*/
public const DEFAULT_HTTP_CONNECT_TIMEOUT = 2;

/**
* @var array<string, mixed> The configuration options
*/
private $options = [];
private $options;

/**
* @var OptionsResolver The options resolver
Expand Down Expand Up @@ -578,6 +590,48 @@ public function setHttpProxy(?string $httpProxy): void
$this->options = $this->resolver->resolve($options);
}

/**
* Gets the maximum number of seconds to wait while trying to connect to a server.
*/
public function getHttpConnectTimeout(): float
{
return $this->options['http_connect_timeout'];
}

/**
* Sets the maximum number of seconds to wait while trying to connect to a server.
*
* @param float $httpConnectTimeout The amount of time in seconds
*/
public function setHttpConnectTimeout(float $httpConnectTimeout): void
{
$options = array_merge($this->options, ['http_connect_timeout' => $httpConnectTimeout]);

$this->options = $this->resolver->resolve($options);
}

/**
* Gets the maximum execution time for the request+response as a whole.
*/
public function getHttpTimeout(): float
{
return $this->options['http_timeout'];
}

/**
* Sets the maximum execution time for the request+response as a whole. The
* value should also include the time for the connect phase, so it should be
* greater than the value set for the `http_connect_timeout` option.
*
* @param float $httpTimeout The amount of time in seconds
*/
public function setHttpTimeout(float $httpTimeout): void
{
$options = array_merge($this->options, ['http_timeout' => $httpTimeout]);

$this->options = $this->resolver->resolve($options);
}

/**
* Gets whether the silenced errors should be captured or not.
*
Expand Down Expand Up @@ -726,6 +780,8 @@ private function configureOptions(OptionsResolver $resolver): void
'send_default_pii' => false,
'max_value_length' => 1024,
'http_proxy' => null,
'http_connect_timeout' => self::DEFAULT_HTTP_CONNECT_TIMEOUT,
'http_timeout' => self::DEFAULT_HTTP_TIMEOUT,
'capture_silenced_errors' => false,
'max_request_body_size' => 'medium',
'class_serializers' => [],
Expand Down Expand Up @@ -756,6 +812,8 @@ private function configureOptions(OptionsResolver $resolver): void
$resolver->setAllowedTypes('default_integrations', 'bool');
$resolver->setAllowedTypes('max_value_length', 'int');
$resolver->setAllowedTypes('http_proxy', ['null', 'string']);
$resolver->setAllowedTypes('http_connect_timeout', ['int', 'float']);
$resolver->setAllowedTypes('http_timeout', ['int', 'float']);
$resolver->setAllowedTypes('capture_silenced_errors', 'bool');
$resolver->setAllowedTypes('max_request_body_size', 'string');
$resolver->setAllowedTypes('class_serializers', 'array');
Expand Down
40 changes: 38 additions & 2 deletions tests/OptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function testConstructor(

$options = new Options([$option => $value]);

$this->assertSame($value, $options->$getterMethod());
$this->assertEquals($value, $options->$getterMethod());
}

/**
Expand Down Expand Up @@ -81,7 +81,7 @@ public function testGettersAndSetters(
$options->$setterMethod($value);
}

$this->assertSame($value, $options->$getterMethod());
$this->assertEquals($value, $options->$getterMethod());
}

public function optionsDataProvider(): \Generator
Expand Down Expand Up @@ -293,6 +293,42 @@ static function (): void {},
null,
];

yield [
'http_timeout',
1,
'getHttpTimeout',
'setHttpTimeout',
null,
null,
];

yield [
'http_timeout',
1.2,
'getHttpTimeout',
'setHttpTimeout',
null,
null,
];

yield [
'http_connect_timeout',
1,
'getHttpConnectTimeout',
'setHttpConnectTimeout',
null,
null,
];

yield [
'http_connect_timeout',
1.2,
'getHttpConnectTimeout',
'setHttpConnectTimeout',
null,
null,
];

yield [
'capture_silenced_errors',
true,
Expand Down