'Why can't I access the response content when the Symfony HTTP Client encounters an error, and an exception is thrown instead?

I want to make a request to retrieve user info from OAUTH server with Symfony HttpClient but I can't fetch fetch the response directly when encountering an error response, because the client throws an exception.

My UserProvider:

    public function loadUserByUsername($username)
    {
        try {
            $response = $this->httpClient->request(
                'GET',
                $this->baseUrl . '/userinfo',
                [
                    'headers' => [
                        'Accept' => 'application/json',
                        'Content-Type' => 'application/json'
                    ],
                    'auth_bearer' => $username
                ]
            );

            var_dump($response->toArray());die;

        } catch (\Exception $e) {
            var_dump($e->getMessage());die;
            throw new UsernameNotFoundException($e->getMessage());
        }
    }

When I call $response->toArray() or $response->getContent(), an exception is thrown and I get the following error message on Postman

<pre class='xdebug-var-dump' dir='ltr'>
<small>/var/www/html/backend/src/Security/Provider/KeycloakUserProvider.php:50:</small><small>string</small> <font color='#cc0000'>'HTTP/2 401  returned for &quot;https://oauth_server/userinfo&quot;.'</font> <i>(length=127)</i>
</pre>

An example of the response received on the browser:

{"error":"invalid_request","error_description":"Token not provided"}

Why can't I access the response directly by calling $response->toArray()?



Solution 1:[1]

Whenever the status code of the response is not "good" (e.g. in the 300-599 range), the response is considered exceptional, and you are supposed to handle it.

This is clearly documented here:

When the HTTP status code of the response is in the 300-599 range (i.e. 3xx, 4xx or 5xx), the getHeaders(), getContent() and toArray() methods throw an appropriate exception, all of which implement the HttpExceptionInterface.

To opt-out from this exception and deal with 300-599 status codes on your own, pass false as the optional argument to every call of those methods, e.g. $response->getHeaders(false);.

If you do not want the client to throw an exception when encountering a non-OK response, you need to pass false to getContent() or toArray().

E.g.

$rawResponse   = $response->getContents(false);
$arrayResponse = $response->toArray(false);

There is nothing wrong in handling the exception explicitly in your code, and will make your application better express the conditions it encounters. A "non-good" should be treated as anomalous, and handled accordingly.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1