php 处理 Guzzle 异常并获取 HTTP 正文
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19748105/
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
Handle Guzzle exception and get HTTP body
提问by domos
I would like to handle errors from Guzzle when the server returns 4xx and 5xx status codes. I make a request like this:
当服务器返回 4xx 和 5xx 状态代码时,我想处理来自 Guzzle 的错误。我提出这样的要求:
$client = $this->getGuzzleClient();
$request = $client->post($url, $headers, $value);
try {
$response = $request->send();
return $response->getBody();
} catch (\Exception $e) {
// How can I get the response body?
}
$e->getMessage
returns code info but not the body of the HTTP response. How can I get the response body?
$e->getMessage
返回代码信息,但不返回 HTTP 响应的正文。我怎样才能得到响应体?
采纳答案by sebbo
Guzzle 3.x
狂饮3.x
Per the docs, you can catch the appropriate exception type (ClientErrorResponseException
for 4xx errors) and call its getResponse()
method to get the response object, then call getBody()
on that:
根据docs,您可以捕获适当的异常类型(ClientErrorResponseException
对于 4xx 错误)并调用其getResponse()
方法来获取响应对象,然后调用getBody()
它:
use Guzzle\Http\Exception\ClientErrorResponseException;
...
try {
$response = $request->send();
} catch (ClientErrorResponseException $exception) {
$responseBody = $exception->getResponse()->getBody(true);
}
Passing true
to the getBody
function indicates that you want to get the response body as a string. Otherwise you will get it as instance of class Guzzle\Http\EntityBody
.
传递true
给该getBody
函数表示您希望以字符串形式获取响应正文。否则你会得到它作为 class 的实例Guzzle\Http\EntityBody
。
回答by Mark Amery
Guzzle 6.x
狂饮6.x
Per the docs, the exception types you may need to catch are:
根据docs,您可能需要捕获的异常类型是:
GuzzleHttp\Exception\ClientException
for 400-level errorsGuzzleHttp\Exception\ServerException
for 500-level errorsGuzzleHttp\Exception\BadResponseException
for both (it's their superclass)
GuzzleHttp\Exception\ClientException
对于 400 级错误GuzzleHttp\Exception\ServerException
对于 500 级错误GuzzleHttp\Exception\BadResponseException
对于两者(这是他们的超类)
Code to handle such errors thus now looks something like this:
处理此类错误的代码现在看起来像这样:
$client = new GuzzleHttp\Client;
try {
$client->get('http://google.com/nosuchpage');
}
catch (GuzzleHttp\Exception\ClientException $e) {
$response = $e->getResponse();
$responseBodyAsString = $response->getBody()->getContents();
}
回答by chap
While the answers above are good they will not catch network errors. As Mark mentioned, BadResponseException is just a super class for ClientException and ServerException. But RequestException is also a super class of BadResponseException. RequestException will be thrown for not only 400 and 500 errors but network errors and infinite redirects too. So let's say you request the page below but your network is playing up and your catch is only expecting a BadResponseException. Well your application will throw an error.
虽然上面的答案很好,但它们不会捕获网络错误。正如 Mark 所提到的,BadResponseException 只是 ClientException 和 ServerException 的超类。但 RequestException 也是 BadResponseException 的超类。RequestException 不仅会因 400 和 500 错误而引发,还会因网络错误和无限重定向而引发。因此,假设您请求下面的页面,但您的网络正在运行,而您的捕获只期待 BadResponseException。那么你的应用程序会抛出一个错误。
It's better in this case to expect RequestException and check for a response.
在这种情况下,最好期待 RequestException 并检查响应。
try {
$client->get('http://123123123.com')
} catch (RequestException $e) {
// If there are network errors, we need to ensure the application doesn't crash.
// if $e->hasResponse is not null we can attempt to get the message
// Otherwise, we'll just pass a network unavailable message.
if ($e->hasResponse()) {
$exception = (string) $e->getResponse()->getBody();
$exception = json_decode($exception);
return new JsonResponse($exception, $e->getCode());
} else {
return new JsonResponse($e->getMessage(), 503);
}
}
回答by Valentine Shi
As of 2019 here is what I elaborated from the answers above and Guzzle docsto handle the exception, get the response body, status code, message and the other sometimes valuable response items.
截至 2019 年,这里是我从上面的答案和Guzzle 文档中阐述的用于处理异常、获取响应正文、状态代码、消息和其他有时有价值的响应项目的内容。
try {
/**
* We use Guzzle to make an HTTP request somewhere in the
* following theMethodMayThrowException().
*/
$result = theMethodMayThrowException();
} catch (\GuzzleHttp\Exception\RequestException $e) {
/**
* Here we actually catch the instance of GuzzleHttp\Psr7\Response
* (find it in ./vendor/guzzlehttp/psr7/src/Response.php) with all
* its own and its 'Message' trait's methods. See more explanations below.
*
* So you can have: HTTP status code, message, headers and body.
* Just check the exception object has the response before.
*/
if ($e->hasResponse()) {
$response = $e->getResponse();
var_dump($response->getStatusCode()); // HTTP status code;
var_dump($response->getReasonPhrase()); // Response message;
var_dump((string) $response->getBody()); // Body, normally it is JSON;
var_dump(json_decode((string) $response->getBody())); // Body as the decoded JSON;
var_dump($response->getHeaders()); // Headers array;
var_dump($response->hasHeader('Content-Type')); // Is the header presented?
var_dump($response->getHeader('Content-Type')[0]); // Concrete header value;
}
}
// process $result etc. ...
Voila. You get the response's information in conveniently separated items.
瞧。您可以在方便的分隔项中获取响应信息。
Side Notes:
旁注:
With catch
clause we catch the inheritance chain PHP root exception class
\Exception
as Guzzle custom exceptions extend it.
Withcatch
子句,我们捕获继承链 PHP 根异常类,
\Exception
因为 Guzzle 自定义异常扩展了它。
This approach may be useful for use cases where Guzzle is used under the hood like in Laravel or AWS API PHP SDK so you cannot catch the genuine Guzzle exception.
这种方法可能适用于在 Laravel 或 AWS API PHP SDK 等引擎盖下使用 Guzzle 的用例,因此您无法捕获真正的 Guzzle 异常。
In this case, the exception class may not be the one mentioned in the Guzzle docs (e.g. GuzzleHttp\Exception\RequestException
as the root exception for Guzzle).
在这种情况下,异常类可能不是 Guzzle 文档中提到的类(例如GuzzleHttp\Exception\RequestException
作为 Guzzle 的根异常)。
So you have to catch \Exception
instead but bear in mind it is still the Guzzle exception class instance.
因此,您必须改为捕获,\Exception
但请记住,它仍然是 Guzzle 异常类实例。
Though use with care. Those wrappers may make Guzzle $e->getResponse()
object's genuine methods not available. In this case, you will have to look at the wrapper's actual exception source code and find out how to get status, message, etc. instead of using Guzzle $response
's methods.
虽然要小心使用。这些包装器可能会使 Guzzle$e->getResponse()
对象的真正方法不可用。在这种情况下,您将不得不查看包装器的实际异常源代码并找出如何获取状态、消息等,而不是使用 Guzzle$response
的方法。
If you call Guzzle directly yourself you can catch GuzzleHttp\Exception\RequestException
or any other one mentioned in their exceptions docswith respect to your use case conditions.
如果您自己直接调用 Guzzle,您可以捕获GuzzleHttp\Exception\RequestException
或在他们的异常文档中提到的关于您的用例条件的任何其他人。
回答by user8487819
if put 'http_errors' => false
in guzzle request options, then it would stop throw exception while get 4xx or 5xx error, like this: $client->get(url, ['http_errors' => false])
. then you parse the response, not matter it's ok or error, it would be in the response
for more info
要是搁'http_errors' => false
在狂饮请求选项,那么它将停止抛出异常而获取4XX或5XX错误,像这样:$client->get(url, ['http_errors' => false])
。然后你解析响应,不管它是好的还是错误,它都会在响应中
获取更多信息