wake-up-neo.net

Ausnahmen von Guzzle abfangen

Ich versuche, Ausnahmen von einer Reihe von Tests abzufangen, die ich auf einer API ausführe, die ich entwickle, und ich verwende Guzzle, um die API-Methoden zu nutzen. Ich habe die Tests in einen Try/Catch-Block verpackt, aber es werden immer noch nicht behandelte 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 abzurufen, die HTTP-Codes von 500, 401, 400 haben, und zwar 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 Typ der geworfenen Ausnahme 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]

die Ausführung der Seite wird wie erwartet angehalten. Durch das Hinzufügen des BadResponseException-Catch konnte ich 404-Werte korrekt abfangen, aber dies scheint bei 500 oder 401-Antworten nicht zu funktionieren. Kann jemand vorschlagen, wo ich bitte falsch gehe.

65
Eric

Wenn die Ausnahmebedingung in diesem try Block ausgelöst wird, sollte im schlimmsten Fall das Szenario Exception alles abfangen, was nicht abgefangen wurde.

Bedenken Sie, dass der erste Teil des Tests die Exception auslöst, und binden Sie diese ebenfalls in den Block try ein.

13
user2584140

Abhängig von Ihrem Projekt kann es erforderlich sein, Ausnahmen für guzzle zu deaktivieren. Manchmal erlauben Codierungsregeln keine Ausnahmen für die Flusskontrolle. Sie können Ausnahmen deaktivieren für Guzzle wie folgt:

$client = new \Guzzle\Http\Client($httpBase, array(
  'request.options' => array(
     'exceptions' => false,
   )
));

Dies deaktiviert keine Curl-Ausnahmen für Zeitüberschreitungen. Jetzt können Sie jeden Statuscode einfach abrufen:

$request = $client->get($uri);
$response = $request->send();
$statuscode = $response->getStatusCode();

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 Düse 5.

$client = new \GuzzleHttp\Client(['defaults' => [ 'exceptions' => false ]] );

Vielen Dank an @mika

für Düse 6

$client = new \GuzzleHttp\Client(['http_errors' => false]);
113
Trendfischer

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 zu "protokollieren" oder "erneut zu senden", 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 Ereignisübertragung stoppen möchten, können Sie den Ereignis-Listener (mit einer höheren Priorität als -255) überschreiben und die Ereignisübertragung einfach 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 Sprühfehler wie die folgenden zu vermeiden:

request.CRITICAL: Uncaught PHP Exception Guzzle\Http\Exception\ClientErrorResponseException: "Client error response

in Ihrer Bewerbung.

45
Dado

In meinem Fall habe ich Exception auf eine namenspaced-Datei geworfen, also hat PHP versucht, My\Namespace\Exception Abzufangen, also überhaupt keine Ausnahmen abzufangen.

Es lohnt sich zu prüfen, ob catch (Exception $e) die richtige Exception Klasse findet.

Probieren Sie einfach catch (\Exception $e) (mit diesem \ Dort) und sehen Sie, ob es funktioniert.

29
dmmd

Sie müssen einen zusätzlichen Parameter mit http_errors => false hinzufügen

$request = $client->get($url, ['http_errors' => false]);
10
andr3s2

Alte Frage, aber Guzzle fügt die Antwort im Ausnahmeobjekt hinzu. Also ein einfacher Anlaufpunkt für GuzzleHttp\Exception\ClientException und verwenden Sie dann getResponse für diese Ausnahme, um festzustellen, welcher Fehler mit 400 Ebenen vorliegt, und fahren Sie von dort fort.

5
Carson Reinke

Ich fing GuzzleHttp\Exception\BadResponseException wie @dado vorschlägt. Aber eines Tages bekam ich GuzzleHttp\Exception\ConnectException wenn DNS für Domain nicht verfügbar war. Also mein Vorschlag ist - Fang GuzzleHttp\Exception\ConnectException um auch bei DNS-Fehlern auf Nummer sicher zu gehen.

2
Ivan Yarych