从 Guzzle 捕获异常

2022-08-30 07:42:11

我正在尝试从我正在开发的API上运行的一组测试中捕获异常,并且我正在使用Guzzle来使用API方法。我已经将测试包装在try/catch块中,但它仍然抛出未处理的异常错误。按照其文档中所述添加事件侦听器似乎没有任何作用。我需要能够检索HTTP代码为500,401,400的响应,实际上任何不是200的响应,因为如果它不起作用,系统将根据调用结果设置最合适的代码。

当前代码示例

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;

    }

即使有针对抛出异常类型的特定捕获块,我仍然会回来

Fatal error: Uncaught exception 'Guzzle\Http\Exception\ClientErrorResponseException' with message 'Client error response [status code] 401 [reason phrase] Unauthorized [url]

并且页面上的所有执行都将停止,如您所料。BadResponseException catch的添加使我能够正确捕获404,但这似乎不适用于500或401响应。任何人都可以建议我哪里出错了。


答案 1

根据您的项目,可能需要禁用 guzzle 的异常。有时,编码规则不允许流控制的异常。您可以禁用 Guzzle 3 的例外,如下所示:

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

这不会禁用超时等内容的 curl 异常,但现在您可以轻松获取每个状态代码:

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

要检查,如果您获得了有效的代码,则可以使用如下内容:

if ($statuscode > 300) {
  // Do some error handling
}

...或者更好地处理所有预期的代码:

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...");
}

对于咕噜咕噜 5.3

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

感谢@mika

对于咕噜咕噜 6

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

答案 2

要捕获Guzzle错误,您可以执行如下操作:

try {
    $response = $client->get('/not_found.xml')->send();
} catch (Guzzle\Http\Exception\BadResponseException $e) {
    echo 'Uh oh! ' . $e->getMessage();
}

...但是,为了能够“记录”或“重新发送”您的请求,请尝试如下操作:

// 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();
        }

});

...或者,如果要“停止事件传播”,可以覆盖事件侦听器(优先级高于 -255),只需停止事件传播即可。

$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();
    }
});

这是防止诸如此类的口臭错误的好主意:

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

在您的应用程序中。


推荐