当服务器返回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?
}
Run Code Online (Sandbox Code Playgroud)
$e->getMessage返回代码信息,但不返回HTTP响应的主体.我如何获得响应机构?
Mar*_*ery 202
根据文档,您可能需要捕获的异常类型是:
GuzzleHttp\Exception\ClientException 400级错误GuzzleHttp\Exception\ServerException 500级错误GuzzleHttp\Exception\BadResponseException 对于两者(这是他们的超类)因此处理此类错误的代码现在看起来像这样:
$client = new GuzzleHttp\Client;
try {
$client->get('http://google.com/nosuchpage');
}
catch (GuzzleHttp\Exception\ClientException $e) {
$response = $e->getResponse();
$responseBodyAsString = $response->getBody()->getContents();
}
Run Code Online (Sandbox Code Playgroud)
seb*_*bbo 67
根据文档,您可以捕获相应的异常类型(ClientErrorResponseException对于4xx错误)并调用其getResponse()方法来获取响应对象,然后调用getBody():
use Guzzle\Http\Exception\ClientErrorResponseException;
...
try {
$response = $request->send();
} catch (ClientErrorResponseException $exception) {
$responseBody = $exception->getResponse()->getBody(true);
}
Run Code Online (Sandbox Code Playgroud)
传递true给getBody函数表示您希望将响应主体作为字符串.否则你会得到它作为类的实例Guzzle\Http\EntityBody.
cha*_*hap 45
虽然上面的答案是好的,但它们不会处理网络错误,因为Mark提到BadResponseException只是ClientException和ServerException的超类.但RequestException也是BadRequestException的超类.这不仅会捕获400和500错误,还会捕获网络错误.所以,假设您要求下面的页面,但您的网络正在播放,您的捕获期待BadResponseException.那么你的应用程序将抛出错误.
在这种情况下,最好是期望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);
}
}
Run Code Online (Sandbox Code Playgroud)
As of 2019 here is what I elaborated from the answers above and Guzzle docs to handle the exception, get the response body, status code, message and the other sometimes valuable response items.
try {
/**
* We use Guzzle to make an HTTP request somewhere in the
* following theMethodMayThrowException().
*/
$result = theMethodMayThrowException();
} catch (\Exception $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()); // Message
var_dump((string) $response->getBody()); // Body
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. ...
Run Code Online (Sandbox Code Playgroud)
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.
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.
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).
So you have to catch \Exception instead but bear in mind it is still the Guzzle exception class instance.
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.
If you call Guzzle directly yourself you can catch GuzzleHttp\Exception\RequestException or any other one mentioned in their exceptions docs with respect to your use case conditions.
该异常应该是具有 getResponse 方法的 BadResponseException 实例。然后,您可以将响应正文转换为字符串。参考: https: //github.com/guzzle/guzzle/issues/1105
use GuzzleHttp\Exception\BadResponseException;
$url = $this->baseUrl . "subnet?section=$section";
try {
$response = $this->client->get($url);
$subnets = json_decode($response->getBody(), true);
return $subnets['subnets'];
} catch (BadResponseException $ex) {
$response = $ex->getResponse();
$jsonBody = (string) $response->getBody();
// do something with json string...
}
Run Code Online (Sandbox Code Playgroud)
小智 5
上述响应均不适用于没有正文但仍有一些描述文本的错误。对我来说,这是SSL certificate problem: unable to get local issuer certificate错误。所以我直接查看了代码,因为 doc 并没有说太多,并且做了这个(在Guzzle 7.1中):
try {
// call here
} catch (\GuzzleHttp\Exception\RequestException $e) {
if ($e->hasResponse()) {
$response = $e->getResponse();
// message is in $response->getReasonPhrase()
} else {
$response = $e->getHandlerContext();
if (isset($response['error'])) {
// message is in $response['error']
} else {
// Unknown error occured!
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是:
当服务器返回 4xx 和 5xx 状态代码时,我想处理 Guzzle 的错误
虽然您可以专门处理 4xx 或 5xx 状态代码,但实际上捕获所有异常并相应地处理结果是有意义的。
问题还在于,您是否只想处理错误或获取正文?我认为在大多数情况下,处理错误而不获取消息正文或仅在非错误的情况下获取正文就足够了。
我会查看文档以检查您的 Guzzle 版本如何处理它,因为这可能会改变:https ://docs.guzzlephp.org/en/stable/quickstart.html#exceptions
另请参阅有关“处理错误”的官方文档中的此页面,其中指出:
收到 4xx 或 5xx 响应的请求将抛出一个
Guzzle\Http\Exception\BadResponseException. 更具体地说,4xx错误会抛出 aGuzzle\Http\Exception\ClientErrorResponseException,而5xx错误会抛出 Guzzle\Http\Exception\ServerErrorResponseException。您可以捕获特定的异常,也可以只捕获BadResponseException以处理任一类型的错误。
Guzzle 7(来自文档):
. \RuntimeException
??? TransferException (implements GuzzleException)
??? RequestException
??? BadResponseException
? ??? ServerException
? ??? ClientException
??? ConnectException
??? TooManyRedirectsException
Run Code Online (Sandbox Code Playgroud)
因此,您的代码可能如下所示:
try {
$response = $client->request('GET', $url);
if ($response->getStatusCode() >= 300) {
// is HTTP status code (for non-exceptions)
$statusCode = $response->getStatusCode();
// handle error
} else {
// is valid URL
}
} catch (TooManyRedirectsException $e) {
// handle too many redirects
} catch (ClientException | ServerException $e) {
// ClientException - A GuzzleHttp\Exception\ClientException is thrown for 400 level errors if the http_errors request option is set to true.
// ServerException - A GuzzleHttp\Exception\ServerException is thrown for 500 level errors if the http_errors request option is set to true.
if ($e->hasResponse()) {
// is HTTP status code, e.g. 500
$statusCode = $e->getResponse()->getStatusCode();
}
} catch (ConnectException $e) {
// ConnectException - A GuzzleHttp\Exception\ConnectException exception is thrown in the event of a networking error. This may be any libcurl error, including certificate problems
$handlerContext = $e->getHandlerContext();
if ($handlerContext['errno'] ?? 0) {
// this is the libcurl error code, not the HTTP status code!!!
// for example 6 for "Couldn't resolve host"
$errno = (int)($handlerContext['errno']);
}
// get a description of the error (which will include a link to libcurl page)
$errorMessage = $handlerContext['error'] ?? $e->getMessage();
} catch (\Exception $e) {
// fallback, in case of other exception
}
Run Code Online (Sandbox Code Playgroud)
如果你真的需要尸体,你可以像往常一样取回它:
https://docs.guzzlephp.org/en/stable/quickstart.html#using-responses
$body = $response->getBody();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
107253 次 |
| 最近记录: |