diff --git a/AmpHttpClient.php b/AmpHttpClient.php index 341961e..f93aaa8 100644 --- a/AmpHttpClient.php +++ b/AmpHttpClient.php @@ -64,7 +64,7 @@ final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface, * * @see HttpClientInterface::OPTIONS_DEFAULTS for available options */ - public function __construct(array $defaultOptions = [], callable $clientConfigurator = null, int $maxHostConnections = 6, int $maxPendingPushes = 50) + public function __construct(array $defaultOptions = [], ?callable $clientConfigurator = null, int $maxHostConnections = 6, int $maxPendingPushes = 50) { $this->defaultOptions['buffer'] ??= self::shouldBuffer(...); @@ -148,7 +148,7 @@ public function request(string $method, string $url, array $options = []): Respo return new AmpResponse($this->multi, $request, $options, $this->logger); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { if ($responses instanceof AmpResponse) { $responses = [$responses]; diff --git a/AsyncDecoratorTrait.php b/AsyncDecoratorTrait.php index 912b825..785c34a 100644 --- a/AsyncDecoratorTrait.php +++ b/AsyncDecoratorTrait.php @@ -30,7 +30,7 @@ trait AsyncDecoratorTrait */ abstract public function request(string $method, string $url, array $options = []): ResponseInterface; - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { if ($responses instanceof AsyncResponse) { $responses = [$responses]; diff --git a/CachingHttpClient.php b/CachingHttpClient.php index 8940c6d..fd6a18c 100644 --- a/CachingHttpClient.php +++ b/CachingHttpClient.php @@ -105,7 +105,7 @@ public function request(string $method, string $url, array $options = []): Respo return MockResponse::fromRequest($method, $url, $options, $response); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { if ($responses instanceof ResponseInterface) { $responses = [$responses]; diff --git a/Chunk/ErrorChunk.php b/Chunk/ErrorChunk.php index 5584438..3b61d82 100644 --- a/Chunk/ErrorChunk.php +++ b/Chunk/ErrorChunk.php @@ -84,7 +84,7 @@ public function getError(): ?string return $this->errorMessage; } - public function didThrow(bool $didThrow = null): bool + public function didThrow(?bool $didThrow = null): bool { if (null !== $didThrow && $this->didThrow !== $didThrow) { return !$this->didThrow = $didThrow; diff --git a/CurlHttpClient.php b/CurlHttpClient.php index bbaa4de..e74e026 100644 --- a/CurlHttpClient.php +++ b/CurlHttpClient.php @@ -317,7 +317,7 @@ public function request(string $method, string $url, array $options = []): Respo return $pushedResponse ?? new CurlResponse($this->multi, $ch, $options, $this->logger, $method, self::createRedirectResolver($options, $host, $port), CurlClientState::$curlVersion['version_number'], $url); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { if ($responses instanceof CurlResponse) { $responses = [$responses]; diff --git a/DataCollector/HttpClientDataCollector.php b/DataCollector/HttpClientDataCollector.php index 5839989..8e85462 100644 --- a/DataCollector/HttpClientDataCollector.php +++ b/DataCollector/HttpClientDataCollector.php @@ -38,7 +38,7 @@ public function registerClient(string $name, TraceableHttpClient $client): void $this->clients[$name] = $client; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { $this->lateCollect(); } diff --git a/DecoratorTrait.php b/DecoratorTrait.php index c100a73..6fcb349 100644 --- a/DecoratorTrait.php +++ b/DecoratorTrait.php @@ -25,7 +25,7 @@ trait DecoratorTrait { private HttpClientInterface $client; - public function __construct(HttpClientInterface $client = null) + public function __construct(?HttpClientInterface $client = null) { $this->client = $client ?? HttpClient::create(); } @@ -35,7 +35,7 @@ public function request(string $method, string $url, array $options = []): Respo return $this->client->request($method, $url, $options); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { return $this->client->stream($responses, $timeout); } diff --git a/EventSourceHttpClient.php b/EventSourceHttpClient.php index 853657c..80022ea 100644 --- a/EventSourceHttpClient.php +++ b/EventSourceHttpClient.php @@ -33,7 +33,7 @@ final class EventSourceHttpClient implements HttpClientInterface, ResetInterface private float $reconnectionTime; - public function __construct(HttpClientInterface $client = null, float $reconnectionTime = 10.0) + public function __construct(?HttpClientInterface $client = null, float $reconnectionTime = 10.0) { $this->client = $client ?? HttpClient::create(); $this->reconnectionTime = $reconnectionTime; diff --git a/HttpClientTrait.php b/HttpClientTrait.php index 193efbf..85a1814 100644 --- a/HttpClientTrait.php +++ b/HttpClientTrait.php @@ -535,7 +535,7 @@ private static function normalizePeerFingerprint(mixed $fingerprint): array /** * @throws InvalidArgumentException When the value cannot be json-encoded */ - private static function jsonEncode(mixed $value, int $flags = null, int $maxDepth = 512): string + private static function jsonEncode(mixed $value, ?int $flags = null, int $maxDepth = 512): string { $flags ??= \JSON_HEX_TAG | \JSON_HEX_APOS | \JSON_HEX_AMP | \JSON_HEX_QUOT | \JSON_PRESERVE_ZERO_FRACTION; diff --git a/HttplugClient.php b/HttplugClient.php index 2652f15..67cf827 100644 --- a/HttplugClient.php +++ b/HttplugClient.php @@ -69,7 +69,7 @@ final class HttplugClient implements ClientInterface, HttpAsyncClient, RequestFa private HttplugWaitLoop $waitLoop; - public function __construct(HttpClientInterface $client = null, ResponseFactoryInterface $responseFactory = null, StreamFactoryInterface $streamFactory = null) + public function __construct(?HttpClientInterface $client = null, ?ResponseFactoryInterface $responseFactory = null, ?StreamFactoryInterface $streamFactory = null) { $this->client = $client ?? HttpClient::create(); $streamFactory ??= $responseFactory instanceof StreamFactoryInterface ? $responseFactory : null; @@ -143,7 +143,7 @@ public function sendAsyncRequest(RequestInterface $request): HttplugPromise * * @return int The number of remaining pending promises */ - public function wait(float $maxDuration = null, float $idleTimeout = null): int + public function wait(?float $maxDuration = null, ?float $idleTimeout = null): int { return $this->waitLoop->wait(null, $maxDuration, $idleTimeout); } @@ -220,7 +220,7 @@ public function reset(): void } } - private function sendPsr7Request(RequestInterface $request, bool $buffer = null): ResponseInterface + private function sendPsr7Request(RequestInterface $request, ?bool $buffer = null): ResponseInterface { try { $body = $request->getBody(); diff --git a/Internal/AmpClientState.php b/Internal/AmpClientState.php index 90a002f..c5e6968 100644 --- a/Internal/AmpClientState.php +++ b/Internal/AmpClientState.php @@ -150,7 +150,7 @@ private function getClient(array $options): array /** @var resource|null */ public $handle; - public function connect(string $uri, ConnectContext $context = null, CancellationToken $token = null): Promise + public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null): Promise { $result = $this->connector->connect($this->uri ?? $uri, $context, $token); $result->onResolve(function ($e, $socket) { diff --git a/Internal/AmpResolver.php b/Internal/AmpResolver.php index 1288023..9137be2 100644 --- a/Internal/AmpResolver.php +++ b/Internal/AmpResolver.php @@ -32,7 +32,7 @@ public function __construct(array &$dnsMap) $this->dnsMap = &$dnsMap; } - public function resolve(string $name, int $typeRestriction = null): Promise + public function resolve(string $name, ?int $typeRestriction = null): Promise { if (!isset($this->dnsMap[$name]) || !\in_array($typeRestriction, [Record::A, null], true)) { return Dns\resolver()->resolve($name, $typeRestriction); diff --git a/Internal/HttplugWaitLoop.php b/Internal/HttplugWaitLoop.php index eaccdb8..bebe135 100644 --- a/Internal/HttplugWaitLoop.php +++ b/Internal/HttplugWaitLoop.php @@ -46,7 +46,7 @@ public function __construct(HttpClientInterface $client, ?\SplObjectStorage $pro $this->streamFactory = $streamFactory; } - public function wait(?ResponseInterface $pendingResponse, float $maxDuration = null, float $idleTimeout = null): int + public function wait(?ResponseInterface $pendingResponse, ?float $maxDuration = null, ?float $idleTimeout = null): int { if (!$this->promisePool) { return 0; diff --git a/MockHttpClient.php b/MockHttpClient.php index e4b6c96..a0e08f9 100644 --- a/MockHttpClient.php +++ b/MockHttpClient.php @@ -35,7 +35,7 @@ class MockHttpClient implements HttpClientInterface, ResetInterface /** * @param callable|callable[]|ResponseInterface|ResponseInterface[]|iterable|null $responseFactory */ - public function __construct(callable|iterable|ResponseInterface $responseFactory = null, ?string $baseUri = 'https://example.com') + public function __construct(callable|iterable|ResponseInterface|null $responseFactory = null, ?string $baseUri = 'https://example.com') { $this->setResponseFactory($responseFactory); $this->defaultOptions['base_uri'] = $baseUri; @@ -84,7 +84,7 @@ public function request(string $method, string $url, array $options = []): Respo return MockResponse::fromRequest($method, $url, $options, $response); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { if ($responses instanceof ResponseInterface) { $responses = [$responses]; diff --git a/NativeHttpClient.php b/NativeHttpClient.php index ad6bfde..68f1fc2 100644 --- a/NativeHttpClient.php +++ b/NativeHttpClient.php @@ -269,7 +269,7 @@ public function request(string $method, string $url, array $options = []): Respo return new NativeResponse($this->multi, $context, implode('', $url), $options, $info, $resolver, $onProgress, $this->logger); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { if ($responses instanceof NativeResponse) { $responses = [$responses]; diff --git a/NoPrivateNetworkHttpClient.php b/NoPrivateNetworkHttpClient.php index 70c172f..7bfe24d 100644 --- a/NoPrivateNetworkHttpClient.php +++ b/NoPrivateNetworkHttpClient.php @@ -37,7 +37,7 @@ final class NoPrivateNetworkHttpClient implements HttpClientInterface, LoggerAwa * @param string|array|null $subnets String or array of subnets using CIDR notation that will be used by IpUtils. * If null is passed, the standard private subnets will be used. */ - public function __construct(HttpClientInterface $client, string|array $subnets = null) + public function __construct(HttpClientInterface $client, string|array|null $subnets = null) { if (!class_exists(IpUtils::class)) { throw new \LogicException(sprintf('You cannot use "%s" if the HttpFoundation component is not installed. Try running "composer require symfony/http-foundation".', __CLASS__)); @@ -72,7 +72,7 @@ public function request(string $method, string $url, array $options = []): Respo return $this->client->request($method, $url, $options); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { return $this->client->stream($responses, $timeout); } diff --git a/Psr18Client.php b/Psr18Client.php index 6120146..d46a7b1 100644 --- a/Psr18Client.php +++ b/Psr18Client.php @@ -54,7 +54,7 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str private ResponseFactoryInterface $responseFactory; private StreamFactoryInterface $streamFactory; - public function __construct(HttpClientInterface $client = null, ResponseFactoryInterface $responseFactory = null, StreamFactoryInterface $streamFactory = null) + public function __construct(?HttpClientInterface $client = null, ?ResponseFactoryInterface $responseFactory = null, ?StreamFactoryInterface $streamFactory = null) { $this->client = $client ?? HttpClient::create(); $streamFactory ??= $responseFactory instanceof StreamFactoryInterface ? $responseFactory : null; diff --git a/Response/AmpResponse.php b/Response/AmpResponse.php index 6dfb9a0..bb9aab1 100644 --- a/Response/AmpResponse.php +++ b/Response/AmpResponse.php @@ -134,7 +134,7 @@ public function __construct(AmpClientState $multi, Request $request, array $opti }); } - public function getInfo(string $type = null): mixed + public function getInfo(?string $type = null): mixed { return null !== $type ? $this->info[$type] ?? null : $this->info; } @@ -179,7 +179,7 @@ private static function schedule(self $response, array &$runningResponses): void /** * @param AmpClientState $multi */ - private static function perform(ClientState $multi, array &$responses = null): void + private static function perform(ClientState $multi, ?array &$responses = null): void { if ($responses) { foreach ($responses as $response) { diff --git a/Response/AsyncContext.php b/Response/AsyncContext.php index eeb7a11..4f4d106 100644 --- a/Response/AsyncContext.php +++ b/Response/AsyncContext.php @@ -116,7 +116,7 @@ public function cancel(): ChunkInterface /** * Returns the current info of the response. */ - public function getInfo(string $type = null): mixed + public function getInfo(?string $type = null): mixed { if (null !== $type) { return $this->info[$type] ?? $this->response->getInfo($type); @@ -189,7 +189,7 @@ public function replaceResponse(ResponseInterface $response): ResponseInterface * * @param ?callable(ChunkInterface, self): ?\Iterator $passthru */ - public function passthru(callable $passthru = null): void + public function passthru(?callable $passthru = null): void { $this->passthru = $passthru ?? static function ($chunk, $context) { $context->passthru = null; diff --git a/Response/AsyncResponse.php b/Response/AsyncResponse.php index 6f97915..ea27b1c 100644 --- a/Response/AsyncResponse.php +++ b/Response/AsyncResponse.php @@ -45,7 +45,7 @@ class AsyncResponse implements ResponseInterface, StreamableInterface /** * @param ?callable(ChunkInterface, AsyncContext): ?\Iterator $passthru */ - public function __construct(HttpClientInterface $client, string $method, string $url, array $options, callable $passthru = null) + public function __construct(HttpClientInterface $client, string $method, string $url, array $options, ?callable $passthru = null) { $this->client = $client; $this->shouldBuffer = $options['buffer'] ?? true; @@ -58,7 +58,7 @@ public function __construct(HttpClientInterface $client, string $method, string } $this->response = $client->request($method, $url, ['buffer' => false] + $options); $this->passthru = $passthru; - $this->initializer = static function (self $response, float $timeout = null) { + $this->initializer = static function (self $response, ?float $timeout = null) { if (null === $response->shouldBuffer) { return false; } @@ -66,7 +66,7 @@ public function __construct(HttpClientInterface $client, string $method, string while (true) { foreach (self::stream([$response], $timeout) as $chunk) { if ($chunk->isTimeout() && $response->passthru) { - foreach (self::passthru($response->client, $response, new ErrorChunk($response->offset, new TransportException($chunk->getError()))) as $chunk) { + foreach (self::passthru($response->client, $response, new ErrorChunk($response->offset, $chunk->getError())) as $chunk) { if ($chunk->isFirst()) { return false; } @@ -115,7 +115,7 @@ public function getHeaders(bool $throw = true): array return $headers; } - public function getInfo(string $type = null): mixed + public function getInfo(?string $type = null): mixed { if (null !== $type) { return $this->info[$type] ?? $this->response->getInfo($type); @@ -207,7 +207,7 @@ public function __destruct() /** * @internal */ - public static function stream(iterable $responses, float $timeout = null, string $class = null): \Generator + public static function stream(iterable $responses, ?float $timeout = null, ?string $class = null): \Generator { while ($responses) { $wrappedResponses = []; @@ -315,7 +315,7 @@ public static function stream(iterable $responses, float $timeout = null, string /** * @param \SplObjectStorage|null $asyncMap */ - private static function passthru(HttpClientInterface $client, self $r, ChunkInterface $chunk, \SplObjectStorage $asyncMap = null): \Generator + private static function passthru(HttpClientInterface $client, self $r, ChunkInterface $chunk, ?\SplObjectStorage $asyncMap = null): \Generator { $r->stream = null; $response = $r->response; diff --git a/Response/CurlResponse.php b/Response/CurlResponse.php index d472aca..1d9e4be 100644 --- a/Response/CurlResponse.php +++ b/Response/CurlResponse.php @@ -42,7 +42,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface /** * @internal */ - public function __construct(CurlClientState $multi, \CurlHandle|string $ch, array $options = null, LoggerInterface $logger = null, string $method = 'GET', callable $resolveRedirect = null, int $curlVersion = null, string $originalUrl = null) + public function __construct(CurlClientState $multi, \CurlHandle|string $ch, ?array $options = null, ?LoggerInterface $logger = null, string $method = 'GET', ?callable $resolveRedirect = null, ?int $curlVersion = null, ?string $originalUrl = null) { $this->multi = $multi; @@ -98,7 +98,6 @@ public function __construct(CurlClientState $multi, \CurlHandle|string $ch, arra $this->info['pause_handler'] = static function (float $duration) use ($ch, $multi, $execCounter) { if (0 < $duration) { if ($execCounter === $multi->execCounter) { - $multi->execCounter = !\is_float($execCounter) ? 1 + $execCounter : \PHP_INT_MIN; curl_multi_remove_handle($multi->handle, $ch); } @@ -193,7 +192,7 @@ public function __construct(CurlClientState $multi, \CurlHandle|string $ch, arra }); } - public function getInfo(string $type = null): mixed + public function getInfo(?string $type = null): mixed { if (!$info = $this->finalInfo) { $info = array_merge($this->info, curl_getinfo($this->handle)); @@ -266,7 +265,7 @@ private static function schedule(self $response, array &$runningResponses): void /** * @param CurlClientState $multi */ - private static function perform(ClientState $multi, array &$responses = null): void + private static function perform(ClientState $multi, ?array &$responses = null): void { if ($multi->performing) { if ($responses) { diff --git a/Response/HttplugPromise.php b/Response/HttplugPromise.php index e9dc240..274dac7 100644 --- a/Response/HttplugPromise.php +++ b/Response/HttplugPromise.php @@ -30,7 +30,7 @@ public function __construct(GuzzlePromiseInterface $promise) $this->promise = $promise; } - public function then(callable $onFulfilled = null, callable $onRejected = null): self + public function then(?callable $onFulfilled = null, ?callable $onRejected = null): self { return new self($this->promise->then( $this->wrapThenCallback($onFulfilled), diff --git a/Response/MockResponse.php b/Response/MockResponse.php index dba6307..0493bcb 100644 --- a/Response/MockResponse.php +++ b/Response/MockResponse.php @@ -88,7 +88,7 @@ public function getRequestMethod(): string return $this->requestMethod; } - public function getInfo(string $type = null): mixed + public function getInfo(?string $type = null): mixed { return null !== $type ? $this->info[$type] ?? null : $this->info; } diff --git a/Response/NativeResponse.php b/Response/NativeResponse.php index 4d9e3e2..7735070 100644 --- a/Response/NativeResponse.php +++ b/Response/NativeResponse.php @@ -86,7 +86,7 @@ public function __construct(NativeClientState $multi, $context, string $url, arr }); } - public function getInfo(string $type = null): mixed + public function getInfo(?string $type = null): mixed { if (!$info = $this->finalInfo) { $info = $this->info; @@ -228,7 +228,7 @@ private static function schedule(self $response, array &$runningResponses): void /** * @param NativeClientState $multi */ - private static function perform(ClientState $multi, array &$responses = null): void + private static function perform(ClientState $multi, ?array &$responses = null): void { foreach ($multi->openHandles as $i => [$pauseExpiry, $h, $buffer, $onProgress]) { if ($pauseExpiry) { diff --git a/Response/StreamWrapper.php b/Response/StreamWrapper.php index e68eacb..a668027 100644 --- a/Response/StreamWrapper.php +++ b/Response/StreamWrapper.php @@ -45,7 +45,7 @@ class StreamWrapper * * @return resource */ - public static function createResource(ResponseInterface $response, HttpClientInterface $client = null) + public static function createResource(ResponseInterface $response, ?HttpClientInterface $client = null) { if ($response instanceof StreamableInterface) { $stack = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 2); diff --git a/Response/TraceableResponse.php b/Response/TraceableResponse.php index 4944e25..d65c806 100644 --- a/Response/TraceableResponse.php +++ b/Response/TraceableResponse.php @@ -36,7 +36,7 @@ class TraceableResponse implements ResponseInterface, StreamableInterface private mixed $content; private ?StopwatchEvent $event; - public function __construct(HttpClientInterface $client, ResponseInterface $response, &$content, StopwatchEvent $event = null) + public function __construct(HttpClientInterface $client, ResponseInterface $response, &$content, ?StopwatchEvent $event = null) { $this->client = $client; $this->response = $response; @@ -134,7 +134,7 @@ public function cancel(): void } } - public function getInfo(string $type = null): mixed + public function getInfo(?string $type = null): mixed { return $this->response->getInfo($type); } diff --git a/Response/TransportResponseTrait.php b/Response/TransportResponseTrait.php index ca27178..7b65fd7 100644 --- a/Response/TransportResponseTrait.php +++ b/Response/TransportResponseTrait.php @@ -139,7 +139,7 @@ private function doDestruct(): void * * @internal */ - public static function stream(iterable $responses, float $timeout = null): \Generator + public static function stream(iterable $responses, ?float $timeout = null): \Generator { $runningResponses = []; diff --git a/RetryableHttpClient.php b/RetryableHttpClient.php index b506c9b..d3b7794 100644 --- a/RetryableHttpClient.php +++ b/RetryableHttpClient.php @@ -39,7 +39,7 @@ class RetryableHttpClient implements HttpClientInterface, ResetInterface /** * @param int $maxRetries The maximum number of times to retry */ - public function __construct(HttpClientInterface $client, RetryStrategyInterface $strategy = null, int $maxRetries = 3, LoggerInterface $logger = null) + public function __construct(HttpClientInterface $client, ?RetryStrategyInterface $strategy = null, int $maxRetries = 3, ?LoggerInterface $logger = null) { $this->client = $client; $this->strategy = $strategy ?? new GenericRetryStrategy(); diff --git a/ScopingHttpClient.php b/ScopingHttpClient.php index fd92a85..5734d3e 100644 --- a/ScopingHttpClient.php +++ b/ScopingHttpClient.php @@ -32,7 +32,7 @@ class ScopingHttpClient implements HttpClientInterface, ResetInterface, LoggerAw private array $defaultOptionsByRegexp; private ?string $defaultRegexp; - public function __construct(HttpClientInterface $client, array $defaultOptionsByRegexp, string $defaultRegexp = null) + public function __construct(HttpClientInterface $client, array $defaultOptionsByRegexp, ?string $defaultRegexp = null) { $this->client = $client; $this->defaultOptionsByRegexp = $defaultOptionsByRegexp; @@ -43,7 +43,7 @@ public function __construct(HttpClientInterface $client, array $defaultOptionsBy } } - public static function forBaseUri(HttpClientInterface $client, string $baseUri, array $defaultOptions = [], string $regexp = null): self + public static function forBaseUri(HttpClientInterface $client, string $baseUri, array $defaultOptions = [], ?string $regexp = null): self { $regexp ??= preg_quote(implode('', self::resolveUrl(self::parseUrl('.'), self::parseUrl($baseUri)))); @@ -88,7 +88,7 @@ public function request(string $method, string $url, array $options = []): Respo return $this->client->request($method, $url, $options); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { return $this->client->stream($responses, $timeout); } diff --git a/Tests/AsyncDecoratorTraitTest.php b/Tests/AsyncDecoratorTraitTest.php index e1c4b7e..97e4c42 100644 --- a/Tests/AsyncDecoratorTraitTest.php +++ b/Tests/AsyncDecoratorTraitTest.php @@ -26,7 +26,7 @@ class AsyncDecoratorTraitTest extends NativeHttpClientTest { - protected function getHttpClient(string $testCase, \Closure $chunkFilter = null, HttpClientInterface $decoratedClient = null): HttpClientInterface + protected function getHttpClient(string $testCase, ?\Closure $chunkFilter = null, ?HttpClientInterface $decoratedClient = null): HttpClientInterface { if ('testHandleIsRemovedOnException' === $testCase) { $this->markTestSkipped("AsyncDecoratorTrait doesn't cache handles"); @@ -43,7 +43,7 @@ protected function getHttpClient(string $testCase, \Closure $chunkFilter = null, private ?\Closure $chunkFilter; - public function __construct(HttpClientInterface $client, \Closure $chunkFilter = null) + public function __construct(HttpClientInterface $client, ?\Closure $chunkFilter = null) { $this->chunkFilter = $chunkFilter; $this->client = $client; diff --git a/Tests/RetryableHttpClientTest.php b/Tests/RetryableHttpClientTest.php index fcd839d..849d411 100644 --- a/Tests/RetryableHttpClientTest.php +++ b/Tests/RetryableHttpClientTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpClient\Exception\ServerException; +use Symfony\Component\HttpClient\Exception\TimeoutException; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\NativeHttpClient; @@ -21,6 +22,7 @@ use Symfony\Component\HttpClient\Retry\GenericRetryStrategy; use Symfony\Component\HttpClient\RetryableHttpClient; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; +use Symfony\Contracts\HttpClient\Test\TestHttpServer; class RetryableHttpClientTest extends TestCase { @@ -245,6 +247,35 @@ public function testRetryOnErrorAssertContent() self::assertSame('Test out content', $response->getContent(), 'Content should be buffered'); } + /** + * @testWith ["GET"] + * ["POST"] + * ["PUT"] + * ["PATCH"] + * ["DELETE"] + */ + public function testRetryOnHeaderTimeout(string $method) + { + $client = HttpClient::create(); + + if ($client instanceof NativeHttpClient) { + $this->markTestSkipped('NativeHttpClient cannot timeout before receiving headers'); + } + + TestHttpServer::start(); + + $client = new RetryableHttpClient($client); + $response = $client->request($method, 'http://localhost:8057/timeout-header', ['timeout' => 0.1]); + + try { + $response->getStatusCode(); + $this->fail(TimeoutException::class.' expected'); + } catch (TimeoutException $e) { + } + + $this->assertSame('Idle timeout reached for "http://localhost:8057/timeout-header".', $response->getInfo('error')); + } + public function testRetryWithMultipleBaseUris() { $client = new RetryableHttpClient( diff --git a/TraceableHttpClient.php b/TraceableHttpClient.php index 974e9f6..9f1bd51 100644 --- a/TraceableHttpClient.php +++ b/TraceableHttpClient.php @@ -30,7 +30,7 @@ final class TraceableHttpClient implements HttpClientInterface, ResetInterface, private ?Stopwatch $stopwatch; private \ArrayObject $tracedRequests; - public function __construct(HttpClientInterface $client, Stopwatch $stopwatch = null) + public function __construct(HttpClientInterface $client, ?Stopwatch $stopwatch = null) { $this->client = $client; $this->stopwatch = $stopwatch; @@ -66,7 +66,7 @@ public function request(string $method, string $url, array $options = []): Respo return new TraceableResponse($this->client, $this->client->request($method, $url, $options), $content, $this->stopwatch?->start("$method $url", 'http_client')); } - public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface + public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface { if ($responses instanceof TraceableResponse) { $responses = [$responses]; diff --git a/UriTemplateHttpClient.php b/UriTemplateHttpClient.php index 55ae724..2767ed3 100644 --- a/UriTemplateHttpClient.php +++ b/UriTemplateHttpClient.php @@ -22,7 +22,7 @@ class UriTemplateHttpClient implements HttpClientInterface, ResetInterface /** * @param (\Closure(string $url, array $vars): string)|null $expander */ - public function __construct(HttpClientInterface $client = null, private ?\Closure $expander = null, private array $defaultVars = []) + public function __construct(?HttpClientInterface $client = null, private ?\Closure $expander = null, private array $defaultVars = []) { $this->client = $client ?? HttpClient::create(); }