Я пытаюсь поймать исключения из набора тестов, которые я запускаю на 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 }