php 从 Guzzle 捕获异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17658283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Catching exceptions from Guzzle
提问by Eric
I'm trying to catch exceptions from a set of tests I'm running on an API I'm developing and I'm using Guzzle to consume the API methods. I've got the tests wrapped in a try/catch block but it is still throwing unhandled exception errors. Adding an event listener as described in their docs doesn't seem to do anything. I need to be able to retrieve the responses that have HTTP codes of 500, 401, 400, in fact anything that isn't 200 as the system will set the most appropriate code based on the result of the call if it didn't work.
我正在尝试从我正在开发的 API 上运行的一组测试中捕获异常,并且我正在使用 Guzzle 来使用 API 方法。我已经将测试包装在 try/catch 块中,但它仍然抛出未处理的异常错误。按照他们的文档中的描述添加事件侦听器似乎没有任何作用。我需要能够检索 HTTP 代码为 500、401、400 的响应,实际上任何不是 200 的响应,因为如果它不起作用,系统将根据调用结果设置最合适的代码.
Current code example
当前代码示例
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;
}
Even with the specific catch block for the thrown exception type I am still getting back
即使对于抛出的异常类型有特定的 catch 块,我仍然会回来
Fatal error: Uncaught exception 'Guzzle\Http\Exception\ClientErrorResponseException' with message 'Client error response [status code] 401 [reason phrase] Unauthorized [url]
and all execution on the page stops, as you'd expect. The addition of the BadResponseException catch allowed me to catch 404s correctly, but this doesn't seem to work for 500 or 401 responses. Can anyone suggest where I am going wrong please.
正如您所期望的那样,页面上的所有执行都会停止。BadResponseException 捕获的添加使我能够正确捕获 404,但这似乎不适用于 500 或 401 响应。任何人都可以建议我哪里出错了。
采纳答案by dmmd
If the Exception is being thrown in that try
block then at worst case scenario Exception
should be catching anything uncaught.
如果在该try
块中抛出异常,那么在最坏的情况下Exception
应该捕获任何未捕获的东西。
Consider that the first part of the test is throwing the Exception and wrap that in the try
block as well.
考虑到测试的第一部分是抛出异常并将其包装在try
块中。
回答by Trendfischer
Depending on your project, disabling exceptions for guzzle might be necessary. Sometimes coding rules disallow exceptions for flow control. You can disable exceptions for Guzzle 3like this:
根据您的项目,可能需要禁用 guzzle 异常。有时编码规则不允许流控制的异常。您可以像这样禁用Guzzle 3 的异常:
$client = new \Guzzle\Http\Client($httpBase, array(
'request.options' => array(
'exceptions' => false,
)
));
This does not disable curl exceptions for something like timeouts, but now you can get every status code easily:
这不会禁用诸如超时之类的 curl 异常,但现在您可以轻松获取每个状态代码:
$request = $client->get($uri);
$response = $request->send();
$statuscode = $response->getStatusCode();
To check, if you got a valid code, you can use something like this:
要检查,如果你有一个有效的代码,你可以使用这样的东西:
if ($statuscode > 300) {
// Do some error handling
}
... or better handle all expected codes:
...或更好地处理所有预期的代码:
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...");
}
For Guzzle 5.3
对于狂饮 5.3
$client = new \GuzzleHttp\Client(['defaults' => [ 'exceptions' => false ]] );
Thanks to @mika
感谢@mika
For Guzzle 6
对于狂饮 6
$client = new \GuzzleHttp\Client(['http_errors' => false]);
回答by Dado
To catch Guzzle errors you can do something like this:
要捕获 Guzzle 错误,您可以执行以下操作:
try {
$response = $client->get('/not_found.xml')->send();
} catch (Guzzle\Http\Exception\BadResponseException $e) {
echo 'Uh oh! ' . $e->getMessage();
}
... but, to be able to "log" or "resend" your request try something like this:
...但是,为了能够“记录”或“重新发送”您的请求,请尝试以下操作:
// 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();
}
});
... or if you want to "stop event propagation" you can overridde event listener (with a higher priority than -255) and simply stop event propagation.
...或者如果您想“停止事件传播”,您可以覆盖事件侦听器(优先级高于 -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();
}
});
thats a good idea to prevent guzzle errors like:
这是一个好主意,以防止大量错误,例如:
request.CRITICAL: Uncaught PHP Exception Guzzle\Http\Exception\ClientErrorResponseException: "Client error response
in your application.
在您的应用程序中。
回答by dmmd
In my case I was throwing Exception
on a namespaced file, so php tried to catch My\Namespace\Exception
therefore not catching any exceptions at all.
在我的情况下,我抛出Exception
了一个命名空间文件,所以 php 试图捕获My\Namespace\Exception
因此根本没有捕获任何异常。
Worth checking if catch (Exception $e)
is finding the right Exception
class.
值得检查是否catch (Exception $e)
找到了合适的Exception
课程。
Just try catch (\Exception $e)
(with that \
there) and see if it works.
只需尝试catch (\Exception $e)
(在\
那里),看看它是否有效。
回答by andr3s2
You need to add a extra parameter with http_errors => false
您需要使用 http_errors => false 添加一个额外的参数
$request = $client->get($url, ['http_errors' => false]);
回答by Carson Reinke
Old question, but Guzzle adds the response within the exception object. So a simple try-catch on GuzzleHttp\Exception\ClientException
and then using getResponse
on that exception to see what 400-level error and continuing from there.
老问题,但 Guzzle 在异常对象中添加了响应。所以一个简单的 try-catch onGuzzleHttp\Exception\ClientException
然后使用getResponse
该异常来查看什么 400 级错误并从那里继续。
回答by Ivan Yarych
I was catching GuzzleHttp\Exception\BadResponseException
as @dado is suggesting. But one day I got GuzzleHttp\Exception\ConnectException
when DNS for domain wasn't available.
So my suggestion is - catch GuzzleHttp\Exception\ConnectException
to be safe about DNS errors as well.
GuzzleHttp\Exception\BadResponseException
正如@dado 所建议的那样,我正在赶上。但有一天,GuzzleHttp\Exception\ConnectException
当域的 DNS 不可用时,我得到了。所以我的建议是 - 抓住GuzzleHttp\Exception\ConnectException
DNS 错误也是安全的。