Ich möchte Fehler von Guzzle behandeln, wenn der Server 4xx- und 5xx-Statuscodes zurückgibt. Ich mache eine Anfrage wie folgt:
$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
Gibt Code-Informationen zurück, jedoch nicht den Text der HTTP-Antwort. Wie kann ich den Antworttext erhalten?
Antworten:
Guzzle 3.x.
Gemäß den Dokumenten können Sie den entsprechenden Ausnahmetyp (
ClientErrorResponseException
für 4xx-Fehler) abfangen und seinegetResponse()
Methode aufrufen , um das Antwortobjekt abzurufen, und dann Folgendes aufrufengetBody()
:Wenn Sie
true
an diegetBody
Funktion übergeben, wird angezeigt, dass Sie den Antworttext als Zeichenfolge erhalten möchten. Andernfalls erhalten Sie es als Instanz der KlasseGuzzle\Http\EntityBody
.quelle
Guzzle 6.x.
Gemäß den Dokumenten müssen Sie möglicherweise folgende Ausnahmetypen abfangen:
GuzzleHttp\Exception\ClientException
für 400-Level-FehlerGuzzleHttp\Exception\ServerException
für 500-Level-FehlerGuzzleHttp\Exception\BadResponseException
für beide (es ist ihre Superklasse)Der Code zur Behandlung solcher Fehler sieht nun ungefähr so aus:
quelle
$response->getBody()->getContents()
würde eine leere Zeichenfolge zurückgeben. Ich bin dann in den Dokumenten darauf gestoßen :\GuzzleHttp\Psr7\str($e->getResponse())
Wenn ich die Antwort als Psr7-String umwandelte, erhielt ich eine gut formatierte und vollständige Fehlermeldung.Psr7\str()
unterschiedliche Ergebnisse haben würde zu->getContents()
. Haben Sie ein minimales Beispiel, das dies demonstriert, damit ich das verstehen und vielleicht diese Antwort aktualisieren kann?'http_errors' => false
Option in der Guzzle-Anforderung übergeben werden kann, wodurch das Auslösen von Ausnahmen deaktiviert wird. Sie können dann den Body$response->getBody()
unabhängig vom Statuscode abrufen und den Statuscode bei Bedarf mit testen$response->getStatusCode()
.$response->getBody()->getContents()
mir in einem Fall eine leere Zeichenfolge gibt, verstehe ich nicht warum. Aber using\GuzzleHttp\Psr7\str()
gibt die gesamte HTTP-Antwort als Zeichenfolge zurück, und ich würde nur den HTTP-Body verwenden. Wie in der Dokumentation erwähnt , kann der Körper verwendet werden, indem er in einen String umgewandelt wird.$stringBody = (string) $clientException->getResponse()->getBody();
\GuzzleHttp\Exception\RequestException
stattdessen einen bekam, der einen400
Statuscode zurückgab . try {$ request-> api ('POST', 'endpoint.json'); } catch (RequestException $ e) {print_r ($ e-> getResponse () -> getBody () -> getContents ()); }Obwohl die obigen Antworten gut sind, werden sie keine Netzwerkfehler abfangen. Wie Mark erwähnt hat, ist BadResponseException nur eine Superklasse für ClientException und ServerException. RequestException ist aber auch eine Superklasse von BadResponseException. RequestException wird nicht nur für 400 und 500 Fehler ausgelöst, sondern auch für Netzwerkfehler und unendliche Weiterleitungen. Angenommen, Sie fordern die folgende Seite an, aber Ihr Netzwerk spielt gerade und Ihr Fang erwartet nur eine BadResponseException. Nun, Ihre Anwendung wird einen Fehler auslösen.
In diesem Fall ist es besser, RequestException zu erwarten und nach einer Antwort zu suchen.
quelle
JsonResponse
eine Klasse von Guzzle?JsonResponse
kommt von SymfonyAb 2019 habe ich aus den obigen Antworten und den Guzzle-Dokumenten Folgendes herausgearbeitet , um die Ausnahme zu behandeln, den Antworttext, den Statuscode, die Nachricht und die anderen manchmal wertvollen Antwortelemente abzurufen.
Voila. Sie erhalten die Informationen der Antwort in bequem getrennten Elementen.
Randnotizen:
Mit
catch
Klausel fangen wir die PHP-Root-Ausnahmeklasse der Vererbungskette\Exception
ab, wenn benutzerdefinierte Guzzle-Ausnahmen sie erweitern.Dieser Ansatz kann für Anwendungsfälle nützlich sein, in denen Guzzle wie in Laravel oder AWS API PHP SDK unter der Haube verwendet wird, sodass Sie die echte Guzzle-Ausnahme nicht abfangen können.
In diesem Fall ist die Ausnahmeklasse möglicherweise nicht die in den Guzzle-Dokumenten erwähnte (z
GuzzleHttp\Exception\RequestException
als Root-Ausnahme für Guzzle).Sie müssen also
\Exception
stattdessen fangen, aber denken Sie daran, dass es sich immer noch um die Guzzle-Ausnahmeklasseninstanz handelt.Obwohl mit Vorsicht verwenden. Diese Wrapper machen möglicherweise
$e->getResponse()
die echten Methoden des Guzzle- Objekts nicht verfügbar. In diesem Fall müssen Sie sich den tatsächlichen Ausnahmequellcode des Wrappers ansehen und herausfinden, wie Sie Status, Nachricht usw. abrufen können$response
, anstatt die Methoden von Guzzle zu verwenden.Wenn Sie Guzzle direkt selbst anrufen, können Sie
GuzzleHttp\Exception\RequestException
oder andere in den Ausnahmedokumenten erwähnte Dokumente in Bezug auf Ihre Anwendungsfallbedingungen abfangen .quelle
$response
bei der Behandlung von Ausnahmen keine Methoden für Ihr Objekt aufrufen, es sei denn, Sie haben dies überprüft$e->hasResponse()
. Andernfalls$response
kann es vorkommen,null
dass Methodenaufrufe einen schwerwiegenden Fehler verursachen.$e->hasResponse
das Ergebnis auf, eine Methode, die es natürlich nicht für Nicht-Guzzle-Ausnahmen gibt. Wenn Sie also eine Nicht-Guzzle-Ausnahme von auslösentheMethodMayThrowException()
, wird dieser Code diese abfangen, versuchen, eine nicht vorhandene Methode aufzurufen, und aufgrund der nicht vorhandenen Methode abstürzen, wodurch die wahre Fehlerursache effektiv ausgeblendet wird. Vorzuziehen wäre zu fangen,GuzzleHttp\Exception\RequestException
anstatt diesException
zu vermeiden.Wenn
'http_errors' => false
Optionen für die Verzehranforderung eingegeben werden, wird die Ausnahme ausgelöst, während ein 4xx- oder 5xx-Fehler wie folgt angezeigt wird :$client->get(url, ['http_errors' => false])
. Dann analysieren Sie die Antwort, unabhängig davon, ob sie in Ordnung oder fehlerhaft ist. Weitere Informationen finden Sie in der Antwortquelle