Ich versuche, Ausnahmen von einer Reihe von Tests abzufangen, die ich auf einer von mir entwickelten API ausführe, und verwende Guzzle, um die API-Methoden zu verwenden. Ich habe die Tests in einen Try / Catch-Block eingeschlossen, aber es werden immer noch unbehandelte Ausnahmefehler ausgegeben. Das Hinzufügen eines Ereignis-Listeners, wie in den Dokumenten beschrieben, scheint nichts zu bewirken. Ich muss in der Lage sein, die Antworten mit HTTP-Codes von 500, 401, 400 abzurufen. Tatsächlich muss alles, was nicht 200 ist, da das System den am besten geeigneten Code basierend auf dem Ergebnis des Aufrufs festlegt, wenn es nicht funktioniert hat .
Aktuelles Codebeispiel
foreach($tests as $test){
$client = new Client($api_url);
$client->getEventDispatcher()->addListener('request.error', function(Event $event) {
if ($event['response']->getStatusCode() == 401) {
$newResponse = new Response($event['response']->getStatusCode());
$event['response'] = $newResponse;
$event->stopPropagation();
}
});
try {
$client->setDefaultOption('query', $query_string);
$request = $client->get($api_version . $test['method'], array(), isset($test['query'])?$test['query']:array());
// Do something with Guzzle.
$response = $request->send();
displayTest($request, $response);
}
catch (Guzzle\Http\Exception\ClientErrorResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch (Guzzle\Http\Exception\ServerErrorResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch (Guzzle\Http\Exception\BadResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch( Exception $e){
echo "AGH!";
}
unset($client);
$client=null;
}
Selbst mit dem spezifischen catch-Block für den ausgelösten Ausnahmetyp komme ich immer noch zurück
Fatal error: Uncaught exception 'Guzzle\Http\Exception\ClientErrorResponseException' with message 'Client error response [status code] 401 [reason phrase] Unauthorized [url]
und alle Ausführung auf der Seite stoppt, wie Sie es erwarten würden. Durch das Hinzufügen des BadResponseException-Catch konnte ich 404s korrekt abfangen, dies scheint jedoch bei 500 oder 401 Antworten nicht zu funktionieren. Kann mir jemand vorschlagen, wo ich falsch liege?
quelle
use
müssen Sie ihnen möglicherweise ein Präfix voranstellen, um die FQ-Klasse explizit anzugeben , es sei denn, Sie geben die Ausnahmen an. So zum Beispiel '\ Guzzle \ Http \ Exception \ ClientErrorResponseException'Antworten:
Wenn die Ausnahme in diesem
try
Block ausgelöst wird, ist dies im schlimmsten Fall der FallException
alles Ungefangene abfangen.Bedenken Sie, dass der erste Teil des Tests die Ausnahme auslöst und diese ebenfalls in den
try
Block einschließt.quelle
Abhängig von Ihrem Projekt kann es erforderlich sein, Ausnahmen für die Verzehrung zu deaktivieren. Manchmal verbieten Codierungsregeln Ausnahmen für die Flusskontrolle. Sie können Ausnahmen für Guzzle 3 folgendermaßen deaktivieren :
$client = new \Guzzle\Http\Client($httpBase, array( 'request.options' => array( 'exceptions' => false, ) ));
Dadurch werden Curl-Ausnahmen für Zeitüberschreitungen nicht deaktiviert, aber jetzt können Sie jeden Statuscode einfach abrufen:
Um zu überprüfen, ob Sie einen gültigen Code haben, können Sie Folgendes verwenden:
if ($statuscode > 300) { // Do some error handling }
... oder besser mit allen erwarteten Codes umgehen:
if (200 === $statuscode) { // Do something } elseif (304 === $statuscode) { // Nothing to do } elseif (404 === $statuscode) { // Clean up DB or something like this } else { throw new MyException("Invalid response from api..."); }
Für Guzzle 5.3
$client = new \GuzzleHttp\Client(['defaults' => [ 'exceptions' => false ]] );
Danke an @mika
Für Guzzle 6
$client = new \GuzzleHttp\Client(['http_errors' => false]);
quelle
break
;-) Aber sicher, es wäre eine gute Lösung, wenn Sie mehrere Statuscodes haben, die Sie auf die gleiche Weise behandeln müssen. Ich bevorzugeif
, weil Schalter nur unterstützt==
.request.options
. Mein Problem wurde behoben und ich konnte es nicht richtig nachschlagen. :)Um Guzzle-Fehler abzufangen, können Sie Folgendes tun:
try { $response = $client->get('/not_found.xml')->send(); } catch (Guzzle\Http\Exception\BadResponseException $e) { echo 'Uh oh! ' . $e->getMessage(); }
... aber um Ihre Anfrage "protokollieren" oder "erneut senden" zu können, versuchen Sie Folgendes:
// Add custom error handling to any request created by this client $client->getEventDispatcher()->addListener( 'request.error', function(Event $event) { //write log here ... if ($event['response']->getStatusCode() == 401) { // create new token and resend your request... $newRequest = $event['request']->clone(); $newRequest->setHeader('X-Auth-Header', MyApplication::getNewAuthToken()); $newResponse = $newRequest->send(); // Set the response object of the request without firing more events $event['response'] = $newResponse; // You can also change the response and fire the normal chain of // events by calling $event['request']->setResponse($newResponse); // Stop other events from firing when you override 401 responses $event->stopPropagation(); } });
... oder wenn Sie die Ereignisausbreitung stoppen möchten, können Sie den Ereignis-Listener (mit einer höheren Priorität als -255) überschreiben und einfach die Ereignisausbreitung stoppen.
$client->getEventDispatcher()->addListener('request.error', function(Event $event) { if ($event['response']->getStatusCode() != 200) { // Stop other events from firing when you get stytus-code != 200 $event->stopPropagation(); } });
Das ist eine gute Idee, um Fehler wie: zu vermeiden.
request.CRITICAL: Uncaught PHP Exception Guzzle\Http\Exception\ClientErrorResponseException: "Client error response
in Ihrer Bewerbung.
quelle
In meinem Fall habe ich
Exception
auf eine Namespace-Datei geworfen , also hat PHP versucht zu fangen,My\Namespace\Exception
also überhaupt keine Ausnahmen.Es lohnt sich zu prüfen, ob
catch (Exception $e)
die richtigeException
Klasse gefunden wird.Versuchen Sie es einfach
catch (\Exception $e)
(damit\
) und sehen Sie, ob es funktioniert.quelle
Sie müssen einen zusätzlichen Parameter mit http_errors => false hinzufügen
$request = $client->get($url, ['http_errors' => false]);
quelle
Alte Frage, aber Guzzle fügt die Antwort innerhalb des Ausnahmeobjekts hinzu. Also ein einfacher Versuch , diese Ausnahme zu erkennen
GuzzleHttp\Exception\ClientException
und dann zu verwendengetResponse
, um zu sehen, welcher 400-Level-Fehler vorliegt, und von dort aus fortzufahren.quelle
Ich habe
GuzzleHttp\Exception\BadResponseException
gefangen , wie @dado vorschlägt. Aber eines Tages bekam ich,GuzzleHttp\Exception\ConnectException
als DNS für Domain nicht verfügbar war. Mein Vorschlag ist also - fangen SieGuzzleHttp\Exception\ConnectException
an, auch bei DNS-Fehlern sicher zu sein.quelle
GuzzleHttp\Exception\RequestException
welche die Eltern vonConnectException
,BadResponseException
undTooManyRedirectsException
.Ich möchte die Antwort für die Ausnahmebehandlung in Psr-7 Guzzle, Guzzle7 und HTTPClient aktualisieren (ausdrucksstarke, minimale API rund um den von laravel bereitgestellten Guzzle-HTTP-Client).
Guzzle7 (das gleiche gilt auch für Guzzle 6)
Mit RequestException fängt RequestException alle Ausnahmen ab, die beim Übertragen von Anforderungen ausgelöst werden können.
try{ $client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Bearer ' . $token]]); $guzzleResponse = $client->get('/foobar'); // or can use // $guzzleResponse = $client->request('GET', '/foobar') if ($guzzleResponse->getStatusCode() == 200) { $response = json_decode($guzzleResponse->getBody(),true); //perform your action with $response } } catch(\GuzzleHttp\Exception\RequestException $e){ // you can catch here 400 response errors and 500 response errors // You can either use logs here use Illuminate\Support\Facades\Log; $error['error'] = $e->getMessage(); $error['request'] = $e->getRequest(); if($e->hasResponse()){ if ($e->getResponse()->getStatusCode() == '400'){ $error['response'] = $e->getResponse(); } } Log::error('Error occurred in get request.', ['error' => $error]); }catch(Exception $e){ //other errors }
Psr7 Guzzle
use GuzzleHttp\Psr7; use GuzzleHttp\Exception\RequestException; try { $client->request('GET', '/foo'); } catch (RequestException $e) { $error['error'] = $e->getMessage(); $error['request'] = Psr7\Message::toString($e->getRequest()); if ($e->hasResponse()) { $error['response'] = Psr7\Message::toString($e->getResponse()); } Log::error('Error occurred in get request.', ['error' => $error]); }
Für HTTPClient
use Illuminate\Support\Facades\Http; try{ $response = Http::get('http://api.foo.com'); if($response->successful()){ $reply = $response->json(); } if($response->failed()){ if($response->clientError()){ //catch all 400 exceptions Log::debug('client Error occurred in get request.'); $response->throw(); } if($response->serverError()){ //catch all 500 exceptions Log::debug('server Error occurred in get request.'); $response->throw(); } } }catch(Exception $e){ //catch the exception here }
quelle