Guzzle exception exceptions

I am trying to catch the exceptions from the test suite that I run on the API that I am developing, and I use Guzzle to use the API methods. I have tests wrapped in a try / catch block, but it still throws unhandled exception errors. Adding an event listener as described in their docs doesn't seem to do anything. I need to get answers containing HTTP codes 500, 401, 400, in fact everything is not 200, because the system will set the most suitable code based on the result of the call if it does not work.

Current code example

foreach($tests as $test){ $client = new Client($api_url); $client->getEventDispatcher()->addListener('request.error', function(Event $event) { if ($event['response']->getStatusCode() == 401) { $newResponse = new Response($event['response']->getStatusCode()); $event['response'] = $newResponse; $event->stopPropagation(); } }); try { $client->setDefaultOption('query', $query_string); $request = $client->get($api_version . $test['method'], array(), isset($test['query'])?$test['query']:array()); // Do something with Guzzle. $response = $request->send(); displayTest($request, $response); } catch (Guzzle\Http\Exception\ClientErrorResponseException $e) { $req = $e->getRequest(); $resp =$e->getResponse(); displayTest($req,$resp); } catch (Guzzle\Http\Exception\ServerErrorResponseException $e) { $req = $e->getRequest(); $resp =$e->getResponse(); displayTest($req,$resp); } catch (Guzzle\Http\Exception\BadResponseException $e) { $req = $e->getRequest(); $resp =$e->getResponse(); displayTest($req,$resp); } catch( Exception $e){ echo "AGH!"; } unset($client); $client=null; } 

Even with a specific catch block for the selected exception type, I still return

 Fatal error: Uncaught exception 'Guzzle\Http\Exception\ClientErrorResponseException' with message 'Client error response [status code] 401 [reason phrase] Unauthorized [url] 

and all execution on the page stops, as you would expect. Adding a BadResponseException capture allowed me to catch 404s correctly, but this does not seem to work for 500 or 401 responses. Can anyone suggest where I am wrong, please.

+38
api php functional-testing guzzle
Jul 15 '13 at 15:44
source share
8 answers

If an exception is thrown in this try block, then in the worst case, the Exception should catch something that is not displayed.

Note that the first part of the test throws an exception and ends it in a try block.

+9
Jul 15 '13 at 15:51
source share

Depending on your project, you may need to disable buzz exceptions. Coding rules sometimes prohibit flow control exceptions. You can disable exceptions for Guzzle 3 as follows:

 $client = new \Guzzle\Http\Client($httpBase, array( 'request.options' => array( 'exceptions' => false, ) )); 

This does not disable curl exceptions for something like timeouts, but now you can easily get every status code:

 $request = $client->get($uri); $response = $request->send(); $statuscode = $response->getStatusCode(); 

To check if you have valid code, you can use something like this:

 if ($statuscode > 300) { // Do some error handling } 

... or better to handle all expected codes:

 if (200 === $statuscode) { // Do something } elseif (304 === $statuscode) { // Nothing to do } elseif (404 === $statuscode) { // Clean up DB or something like this } else { throw new MyException("Invalid response from api..."); } 

For Guzzle 5.3

 $client = new \GuzzleHttp\Client(['defaults' => [ 'exceptions' => false ]] ); 

Thanks @mika

For Guzzle 6

 $client = new \GuzzleHttp\Client(['http_errors' => false]); 
+69
Feb 09 '15 at 18:42
source share

To catch Guzzle errors, you can do something like this:

 try { $response = $client->get('/not_found.xml')->send(); } catch (Guzzle\Http\Exception\BadResponseException $e) { echo 'Uh oh! ' . $e->getMessage(); } 

... but to be able to "register" or "resend" your request, try something like this:

 // Add custom error handling to any request created by this client $client->getEventDispatcher()->addListener( 'request.error', function(Event $event) { //write log here ... if ($event['response']->getStatusCode() == 401) { // create new token and resend your request... $newRequest = $event['request']->clone(); $newRequest->setHeader('X-Auth-Header', MyApplication::getNewAuthToken()); $newResponse = $newRequest->send(); // Set the response object of the request without firing more events $event['response'] = $newResponse; // You can also change the response and fire the normal chain of // events by calling $event['request']->setResponse($newResponse); // Stop other events from firing when you override 401 responses $event->stopPropagation(); } }); 

... or if you want to β€œstop the propagation of events,” you can turn off the event listener (with a higher priority than -255), and simply stop the propagation of the event.

 $client->getEventDispatcher()->addListener('request.error', function(Event $event) { if ($event['response']->getStatusCode() != 200) { // Stop other events from firing when you get stytus-code != 200 $event->stopPropagation(); } }); 

It is a good idea to prevent buzzing bugs, for example:

 request.CRITICAL: Uncaught PHP Exception Guzzle\Http\Exception\ClientErrorResponseException: "Client error response 

in your application.

+37
Sep 25 '13 at 14:11
source share

You need to add an extra parameter using http_errors => false

 $request = $client->get($url, ['http_errors' => false]); 
+5
Sep 14 '15 at 7:19
source share

An old question, but Guzzle adds the answer to the exception object. So, the simplest try-catch is on GuzzleHttp\Exception\ClientException , and then using getResponse in this exception to see what the error is at level 400 and further from there.

+4
Sep 22 '16 at 19:52
source share

In my case, I threw an Exception into the file with names, so php tried to catch My\Namespace\Exception , so I did not find any exceptions at all.

It is worth checking if catch (Exception $e) correct Exception class.

Just try catch (\Exception $e) (with this \ there) and see if it works.

+3
Feb 16 '17 at 16:59
source share

I caught GuzzleHttp\Exception\BadResponseException as @dado suggests. But once I got GuzzleHttp\Exception\ConnectException when DNS for the domain was not available. Therefore, my suggestion is catch GuzzleHttp\Exception\ConnectException , to be safe from DNS errors.

+2
Aug 01 '16 at 8:35
source share
  try { } catch (GuzzleHttp\Subscriber\HttpError $e) { //catches all 4xx and 5xx status codes } 
+1
Feb 27 '16 at 15:00
source share



All Articles