The question was:
I would like to handle errors from Guzzle when the server returns 4xx and 5xx status codes
While you can handle 4xx or 5xx status codes specifically, in practice it makes sense to catch all exceptions and handle the results accordingly.
The question is also, whether you just want to handle the errors or get the body? I think in most cases it would be sufficient to handle the errors and not get the message body or only get the body in the case of a non-error.
I would look at the documentation to check how your version of Guzzle handles it because this may change: https://docs.guzzlephp.org/en/stable/quickstart.html#exceptions
Also see this page in the official documentation on "Working with errors", which states:
Requests that receive a 4xx or 5xx response will throw a Guzzle\Http\Exception\BadResponseException
. More specifically, 4xx errors throw a Guzzle\Http\Exception\ClientErrorResponseException
, and 5xx errors throw a Guzzle\Http\Exception\ServerErrorResponseException
. You can catch the specific exceptions or just catch the BadResponseException
to deal with either type of error.
Guzzle 7 (from the docs):
. \RuntimeException
└── TransferException (implements GuzzleException)
└── RequestException
├── BadResponseException
│ ├── ServerException
│ └── ClientException
├── ConnectException
└── TooManyRedirectsException
So, your code might look like this:
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
}
If you really need the body, you can retrieve it as usual:
https://docs.guzzlephp.org/en/stable/quickstart.html#using-responses
$body = $response->getBody();