Je voudrais gérer les erreurs de Guzzle lorsque le serveur renvoie les 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 la réponse?
Réponses:
Guzzle 3.x
Selon la documentation , vous pouvez attraper le type d'exception approprié (
ClientErrorResponseException
pour les erreurs 4xx) et appeler sagetResponse()
méthode pour obtenir l'objet de réponse, puis appelergetBody()
cela:Passer
true
à lagetBody
fonction indique que vous souhaitez obtenir le corps de la réponse sous forme de chaîne. Sinon, vous l'obtiendrez comme instance de classeGuzzle\Http\EntityBody
.la source
Guzzle 6.x
Selon la documentation , les types d'exceptions que vous devrez peut-être attraper sont:
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 superclasse)Le code pour gérer de telles erreurs ressemble donc maintenant à ceci:
la source
$response->getBody()->getContents()
je retournerais une chaîne vide. Je suis ensuite tombé sur ceci dans la documentation :\GuzzleHttp\Psr7\str($e->getResponse())
le cast de la réponse en tant que chaîne Psr7 m'a donné un message d'erreur bien formaté et complet.Psr7\str()
aurait des résultats différents à->getContents()
. Avez-vous un exemple minimal démontrant cela, qui pourrait me permettre de comprendre cela et peut-être de mettre à jour cette réponse?'http_errors' => false
option peut être passée dans la requête Guzzle qui désactive le lancement d'exceptions. Vous pouvez ensuite obtenir le corps avec$response->getBody()
quel que soit le code d'état, et vous pouvez tester le code d'état si nécessaire avec$response->getStatusCode()
.$response->getBody()->getContents()
me donne une chaîne vide dans un cas, je ne comprends pas pourquoi. Mais en utilisant\GuzzleHttp\Psr7\str()
renvoie toute la réponse HTTP sous forme de chaîne, et je ne voudrais que le corps HTTP. Comme indiqué dans la documentation , le corps peut être utilisé en le convertissant en chaîne.$stringBody = (string) $clientException->getResponse()->getBody();
\GuzzleHttp\Exception\RequestException
place un400
code de statut. essayez {$ request-> api ('POST', 'endpoint.json'); } catch (RequestException $ e) {print_r ($ e-> getResponse () -> getBody () -> getContents ()); }Bien que les réponses ci-dessus soient bonnes, elles ne détecteront pas les erreurs de réseau. Comme Mark l'a mentionné, BadResponseException n'est qu'une super classe pour ClientException et ServerException. Mais RequestException est également une super classe de BadResponseException. RequestException sera lancée non seulement pour les erreurs 400 et 500, mais aussi pour les erreurs réseau et les redirections infinies. Supposons que vous demandiez la page ci-dessous mais que votre réseau joue et que votre capture n'attend qu'une BadResponseException. Eh bien, votre application générera une erreur.
Il est préférable dans ce cas d'attendre RequestException et de rechercher une réponse.
la source
JsonResponse
une classe de Guzzle?JsonResponse
vient de SymfonyÀ partir de 2019, voici ce que j'ai élaboré à partir des réponses ci-dessus et de la documentation Guzzle pour gérer l'exception, obtenir le corps de la réponse, le code d'état, le message et les autres éléments de réponse parfois précieux.
Voila. Vous obtenez les informations de la réponse dans des éléments séparés de manière pratique.
Notes secondaires:
Avec la
catch
clause, nous capturons la classe d'exception racine PHP de la chaîne d'héritage\Exception
car les exceptions personnalisées Guzzle l'étendent.Cette approche peut être utile pour les cas d'utilisation 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 en
GuzzleHttp\Exception\RequestException
tant qu'exception racine pour Guzzle).Vous devez donc attraper à la
\Exception
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
$e->getResponse()
les méthodes authentiques des objets Guzzle non disponibles. Dans ce cas, vous devrez regarder le code source des exceptions du wrapper et découvrir comment obtenir le statut, le message, etc. au lieu d'utiliser$response
les méthodes de Guzzle .Si vous appelez Guzzle directement vous-même, vous pouvez attraper
GuzzleHttp\Exception\RequestException
ou tout autre élément mentionné dans leurs documents d'exceptions en ce qui concerne les conditions de votre cas d'utilisation.la source
$response
objet lors de la manipulation des exceptions , sauf si vous avez vérifié$e->hasResponse()
, sinon$response
peut - êtrenull
et des appels de méthode provoque une erreur fatale.$e->hasResponse
le résultat, une méthode qui, bien sûr, n'existe pas pour les exceptions non Guzzle. Donc, si vous générez une exception non-Guzzle à partir detheMethodMayThrowException()
, ce code l'attrapera, essaiera d'appeler une méthode inexistante et plantera à cause de la méthode inexistante, masquant ainsi la véritable cause de l'erreur. Il serait préférable d'attraperGuzzleHttp\Exception\RequestException
plutôt que d'Exception
éviter cela.si elles sont mises
'http_errors' => false
dans les options de demande Guzzle, il arrêterait exception throw tout get 4xx ou 5xx erreur, comme ceci:$client->get(url, ['http_errors' => false])
. alors vous analysez la réponse, peu importe que ce soit correct ou une erreur, ce serait dans la réponse pour plus d'informationsla source