Ловить исключения из жрут
Я пытаюсь поймать исключения из набора тестов, которые я запускаю на 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 (GuzzleHttpExceptionClientErrorResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch (GuzzleHttpExceptionServerErrorResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch (GuzzleHttpExceptionBadResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch( Exception $e){
echo "AGH!";
}
unset($client);
$client=null;
}
даже с конкретным блоком catch для брошенного типа исключения я все еще возвращаюсь
Fatal error: Uncaught exception 'GuzzleHttpExceptionClientErrorResponseException' with message 'Client error response [status code] 401 [reason phrase] Unauthorized [url]
и все выполнение на странице останавливается, как и следовало ожидать. Добавление улова BadResponseException позволило мне правильно поймать 404s, но это, похоже, не работает для 500 или 401 ответов. Может кто-нибудь подсказать, где я ошибаюсь, пожалуйста.
8 ответов:
Если исключение выбрасывается в
try
блок, то в худшем случаеException
должен ловить что-нибудь неперехваченное.считайте, что первая часть теста бросает исключение и оберните это в
try
блок, а также.
в зависимости от вашего проекта, отключение исключений для жрать может быть необходимо. Иногда правила кодирования запрещают исключения для управления потоком. Вы можете отключить исключения для жрать 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..."); }
Для Жрать 5.3
$client = new \GuzzleHttp\Client(['defaults' => [ 'exceptions' => false ]] );
спасибо @mika
Для Жрать 6
$client = new \GuzzleHttp\Client(['http_errors' => false]);
чтобы поймать жрать ошибки вы можете сделать что-то вроде этого:
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
в вашем приложении.
в моем случае я бросал
Exception
в файле с пространством имен, поэтому php попытался пойматьMy\Namespace\Exception
поэтому не ловит никаких исключений вообще.стоит проверить, если
catch (Exception $e)
найти правильныйException
класса.просто попробовать
catch (\Exception $e)
(С\
есть) и посмотреть, если это работает.
вам нужно добавить дополнительный параметр с http_errors = > false
$request = $client->get($url, ['http_errors' => false]);
старый вопрос, но жрать добавляет ответ в пределах объекта исключения. Так что простая попытка-поймать на
GuzzleHttp\Exception\ClientException
и затем с помощьюgetResponse
на этом исключении, чтобы увидеть, что 400-уровневая ошибка и продолжение оттуда.