我正在尝试从我正在开发的API上运行的一组测试中捕获异常,并且我使用Guzzle来使用API方法。我已经将测试包装在try / catch块中,但它仍然会抛出未处理的异常错误。按照文档中的描述添加事件侦听器似乎没有做任何事情。我需要能够检索具有500,401,400的HTTP代码的响应,实际上任何不是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;
}
即使使用抛出的异常类型的特定catch块,我仍然会回来
Fatal error: Uncaught exception 'Guzzle\Http\Exception\ClientErrorResponseException' with message 'Client error response [status code] 401 [reason phrase] Unauthorized [url]
并且页面上的所有执行都会停止,正如您所期望的那样。添加BadResponseException捕获允许我正确捕获404,但这似乎不适用于500或401响应。任何人都可以建议我哪里出错了。
答案 0 :(得分:105)
根据您的项目,可能需要禁用guzzle的例外情况。有时编码规则不允许流控制的异常。你可以禁用例如 for Guzzle 3 :
$client = new \Guzzle\Http\Client($httpBase, array(
'request.options' => array(
'exceptions' => false,
)
));
这不会禁用超时之类的卷曲异常,但现在您可以轻松获取每个状态代码:
$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...");
}
对于Guzzle 5.3
$client = new \GuzzleHttp\Client(['defaults' => [ 'exceptions' => false ]] );
感谢@mika
Guzzle 6
$client = new \GuzzleHttp\Client(['http_errors' => false]);
答案 1 :(得分:44)
要捕捉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();
}
});
这是一个好主意,可以防止像guzzle错误:
request.CRITICAL: Uncaught PHP Exception Guzzle\Http\Exception\ClientErrorResponseException: "Client error response
在您的申请中。
答案 2 :(得分:28)
在我的情况下,我在命名空间文件上抛出Exception
,因此php试图捕获My\Namespace\Exception
因此根本没有捕获任何异常。
值得检查catch (Exception $e)
是否找到了正确的Exception
课程。
只需尝试catch (\Exception $e)
(那里有\
),看看它是否有效。
答案 3 :(得分:13)
如果在try
块中抛出了异常,那么在最坏的情况下,Exception
应捕获任何未捕获的内容。
考虑测试的第一部分是抛出异常并将其包装在try
块中。
答案 4 :(得分:10)
您需要使用http_errors =>添加额外参数假
$request = $client->get($url, ['http_errors' => false]);
答案 5 :(得分:5)
旧问题,但Guzzle在异常对象中添加了响应。所以GuzzleHttp\Exception\ClientException
上的一个简单的try-catch然后在该异常上使用getResponse
来查看400级错误并从那里继续。
答案 6 :(得分:2)
正如@dado建议的那样,我抓住了GuzzleHttp\Exception\BadResponseException
。但有一天,当域名DNS不可用时,我得到了GuzzleHttp\Exception\ConnectException
。
所以我的建议是 - 抓住GuzzleHttp\Exception\ConnectException
以确保DNS错误的安全。
答案 7 :(得分:1)
我想更新Psr-7 Guzzle,Guzzle7和HTTPClient(laravel提供的Guzzle HTTP客户端周围的表达,最小的API)中异常处理的答案。
使用RequestException ,RequestException捕获在传输请求时可能引发的任何异常。
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
}
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]);
}
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
}
答案 8 :(得分:-1)
.items-holder
{
background-color: #E7E7E7;
border-radius: 4px;
padding: 10px;
display: inline-block;
border-collapse: separate;
border-spacing: 10px 0px;
vertical-align:middle;
}