Me gustaría manejar los errores de Guzzle cuando el servidor devuelve los códigos de estado 4xx y 5xx. Hago una solicitud como esta:
$client = $this->getGuzzleClient();
$request = $client->post($url, $headers, $value);
try {
$response = $request->send();
return $response->getBody();
} catch (\Exception $e) {
// How can I get the response body?
}
$e->getMessage
devuelve información del código pero no el cuerpo de la respuesta HTTP. ¿Cómo puedo obtener el cuerpo de respuesta?
Respuestas:
Guzzle 3.x
Según los documentos , puede capturar el tipo de excepción apropiado (
ClientErrorResponseException
para errores 4xx) y llamar a sugetResponse()
método para obtener el objeto de respuesta, luego invocargetBody()
eso:Pasar
true
a lagetBody
función indica que desea obtener el cuerpo de respuesta como una cadena. De lo contrario, lo obtendrá como instancia de claseGuzzle\Http\EntityBody
.fuente
Guzzle 6.x
Según los documentos , los tipos de excepción que puede necesitar atrapar son:
GuzzleHttp\Exception\ClientException
para errores de 400 nivelesGuzzleHttp\Exception\ServerException
para errores de 500 nivelesGuzzleHttp\Exception\BadResponseException
para ambos (es su superclase)El código para manejar tales errores ahora se ve así:
fuente
$response->getBody()->getContents()
devolvería una cadena vacía. Luego me topé con esto en los documentos :\GuzzleHttp\Psr7\str($e->getResponse())
al enviar la respuesta como una cadena Psr7, recibí un mensaje de error bien formateado y completo.Psr7\str()
tendrían resultados diferentes a->getContents()
. ¿Tiene un ejemplo mínimo que demuestre esto, que me permita entender esto y quizás actualizar esta respuesta?'http_errors' => false
opción se puede pasar en la solicitud Guzzle que deshabilita las excepciones de lanzamiento. Luego puede obtener el cuerpo$response->getBody()
sin importar cuál sea el código de estado, y puede probar el código de estado si es necesario con$response->getStatusCode()
.$response->getBody()->getContents()
me da una cadena vacía en un caso, no entiendo por qué. Pero el uso\GuzzleHttp\Psr7\str()
devuelve toda la respuesta HTTP como una cadena, y solo haría el cuerpo HTTP. Como se dice en la documentación , el cuerpo se puede usar al convertirlo en una cadena.$stringBody = (string) $clientException->getResponse()->getBody();
\GuzzleHttp\Exception\RequestException
un400
código que me devolvió el estado. pruebe {$ request-> api ('POST', 'endpoint.json'); } catch (RequestException $ e) {print_r ($ e-> getResponse () -> getBody () -> getContents ()); }Si bien las respuestas anteriores son buenas, no detectarán errores de red. Como Mark mencionó, BadResponseException es solo una superclase para ClientException y ServerException. Pero RequestException también es una superclase de BadResponseException. RequestException se generará no solo por errores de 400 y 500, sino también por errores de red y redirecciones infinitas. Digamos que solicita la página a continuación, pero su red se está reproduciendo y su captura solo espera una BadResponseException. Bueno, tu aplicación arrojará un error.
En este caso, es mejor esperar RequestException y buscar una respuesta.
fuente
JsonResponse
una clase de Guzzle?JsonResponse
viene de SymfonyA partir de 2019, esto es lo que elaboré a partir de las respuestas anteriores y los documentos de Guzzle para manejar la excepción, obtener el cuerpo de respuesta, el código de estado, el mensaje y los otros elementos de respuesta a veces valiosos.
Voila Obtiene la información de la respuesta en elementos convenientemente separados.
Notas al margen:
Con la
catch
cláusula, captamos la clase de excepción de raíz PHP de la cadena de herencia a\Exception
medida que las excepciones personalizadas de Guzzle la extienden.Este enfoque puede ser útil para casos de uso en los que Guzzle se usa debajo del capó, como en Laravel o AWS API PHP SDK, por lo que no puede detectar la excepción genuina de Guzzle.
En este caso, la clase de excepción puede no ser la mencionada en los documentos de Guzzle (por ejemplo,
GuzzleHttp\Exception\RequestException
como la excepción raíz para Guzzle).Por lo tanto, debe atrapar,
\Exception
pero tenga en cuenta que todavía es la instancia de la clase de excepción Guzzle.Aunque usar con cuidado. Esas envolturas pueden hacer Guzzle
$e->getResponse()
que los métodos genuinos del objeto no estén disponibles. En este caso, tendrá que mirar el código fuente de excepción real del contenedor y descubrir cómo obtener el estado, el mensaje, etc. en lugar de utilizar$response
los métodos de Guzzle .Si llama a Guzzle directamente usted mismo, puede atrapar
GuzzleHttp\Exception\RequestException
o cualquier otro mencionado en sus documentos de excepciones con respecto a las condiciones de su caso de uso.fuente
$response
objeto cuando maneje excepciones a menos que haya marcado$e->hasResponse()
, de lo contrario$response
puede sernull
y cualquier llamada a método causará un error fatal.$e->hasResponse
al resultado, un método que, por supuesto, no existe para las excepciones que no son de Guzzle. Entonces, si genera una excepción que no sea de GuzzletheMethodMayThrowException()
, este código lo detectará, intentará llamar a un método inexistente y se bloqueará debido al método inexistente, ocultando efectivamente la verdadera causa del error. Sería preferible atrapar enGuzzleHttp\Exception\RequestException
lugar deException
evitar esto.Si se pone
'http_errors' => false
en las opciones de solicitud Guzzle, entonces sería dejar de excepción tiro mientras get 4xx o 5xx de error, así:$client->get(url, ['http_errors' => false])
. luego analiza la respuesta, no importa si está bien o es un error, estaría en la respuesta para obtener más informaciónfuente