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 de la API. Tengo las pruebas envueltas en un bloque try / catch pero todavía arroja errores de excepción no manejados. 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 según el 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 de captura específico para el tipo de excepción lanzada, todavía estoy recuperando
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 404 correctamente, pero esto no parece funcionar para respuestas 500 o 401. ¿Alguien puede sugerir dónde me estoy equivocando, por favor?
fuente
use
usando las excepciones, es posible que deba anteponerlas con `` para indicar explícitamente la clase FQ. Entonces, por ejemplo, '\ Guzzle \ Http \ Exception \ ClientErrorResponseException'Respuestas:
Si la excepción se lanza en ese
try
bloque, en el peor de los casos,Exception
debería detectar cualquier cosa que no se haya detectado.Considere que la primera parte de la prueba es lanzar la excepción y envolver eso en el
try
bloque también.fuente
Dependiendo de su proyecto, puede ser necesario deshabilitar las excepciones para tragar. A veces, las reglas de codificación no permiten excepciones para el control de flujo. Puede deshabilitar las excepciones para Guzzle 3 de esta manera:
$client = new \Guzzle\Http\Client($httpBase, array( 'request.options' => array( 'exceptions' => false, ) ));
Esto no deshabilita las excepciones de curl para algo 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 mejor maneja 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]);
fuente
break
;-) Pero claro, sería una buena solución si tiene varios códigos de estado que tiene que manejar de la misma manera. Prefieroif
, porque el interruptor solo admite==
.request.options
. Resolvió mi problema y me salvó de buscarlo correctamente. :)Para detectar errores de Guzzle, puede 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 "reenviar" su solicitud, intente 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 superior a -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 de trago como:
request.CRITICAL: Uncaught PHP Exception Guzzle\Http\Exception\ClientErrorResponseException: "Client error response
en su aplicación.
fuente
En mi caso, estaba lanzando
Exception
un archivo con espacio de nombres, por lo que php trató de detectar,My\Namespace\Exception
por lo tanto, no detectó ninguna excepción.Vale la pena comprobar si
catch (Exception $e)
está encontrando laException
clase adecuada .Intente
catch (\Exception $e)
(con eso\
allí) y vea si funciona.fuente
Necesita agregar un parámetro adicional con http_errors => false
$request = $client->get($url, ['http_errors' => false]);
fuente
Pregunta anterior, pero Guzzle agrega la respuesta dentro del objeto de excepción. Entonces, un simple intento
GuzzleHttp\Exception\ClientException
y luego usargetResponse
esa excepción para ver qué error de nivel 400 y continuar desde allí.fuente
Estaba atrapando
GuzzleHttp\Exception\BadResponseException
como sugiere @dado. Pero un día me llegóGuzzleHttp\Exception\ConnectException
cuando el DNS para el dominio no estaba disponible. Así que mi sugerencia es: también,GuzzleHttp\Exception\ConnectException
tenga cuidado con los errores de DNS.fuente
GuzzleHttp\Exception\RequestException
cuál es el padre deConnectException
,BadResponseException
yTooManyRedirectsException
.Quiero actualizar la respuesta para el manejo de excepciones en Psr-7 Guzzle, Guzzle7 y HTTPClient (API expresiva y mínima alrededor del cliente HTTP Guzzle proporcionado por laravel).
Guzzle7 (lo mismo funciona para Guzzle 6 también)
Con RequestException , RequestException detecta cualquier excepción que se pueda lanzar mientras se transfieren solicitudes.
try{ $client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Bearer ' . $token]]); $guzzleResponse = $client->get('/foobar'); // or can use // $guzzleResponse = $client->request('GET', '/foobar') if ($guzzleResponse->getStatusCode() == 200) { $response = json_decode($guzzleResponse->getBody(),true); //perform your action with $response } } catch(\GuzzleHttp\Exception\RequestException $e){ // you can catch here 400 response errors and 500 response errors // You can either use logs here use Illuminate\Support\Facades\Log; $error['error'] = $e->getMessage(); $error['request'] = $e->getRequest(); if($e->hasResponse()){ if ($e->getResponse()->getStatusCode() == '400'){ $error['response'] = $e->getResponse(); } } Log::error('Error occurred in get request.', ['error' => $error]); }catch(Exception $e){ //other errors }
Psr7 Guzzle
use GuzzleHttp\Psr7; use GuzzleHttp\Exception\RequestException; try { $client->request('GET', '/foo'); } catch (RequestException $e) { $error['error'] = $e->getMessage(); $error['request'] = Psr7\Message::toString($e->getRequest()); if ($e->hasResponse()) { $error['response'] = Psr7\Message::toString($e->getResponse()); } Log::error('Error occurred in get request.', ['error' => $error]); }
Para HTTPClient
use Illuminate\Support\Facades\Http; try{ $response = Http::get('http://api.foo.com'); if($response->successful()){ $reply = $response->json(); } if($response->failed()){ if($response->clientError()){ //catch all 400 exceptions Log::debug('client Error occurred in get request.'); $response->throw(); } if($response->serverError()){ //catch all 500 exceptions Log::debug('server Error occurred in get request.'); $response->throw(); } } }catch(Exception $e){ //catch the exception here }
fuente