サーバーが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
は、HTTP応答の本文ではなくコード情報を返します。応答本文を取得するにはどうすればよいですか?
ドキュメント ごとに、適切な例外タイプ(4xxエラーの場合はClientErrorResponseException
)をキャッチし、そのgetResponse()
メソッドを呼び出して応答オブジェクトを取得し、その上でgetBody()
を呼び出します。
use Guzzle\Http\Exception\ClientErrorResponseException;
...
try {
$response = $request->send();
} catch (ClientErrorResponseException $exception) {
$responseBody = $exception->getResponse()->getBody(true);
}
true
を getBody
関数に渡すと、応答本文を文字列として取得することを示します。それ以外の場合は、Guzzle\Http\EntityBody
クラスのインスタンスとして取得します。
ドキュメント ごとに、キャッチする必要がある例外タイプは次のとおりです。
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();
}
上記の回答は良好ですが、ネットワークエラーは処理しませんが、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);
}
}
2019年の時点で、上記の回答と Guzzle docs から詳しく説明し、例外を処理し、応答本文、ステータスコード、メッセージ、およびその他の重要な応答項目を取得します。
try {
/**
* We use Guzzle to make an HTTP request somewhere in the
* following theMethodMayThrowException().
*/
$result = theMethodMayThorwException();
} 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.
*/
$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. ...
出来上がり。応答の情報は、便利に分離されたアイテムで取得します。
サイドノート:
catch
句を使用すると、Guzzleカスタム例外が拡張するため、継承チェーンPHPルート例外クラス\Exception
をキャッチします。
このアプローチは、GuzzleがLaravelまたはAWS API PHP SDKのように内部で使用されるユースケースに役立ち、真のGuzzle例外をキャッチできません。
この場合、例外クラスはGuzzleのドキュメントに記載されているものではない可能性があります(例:Guzzleのルート例外としてGuzzleHttp\Exception\RequestException
)。
そのため、代わりに\Exception
をキャッチする必要がありますが、それは依然としてGuzzle例外クラスインスタンスであることに注意してください。
注意して使用しますが。これらのラッパーにより、Guzzle $e->getResponse()
オブジェクトの真のメソッドが利用できなくなる場合があります。この場合、Guzzle $response
のメソッドを使用する代わりに、ラッパーの実際の例外ソースコードを調べて、ステータス、メッセージなどを取得する方法を見つける必要があります。
Guzzleを直接自分で呼び出す場合、ユースケース条件に関してGuzzleHttp\Exception\RequestException
または their exceptions docs で言及されている他のいずれかをキャッチできます。