Исключение исключений из Guzzle

Я пытаюсь поймать исключения из набора тестов, которые я запускаю на API, который я разрабатываю, и я использую Guzzle для использования методов API. У меня есть тесты, завернутые в блок try / catch, но он все еще бросает необработанные ошибки исключения. Добавление прослушивателя событий, как описано в их документах, похоже, ничего не делает. Мне нужно получить ответы, содержащие HTTP-коды 500, 401, 400, на самом деле все, что не 200, поскольку система установит наиболее подходящий код на основе результата вызова, если он не работает ,

Текущий пример кода

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; } 

Даже с конкретным блоком catch для выбранного типа исключения я все еще возвращаюсь

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

и все выполнение на странице останавливается, как и следовало ожидать. Добавление захвата BadResponseException позволило мне правильно поймать 404s, но это, похоже, не работает для 500 или 401 ответов. Может ли кто-нибудь предложить, где я ошибаюсь, пожалуйста.

Если исключение возникает в этом блоке try то в худшем случае Exception должен ловить что-либо неотображенное.

Учтите, что первая часть теста бросает исключение и завершает его в блок try .

В зависимости от вашего проекта может потребоваться отключение исключений для жужжания. Иногда правила кодирования запрещают исключения для управления потоком. Вы можете отключить исключения для Guzzle 3 следующим образом:

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

Это не отключает исключения curl для чего-то вроде тайм-аутов, но теперь вы можете легко получить каждый код состояния:

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

Чтобы проверить, есть ли у вас действительный код, вы можете использовать что-то вроде этого:

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

… или лучше обрабатывать все ожидаемые коды:

 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..."); } 

Для Guzzle 5.3

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

Благодаря @mika

Для Guzzle 6

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

Чтобы поймать ошибки Guzzle, вы можете сделать что-то вроде этого:

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

… но, чтобы иметь возможность «регистрировать» или «повторно отправлять» ваш запрос, попробуйте что-то вроде этого:

 // 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(); } }); 

… или если вы хотите «остановить распространение событий», вы можете переопределить прослушиватель событий (с более высоким приоритетом, чем -255), и просто прекратить распространение события.

 $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(); } }); 

Это хорошая идея, чтобы предотвратить ошибки жужжания, такие как:

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

в вашем приложении.

Вам нужно добавить дополнительный параметр с помощью http_errors => false

 $request = $client->get($url, ['http_errors' => false]); 

Старый вопрос, но Guzzle добавляет ответ в объект исключения. Итак, простой try-catch на GuzzleHttp\Exception\ClientException а затем с помощью getResponse в этом исключении, чтобы увидеть, что такое ошибка на уровне 400 и дальше оттуда.

В моем случае я бросал Exception в файл с именами, поэтому php попытался поймать My\Namespace\Exception поэтому вообще не обнаружил никаких исключений.

Стоит проверить, если catch (Exception $e) находит правильный класс Exception .

Просто попробуйте catch (\Exception $e) (с этим \ там) и посмотрите, работает ли он.

Я ловил GuzzleHttp\Exception\BadResponseException как предлагает @dado. Но однажды я получил GuzzleHttp\Exception\ConnectException когда DNS для домена не был доступен. Поэтому мое предложение – catch GuzzleHttp\Exception\ConnectException чтобы быть в безопасности и от ошибок DNS.

  try { } catch (GuzzleHttp\Subscriber\HttpError $e) { //catches all 4xx and 5xx status codes }