Ответ 1
Если исключение выбрано в этом блоке try
, то в худшем случае Exception
должен ловить что-либо неотображенное.
Учтите, что первая часть теста бросает исключение и завершает его в блок try
.
Я пытаюсь поймать исключения из набора тестов, которые я запускаю на 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
}