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->getMessagedevuelve 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 (
ClientErrorResponseExceptionpara errores 4xx) y llamar a sugetResponse()método para obtener el objeto de respuesta, luego invocargetBody()eso:Pasar
truea lagetBodyfunció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\ClientExceptionpara errores de 400 nivelesGuzzleHttp\Exception\ServerExceptionpara errores de 500 nivelesGuzzleHttp\Exception\BadResponseExceptionpara 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' => falseopció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\RequestExceptionun400có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
JsonResponseuna clase de Guzzle?JsonResponseviene 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
catchcláusula, captamos la clase de excepción de raíz PHP de la cadena de herencia a\Exceptionmedida 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\RequestExceptioncomo la excepción raíz para Guzzle).Por lo tanto, debe atrapar,
\Exceptionpero 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$responselos métodos de Guzzle .Si llama a Guzzle directamente usted mismo, puede atrapar
GuzzleHttp\Exception\RequestExceptiono cualquier otro mencionado en sus documentos de excepciones con respecto a las condiciones de su caso de uso.fuente
$responseobjeto cuando maneje excepciones a menos que haya marcado$e->hasResponse(), de lo contrario$responsepuede sernully cualquier llamada a método causará un error fatal.$e->hasResponseal 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\RequestExceptionlugar deExceptionevitar esto.Si se pone
'http_errors' => falseen 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