Обрабатывать исключение Guzzle и получать HTTP-теги
Я хотел бы обрабатывать ошибки от Guzzle, когда сервер возвращает коды состояния 4xx и 5xx. Я делаю запрос следующим образом:
$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. Как я могу получить тело ответа?
Ответы
Ответ 1
Guzzle 3.x
Per , вы можете поймать соответствующий тип исключения (ClientErrorResponseException
для ошибок 4xx) и вызвать его метод getResponse()
для получения объекта ответа, затем вызовите getBody()
на этом:
use Guzzle\Http\Exception\ClientErrorResponseException;
...
try {
$response = $request->send();
} catch (ClientErrorResponseException $exception) {
$responseBody = $exception->getResponse()->getBody(true);
}
Передача true
в функцию getBody
означает, что вы хотите получить тело ответа как строку. В противном случае вы получите его как экземпляр класса Guzzle\Http\EntityBody
.
Ответ 2
Guzzle 6.x
Per docs, типы исключений, которые могут вам понадобиться, следующие:
-
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();
}
Ответ 3
В то время как ответы выше хорошо, они не будут иметь дело с сетевыми ошибками, поскольку 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);
}
}
Ответ 4
Начиная с 2019 года, вот что я разработал из приведенных выше ответов и документов Guzzle для обработки исключения, получения тела ответа, кода состояния, сообщения и других, иногда полезных, элементов ответа.
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 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. ...
Voila. Вы получаете ответную информацию в удобно разделенных пунктах.
Примечания стороны:
С помощью предложения catch
мы перехватываем класс исключений корневого исключения PHP-цепочки
\Exception
, как расширяют его пользовательские исключения в Guzzle.
Этот подход может быть полезен в тех случаях, когда Guzzle используется под капотом, как в Laravel или AWS API PHP SDK, поэтому вы не можете поймать подлинное исключение Guzzle.
В этом случае класс исключений может не совпадать с классом, упомянутым в документации по Guzzle (например, GuzzleHttp\Exception\RequestException
как корневое исключение для Guzzle).
Поэтому вы должны поймать \Exception
, но помните, что это все еще экземпляр класса исключений Guzzle.
Хотя используйте с осторожностью. Эти оболочки могут сделать подлинные методы объекта Guzzle $e->getResponse()
недоступными. В этом случае вам придется взглянуть на фактический исходный код оболочки и выяснить, как получить статус, сообщение и т.д. Вместо использования методов Guzzle $response
.
Если вы сами позвоните в Guzzle, вы можете поймать GuzzleHttp\Exception\RequestException
или любого другого, упомянутого в их документах об исключениях, в отношении условий использования.