send($handler, $request, $options)->otherwise(function (Throwable $exception) use ($handler, $request, $options): PromiseInterface { if (! $exception instanceof ConnectException || $this->timedOutAfterSending($exception) || ! in_array($request->getMethod(), self::RETRIED_METHODS, true)) { return Create::rejectionFor($exception); } Sleep::usleep(500_000); return $this->send($handler, $request, $options); }); }; } private function timedOutAfterSending(ConnectException $exception): bool { $context = $exception->getHandlerContext(); return ($context['errno'] ?? null) === CURLE_OPERATION_TIMEDOUT && ($context['request_size'] ?? 0) > 0; } /** * The cURL handler rejects the promise on a connection failure, but other handlers (such as Http::fake()) throw. */ private function send(callable $handler, RequestInterface $request, array $options): PromiseInterface { try { return Create::promiseFor($handler($request, $options)); } catch (ConnectException $exception) { return Create::rejectionFor($exception); } } }