Ловить исключения из жрут


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

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-уровневая ошибка и продолжение оттуда.

Я ловил GuzzleHttp\Exception\BadResponseException как @dado предлагает. Но однажды я получил GuzzleHttp\Exception\ConnectException когда DNS для домена не доступен. Так что мое предложение - поймать GuzzleHttp\Exception\ConnectException чтобы быть в безопасности об ошибках DNS, а также.

    try {

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