Je souhaite gérer les erreurs de Guzzle lorsque le serveur renvoie des codes d’état 4xx et 5xx. Je fais une demande comme celle-ci:
$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
renvoie les informations de code mais pas le corps de la réponse HTTP. Comment puis-je obtenir le corps de réponse?
Per les docs , vous pouvez intercepter le type d'exception approprié (ClientErrorResponseException
pour les erreurs 4xx) et appeler sa méthode getResponse()
pour obtenir l'objet de réponse, puis appeler getBody()
à ce sujet:
use Guzzle\Http\Exception\ClientErrorResponseException;
...
try {
$response = $request->send();
} catch (ClientErrorResponseException $exception) {
$responseBody = $exception->getResponse()->getBody(true);
}
Si vous transmettez true
à la fonction getBody
, vous indiquez que vous souhaitez obtenir le corps de la réponse sous forme de chaîne. Sinon, vous l'obtiendrez en tant qu'instance de la classe Guzzle\Http\EntityBody
.
Pour la documentation , les types d'exception que vous devrez peut-être intercepter sont les suivants:
GuzzleHttp\Exception\ClientException
pour les erreurs de niveau 400GuzzleHttp\Exception\ServerException
pour les erreurs de niveau 500GuzzleHttp\Exception\BadResponseException
pour les deux (c'est leur super-classe)Le code permettant de gérer de telles erreurs ressemble donc maintenant à ceci:
$client = new GuzzleHttp\Client;
try {
$client->get('http://google.com/nosuchpage');
}
catch (GuzzleHttp\Exception\ClientException $e) {
$response = $e->getResponse();
$responseBodyAsString = $response->getBody()->getContents();
}
Bien que les réponses ci-dessus soient bonnes, elles ne résoudront pas les erreurs de réseau. Comme Mark l'a mentionné, BadResponseException est simplement une super classe pour ClientException et ServerException. Mais RequestException est également une super classe de BadRequestException. Cela interceptera non seulement les erreurs 400 et 500, mais aussi les erreurs de réseau. Supposons donc que vous demandiez la page ci-dessous, mais que votre réseau est en train de s’écrouler et que votre piège attend une exception BadResponseException. Eh bien votre application va jeter une erreur.
Dans ce cas, il est préférable d'attendre RequestException et de rechercher une réponse.
try {
$client->get('http://123123123.com')
} catch (RequestException $e) {
// If there are network errors, we need to ensure the application doesn't crash.
// if $e->hasResponse is not null we can attempt to get the message
// Otherwise, we'll just pass a network unavailable message.
if ($e->hasResponse()) {
$exception = (string) $e->getResponse()->getBody();
$exception = json_decode($exception);
return new JsonResponse($exception, $e->getCode());
} else {
return new JsonResponse($e->getMessage(), 503);
}
}
En 2019, voici ce que j'ai élaboré à partir des réponses ci-dessus et Guzzle docs pour gérer l'exception, obtenez le corps de la réponse, le code d'état, le message et d'autres éléments de réponse parfois précieux.
try {
/**
* We use Guzzle to make an HTTP request somewhere in the
* following theMethodMayThrowException().
*/
$result = theMethodMayThorwException();
} catch (\Exception $e) {
/**
* Here we actually catch the instance of GuzzleHttp\Psr7\Response
* (find it in ./vendor/guzzlehttp/psr7/src/Response.php) with all
* its own and its 'Message' trait's methods. See more explanations below.
*
* So you can have: HTTP status code, message, headers and body.
*/
$response = $e->getResponse();
var_dump($response->getStatusCode()); // HTTP status code
var_dump($response->getReasonPhrase()); // Message
var_dump((string) $response->getBody()); // Body
var_dump($response->getHeaders()); // Headers array
var_dump($response->hasHeader('Content-Type')); // Is the header presented
var_dump($response->getHeader('Content-Type')[0]); // Concrete header value
}
// process $result etc. ...
Voila. Vous obtenez les informations de la réponse dans des éléments bien séparés.
Notes annexes:
Avec la clause catch
, nous interceptons la chaîne d'héritage PHP, la classe d'exceptions racine \Exception
, car les exceptions personnalisées Guzzle l'étendent.
Cette approche peut être utile dans les cas où Guzzle est utilisé sous le capot, comme dans Laravel ou AWS API PHP SDK, de sorte que vous ne pouvez pas intercepter la véritable exception Guzzle.
Dans ce cas, la classe d'exception peut ne pas être celle mentionnée dans la documentation Guzzle (par exemple, GuzzleHttp\Exception\RequestException
en tant qu'exception racine pour Guzzle).
Donc, vous devez attraper \Exception
à la place, mais gardez à l'esprit qu'il s'agit toujours de l'instance de classe d'exception Guzzle.
Bien utiliser avec précaution. Ces wrappers peuvent rendre les méthodes authentiques de l'objet Guzzle $e->getResponse()
non disponibles. Dans ce cas, vous devrez consulter le code source des exceptions réelles du wrapper et savoir comment obtenir l'état, le message, etc. au lieu d'utiliser les méthodes de Guzzle $response
.
Si vous appelez directement Guzzle vous-même, vous pouvez intercepter GuzzleHttp\Exception\RequestException
ou tout autre élément mentionné dans leur document relatif aux exceptions en ce qui concerne les conditions de votre cas d'utilisation.