PHP: How to check for timeout exception in Guzzle

2019-03-19 03:55发布

问题:

Guzzle throws an exception if an error occured during the request. Unfortunately, there does not seem to be an error specific to timeouts - which is important for me as I know that those can ocassionally occur. I'd like to retry the corresponding request and need to able to tell if the error occured due to a timeout.

From the docs:

// Timeout if a server does not return a response in 3.14 seconds.
$client->get('/delay/5', ['timeout' => 3.14]);
// PHP Fatal error:  Uncaught exception 'GuzzleHttp\Exception\RequestException'

The RequestException has the info in itsmessage property:

"cURL error 28: Operation timed out after 3114 milliseconds with 0 bytes received"

So I could evaluate the message pattern but this feels kinda wrong, because those messages could easily be changed in the future.

Is there a better/more stable way to check for timeouts when using guzzle 4?

回答1:

I had the same problem, I've fixed it with stopping an event’s propagation. You can read more about this here.

use GuzzleHttp\Event\ErrorEvent;
use GuzzleHttp\Message\Response;

$client->getEmitter()->on('error', function(ErrorEvent $event) {
    $event->stopPropagation();
    $event->intercept(new Response(200));
    echo $event->getException()->getMessage();
});

In your case this will output cURL error 28: Operation timed out after 3114 milliseconds with 0 bytes received without throwing an RequestException.



回答2:

The Exeption is generated here:

https://github.com/guzzle/guzzle/blob/master/src/Adapter/Curl/CurlAdapter.php

private function handleError(
    TransactionInterface $transaction,
    $info,
    $handle
) {
    $error = curl_error($handle);
    $this->releaseEasyHandle($handle);
    RequestEvents::emitError(
        $transaction,
        new AdapterException("cURL error {$info['curl_result']}: {$error}"),
        $info
    );
}

while this is a private function, you have two options:

  • clone the entire file, give it a new name, use this instead of the CurlAdapter and throw another Exception than "AdapterException"
  • edit the file and throw another Exeption than "AdapterException" but in this case, your Guzzle is no longer maintainable.