php - debug - Capturando excepciones de Guzzle
install guzzle (8)
Estoy tratando de detectar excepciones de un conjunto de pruebas que estoy ejecutando en una API que estoy desarrollando y estoy usando Guzzle para consumir los métodos API. Tengo las pruebas envueltas en un bloque try / catch, pero aún arroja errores de excepción no controlados. Agregar un detector de eventos como se describe en sus documentos no parece hacer nada. Necesito poder recuperar las respuestas que tienen códigos HTTP de 500, 401, 400, de hecho, cualquier cosa que no sea 200 ya que el sistema establecerá el código más apropiado en función del resultado de la llamada si no funcionó .
Ejemplo de código actual
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;
}
Incluso con el bloque catch específico para el tipo de excepción lanzada todavía estoy volviendo
Fatal error: Uncaught exception ''Guzzle/Http/Exception/ClientErrorResponseException'' with message ''Client error response [status code] 401 [reason phrase] Unauthorized [url]
y toda la ejecución en la página se detiene, como era de esperar. La adición de la captura BadResponseException me permitió detectar los 404 correctamente, pero parece que esto no funciona para 500 o 401 respuestas. ¿Alguien puede sugerirme dónde estoy yendo mal, por favor?
Dependiendo de su proyecto, la desactivación de excepciones para guzzle podría ser necesaria. A veces, las reglas de codificación no permiten excepciones para el control de flujo. Puede desactivar excepciones para Guzzle 3 de esta manera:
$client = new /Guzzle/Http/Client($httpBase, array(
''request.options'' => array(
''exceptions'' => false,
)
));
Esto no deshabilita las excepciones curl para algo así como tiempos de espera, pero ahora puede obtener todos los códigos de estado fácilmente:
$request = $client->get($uri);
$response = $request->send();
$statuscode = $response->getStatusCode();
Para verificar, si tiene un código válido, puede usar algo como esto:
if ($statuscode > 300) {
// Do some error handling
}
... o manejar mejor todos los códigos esperados:
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...");
}
Para Guzzle 5.3
$client = new /GuzzleHttp/Client([''defaults'' => [ ''exceptions'' => false ]] );
Gracias a @mika
Para Guzzle 6
$client = new /GuzzleHttp/Client([''http_errors'' => false]);
En mi caso, estaba lanzando Exception
en un archivo de espacio de nombres, por lo que php intentó capturar My/Namespace/Exception
por lo que no detectó ninguna excepción.
Vale la pena verificar si la catch (Exception $e)
está encontrando la clase de Exception
correcta.
Simplemente intente catch (/Exception $e)
(with that /
there) y vea si funciona.
Necesita agregar un parámetro extra con http_errors => false
$request = $client->get($url, [''http_errors'' => false]);
Para detectar los errores de Guzzle puedes hacer algo como esto:
try {
$response = $client->get(''/not_found.xml'')->send();
} catch (Guzzle/Http/Exception/BadResponseException $e) {
echo ''Uh oh! '' . $e->getMessage();
}
... pero, para poder "registrar" o "volver a enviar" su solicitud, pruebe algo como esto:
// 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();
}
});
... o si desea "detener la propagación de eventos" puede anular el detector de eventos (con una prioridad mayor que -255) y simplemente detener la propagación de eventos.
$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();
}
});
esa es una buena idea para evitar errores como:
request.CRITICAL: Uncaught PHP Exception Guzzle/Http/Exception/ClientErrorResponseException: "Client error response
en tu aplicación.
Pregunta anterior, pero Guzzle agrega la respuesta dentro del objeto de excepción. Así que un simple try-catch en GuzzleHttp/Exception/ClientException
y luego usar getResponse
en esa excepción para ver qué error de 400 niveles y continuar desde allí.
Si la Excepción se lanza en ese bloque de try
, en el peor de los casos, la Exception
debe detectar cualquier cosa no detectada.
Considere que la primera parte de la prueba es arrojar la excepción y envolverla en el bloque try
también.
GuzzleHttp/Exception/BadResponseException
como lo sugiere @dado. Pero un día recibí GuzzleHttp/Exception/ConnectException
cuando DNS para el dominio no estaba disponible. Así que mi sugerencia es - atrapar GuzzleHttp/Exception/ConnectException
para estar seguro acerca de los errores de DNS también.
try {
} catch (GuzzleHttp/Subscriber/HttpError $e) {
//catches all 4xx and 5xx status codes
}